diff --git a/cfssl/cfssl.py b/cfssl/cfssl.py index afb67f6..7ac9c35 100644 --- a/cfssl/cfssl.py +++ b/cfssl/cfssl.py @@ -24,12 +24,12 @@ def auth_sign(self, token, request, datetime=None, remote_address=None): """ It provides returns a signed certificate. Args: - token: (str) The authentication token. - request: (cfssl.CertificateRequest) Signing request document. - datetime: (datetime.datetime) Authentication timestamp. - remote_address: (str) An address used in making the request. + token (:obj:`str`): The authentication token. + request (:obj:`cfssl.CertificateRequest`): Signing request document. + datetime (:obj:`datetime.datetime`): Authentication timestamp. + remote_address (:obj:`str`): An address used in making the request. Returns: - (str) A PEM-encoded certificate that has been signed by the + (:obj:`str`) A PEM-encoded certificate that has been signed by the server. """ data = self._clean_mapping({ @@ -45,34 +45,34 @@ def bundle(self, certificate, private_key=None, """ It builds and returns certificate bundles. Args: - certificate: (str) The PEM-encoded certificate to be bundled. + certificate (:obj:`str`): The PEM-encoded certificate to be bundled. If the ``certificate`` parameter is present, the following four arguments are valid: - private_key: (str) The PEM-encoded private key to be included with + private_key (:obj:`str`): The PEM-encoded private key to be included with the bundle. This is valid only if the server is not running in ``keyless`` mode. - flavor: (str) One of ``ubiquitous``, ``force``, or ``optimal``, + flavor (:obj:`str`): One of ``ubiquitous``, ``force``, or ``optimal``, with a default value of ``ubiquitous``. A ubiquitous bundle is one that has a higher probability of being verified everywhere, even by clients using outdated or unusual trust stores. Force will cause the endpoint to use the bundle provided in the ``certificate`` parameter, and will only verify that the bundle is a valid (verifiable) chain. - domain: (str) The domain name to verify as the hostname of the + domain (:obj:`str`): The domain name to verify as the hostname of the certificate. - ip: (str) The IP address to verify against the certificate IP + ip (:obj:`str`): The IP address to verify against the certificate IP SANs. If only the ``domain`` parameter is present, the following parameter is valid: - ip: (str) The IP address of the remote host; this will fetch the + ip (:obj:`str`): The IP address of the remote host; this will fetch the certificate from the IP, and verify that it is valid for the domain name. Returns: - (dict) Object repesenting the bundle, with the following keys: + (:obj:`dict`) Object repesenting the bundle, with the following keys: * bundle contains the concatenated list of PEM certificates forming the certificate chain; this forms the actual bundle. The remaining parameters are additional metadata @@ -99,33 +99,33 @@ def bundle(self, certificate, private_key=None, certificate, e.g. 'SHA1WithRSA'. * status contains a number of elements: * code is bit-encoded error code. 1st bit indicates whether - there is a expiring certificate in the bundle. 2nd bit indicates - whether there is a ubiquity issue with the bundle. + there is a expiring certificate in the bundle. 2nd bit indicates + whether there is a ubiquity issue with the bundle. * expiring_SKIs contains the SKIs (subject key identifiers) - for any certificates that might expire soon (within 30 - days). + for any certificates that might expire soon (within 30 + days). * messages is a list of human-readable warnings on bundle - ubiquity and certificate expiration. For example, an expiration - warning can be "The expiring cert is #1 in the chain", - indicating the leaf certificate is expiring. Ubiquity warnings - include SHA-1 deprecation warning (if the bundle triggers - any major browser's SHA-1 deprecation policy), SHA-2 - compatibility warning (if the bundle contains signatures using - ECDSA SHA-2 hash algorithms, it will be rejected by Windows XP - SP2), compatibility warning (if the bundle contains ECDSA - certificates, it will be rejected by Windows XP, Android 2.2 and - Android 2.3 etc) and root trust warning (if the bundle cannot be - trusted by some major OSes or browsers). + ubiquity and certificate expiration. For example, an expiration + warning can be "The expiring cert is #1 in the chain", + indicating the leaf certificate is expiring. Ubiquity warnings + include SHA-1 deprecation warning (if the bundle triggers + any major browser's SHA-1 deprecation policy), SHA-2 + compatibility warning (if the bundle contains signatures using + ECDSA SHA-2 hash algorithms, it will be rejected by Windows XP + SP2), compatibility warning (if the bundle contains ECDSA + certificates, it will be rejected by Windows XP, Android 2.2 and + Android 2.3 etc) and root trust warning (if the bundle cannot be + trusted by some major OSes or browsers). * rebundled indicates whether the server had to rebundle the - certificate. The server will rebundle the uploaded - certificate as needed; for example, if the certificate - contains none of the required intermediates or a better set - of intermediates was found. In this case, the server will - mark rebundled as true. + certificate. The server will rebundle the uploaded + certificate as needed; for example, if the certificate + contains none of the required intermediates or a better set + of intermediates was found. In this case, the server will + mark rebundled as true. * untrusted_root_stores contains the names of any major - OSes and browsers that doesn't trust the bundle. The names - are used to construct the root trust warnings in the messages - list + OSes and browsers that doesn't trust the bundle. The names + are used to construct the root trust warnings in the messages + list * subject contains the X.509 subject identifier from the certificate. """ @@ -142,16 +142,16 @@ def info(self, label, profile=None): """ It returns information about the CA, including the cert. Args: - label: (str) A string specifying the signer. - profile: (str) a string specifying the signing profile for the + label (:obj:`str`): A string specifying the signer. + profile (:obj:`str`): a string specifying the signing profile for the signer. Signing profile specifies what key usages should be used and how long the expiry should be set. Returns: - (dict) Mapping with three keys: - * certificate: (str) a PEM-encoded certificate of the signer. - * usage: (list) a string array of key usages from the signing + (:obj:`dict`) Mapping with three keys: + * certificate (:obj:`str`): a PEM-encoded certificate of the signer. + * usage (:obj:`list` of :obj:`str`): Key usages from the signing profile. - * expiry: (str) the expiry string from the signing profile. + * expiry (:obj:`str`): the expiry string from the signing profile. """ data = self._clean_mapping({ 'label': label, @@ -163,19 +163,19 @@ def init_ca(self, hosts, names, common_name=None, key=None, ca=None): """ It initializes a new certificate authority. Args: - hosts: (iter of cfssl.Host) Subject Alternative Name(s) for the + hosts (:obj:`iter` of :obj:`cfssl.Host`): Subject Alternative Name(s) for the requested CA certificate. - names: (iter of cfssl.SubjectInfo) The Subject Info(s) for the + names (:obj:`iter` of :obj:`cfssl.SubjectInfo`): The Subject Info(s) for the requested CA certificate. - common_name: (str) the common name for the certificate subject in + common_name (:obj:`str`): the common name for the certificate subject in the requested CA certificate. - key: (cfssl.ConfigKey) Cipher and strength to use for certificate. - ca: (cfssl.ConfigServer) the CA configuration of the requested CA, + key (:obj:`cfssl.ConfigKey`): Cipher and strength to use for certificate. + ca (:obj:`cfssl.ConfigServer`): the CA configuration of the requested CA, including CA pathlen and CA default expiry. Returns: - (dict) Mapping with two keys: - * private key: (str) a PEM-encoded CA private key. - * certificate: (str) a PEM-encoded self-signed CA certificate. + (:obj:`dict`) Mapping with two keys: + * private key (:obj:`str`): a PEM-encoded CA private key. + * certificate (:obj:`str`): a PEM-encoded self-signed CA certificate. """ key = key or ConfigKey() data = self._clean_mapping({ @@ -186,7 +186,7 @@ def init_ca(self, hosts, names, common_name=None, key=None, ca=None): name.to_api() for name in names ], 'CN': common_name, - 'key': key.to_api(), + 'key': key and key.to_api() or ConfigKey().to_api(), 'ca': ca and ca.to_api() or None, }) return self.call('init_ca', 'POST', data=data) @@ -195,20 +195,19 @@ def new_key(self, hosts, names, common_name=None, key=None, ca=None): """ It generates and returns a new private key + CSR. Args: - hosts: (iter of cfssl.Host) Subject Alternative Name(s) for the + hosts (:obj:`iter` of :obj:`cfssl.Host`): Subject Alternative Name(s) for the requested certificate. - names: (iter of cfssl.SubjectInfo) The Subject Info(s) for the + names (:obj:`iter` of :obj:`cfssl.SubjectInfo`): The Subject Info(s) for the requested certificate. - CN: (str) the common name for the certificate subject in the + CN (:obj:`str`): the common name for the certificate subject in the requestedrequested CA certificate. - key: (cfssl.ConfigKey) Cipher and strength to use for certificate. - ca: the CA configuration of the requested CA, including CA pathlen - and CA default expiry. + key (:obj:`cfssl.ConfigKey`): Cipher and strength to use for certificate. + ca (:obj:`cfssl.ConfigServer`): the CA configuration of the requested CA. Returns: - (dict) Mapping with three keys: - * private key: (str) a PEM-encoded CA private key. - * certificate: (str) a PEM-encoded self-signed CA certificate. - * sums: (dict) Mapping holding both MD5 and SHA1 digests for the + (:obj:`dict`) Mapping with three keys: + * private key (:obj:`str`): a PEM-encoded CA private key. + * certificate (:obj:`str`): a PEM-encoded self-signed CA certificate. + * sums: (:obj:`dict`) Mapping holding both MD5 and SHA1 digests for the certificate request """ data = self._clean_mapping({ @@ -219,8 +218,8 @@ def new_key(self, hosts, names, common_name=None, key=None, ca=None): name.to_api() for name in names ], 'CN': common_name, - 'key': key, - 'ca': ca, + 'key': key and key.to_api() or ConfigKey().to_api(), + 'ca': ca and ca.to_api() or None, }) return self.call('newkey', 'POST', data=data) @@ -228,16 +227,16 @@ def new_cert(self, request, label=None, profile=None, bundle=None): """ It generates and returns a new private key and certificate. Args: - request: (cfssl.CertificateRequest) CSR to be used for + request (:obj:`cfssl.CertificateRequest`): CSR to be used for certificate creation. - label: (str) Specifying which signer to be appointed to sign + label (:obj:`str`): Specifying which signer to be appointed to sign the CSR, useful when interacting with cfssl server that stands in front of a remote multi-root CA signer. - profile: (str) Specifying the signing profile for the signer. - bundle: (bool) Specifying whether to include an "optimal" + profile (:obj:`str`): Specifying the signing profile for the signer. + bundle (:obj:`bool`): Specifying whether to include an "optimal" certificate bundle along with the certificate. Returns: - (dict) mapping with these keys: + (:obj:`dict`) mapping with these keys: * private key: a PEM-encoded private key. * certificate_request: a PEM-encoded certificate request. * certificate: a PEM-encoded certificate, signed by the server. @@ -258,11 +257,11 @@ def revoke(self, serial, authority_key_id, reason): """ It provides certificate revocation. Args: - serial: (str) Specifying the serial number of a certificate. - authority_key_id: (str) Specifying the authority key identifier + serial (:obj:`str`): Specifying the serial number of a certificate. + authority_key_id (:obj:`str`): Specifying the authority key identifier of the certificate to be revoked; this is used to distinguish which private key was used to sign the certificate. - reason: (str) Identifying why the certificate was revoked; see, + reason (:obj:`str`): Identifying why the certificate was revoked; see, for example, ReasonStringToCode in the ocsp package or section 4.2.1.13 of RFC 5280. The "reasons" used here are the ReasonFlag names in said RFC. @@ -278,25 +277,25 @@ def scan(self, host, ip=None, timeout=None, family=None, scanner=None): """ It scans servers to determine the quality of their TLS setup. Args: - host: (cfssl.Host) The host to scan. - ip: (str) IP Address to override DNS lookup of host. - timeout: (str) The amount of time allotted for the scan to complete + host (:obj:`cfssl.Host`): The host to scan. + ip (:obj:`str`): IP Address to override DNS lookup of host. + timeout (:obj:`str`): The amount of time allotted for the scan to complete (default: 1 minute). - family: (str) regular expression specifying scan famil(ies) to run. - scanner: (str) regular expression specifying scanner(s) to run. + family (:obj:`str`): regular expression specifying scan famil(ies) to run. + scanner (:obj:`str`): regular expression specifying scanner(s) to run. Returns: - (dict) Mapping with keys for each scan family. Each of these + (:obj:`dict`) Mapping with keys for each scan family. Each of these objects contains keys for each scanner run in that family pointing to objects possibly containing the following keys: - * grade: (str) Describing the exit status of the scan. Can be: + * grade (:obj:`str`): Describing the exit status of the scan. Can be: * "Good": host performing the expected state-of-the-art. * "Warning": host with non-ideal configuration, possibly maintaining support for legacy clients. * "Bad": host with serious misconfiguration or vulnerability * "Skipped": indicates that the scan was not performed for some reason. - * error: (str) Any error encountered during the scan process. - * output: (dict) Arbitrary data retrieved during the scan. + * error (:obj:`str`): Any error encountered during the scan process. + * output: (:obj:`dict`) Arbitrary data retrieved during the scan. """ data = self._clean_mapping({ 'host': host.to_api(), @@ -311,7 +310,7 @@ def scan_info(self): """ It lists options available for scanning. Returns: - (dict) Mapping with keys for each scan family. For each family, + (:obj:`dict`) Mapping with keys for each scan family. For each family, there exists a `description` containing a string describing the family and a `scanners` object mapping each of the family's scanners to an object containing a `description` string. @@ -323,21 +322,21 @@ def sign(self, certificate_request, hosts=None, subject=None, """ It signs and returns a certificate. Args: - certificate_request: (str) the CSR bytes to be signed (in PEM). - hosts: (iter of cfssl.Host) of SAN (subject alternative .names) + certificate_request (:obj:`str`): the CSR bytes to be signed (in PEM). + hosts (:obj:`iter` of :obj:`cfssl.Host`): of SAN (subject alternative .names) which overrides the ones in the CSR - subject: (str) The certificate subject which overrides + subject (:obj:`str`): The certificate subject which overrides the ones in the CSR. - serial_sequence: (str) Specify the prefix which the generated + serial_sequence (:obj:`str`): Specify the prefix which the generated certificate serial should have. - label: (str) Specifying which signer to be appointed to sign + label (:obj:`str`): Specifying which signer to be appointed to sign the CSR, useful when interacting with a remote multi-root CA signer. - profile: (cfssl.ConfigServer) Specifying the signing profile for + profile (:obj:`cfssl.ConfigServer`): Specifying the signing profile for the signer, useful when interacting with a remote multi-root CA signer. Returns: - (str) A PEM-encoded certificate that has been signed by the + (:obj:`str`) A PEM-encoded certificate that has been signed by the server. """ data = self._clean_mapping({ @@ -357,16 +356,16 @@ def call(self, endpoint, method='GET', params=None, data=None): """ It calls the remote endpoint and returns the result, if success. Args: - endpoint: (str) CFSSL endpoint to call (e.g. ``newcert``). - method: (str) HTTP method to utilize for the Request. + endpoint (:obj:`str`): CFSSL endpoint to call (e.g. ``newcert``). + method (:obj:`str`): HTTP method to utilize for the Request. params: (dict|bytes) Data to be sent in the query string for the Request. - data: (dict|bytes|file) Data to send in the body of the - Request. + data: (:obj:`dict`|:obj:`bytes`|:obj:`file`) Data to send in the body + of the Request. Returns: (mixed) Data contained in ``result`` key of the API response. Raises: - CFSSLRemoteException: In the event of a ``False`` in the + :obj:`CFSSLRemoteException`: In the event of a ``False`` in the ``success`` key of the API response. """ endpoint = '%s/api/v1/cfssl/%s' % (self.uri_base, endpoint) diff --git a/cfssl/defaults.py b/cfssl/defaults.py index dd4db07..846a993 100644 --- a/cfssl/defaults.py +++ b/cfssl/defaults.py @@ -2,6 +2,9 @@ # Copyright 2016 LasLabs Inc. # License MIT (https://opensource.org/licenses/MIT). +from datetime import timedelta + + DEFAULT_ALGORITHM = 'rsa' DEFAULT_STRENGTH = 4096 -DEFAULT_EXPIRE_MINUTES = 365 * 24 * 60 +DEFAULT_EXPIRE_DELTA = timedelta(days=365) diff --git a/cfssl/models/certificate_request.py b/cfssl/models/certificate_request.py index 9ea662c..a5f611a 100644 --- a/cfssl/models/certificate_request.py +++ b/cfssl/models/certificate_request.py @@ -11,6 +11,18 @@ class CertificateRequest(object): """ It provides a Certificate Request compatible with CFSSL. """ def __init__(self, common_name, names=None, hosts=None, key=None): + """ Initialize a new CertificateRequest. + + Args: + common_name (:obj:`str`): The fully qualified domain name for the + server. This must be an exact match. + names (:type:`iter` of :obj:`cfssl.SubjectInfo`, optional): + Subject Information to be added to the request. + hosts (:type:`iter` of :obj:`cfssl.Host`, optional): Hosts + to be added to the request. + key (:obj:`cfssl.ConfigKey`, optional): Key configuration + for the request. + """ self.common_name = common_name self.names = names or [] self.hosts = hosts or [] diff --git a/cfssl/models/config_client.py b/cfssl/models/config_client.py index a3da5b0..6a64b8f 100644 --- a/cfssl/models/config_client.py +++ b/cfssl/models/config_client.py @@ -10,6 +10,18 @@ class ConfigClient(ConfigMixer): def __init__(self, sign_policy_default, sign_policies_add, auth_policies, remotes): + """ Initialize a new Client Configuration. + + Args: + sign_policy_default (:obj:`cfssl.PolicySign`): Default signing + policy for client to use. + sign_policies_add (:type:`iter` of :obj:`cfssl.PolicySign`): + Additional signing policies to use for the client. + auth_policies (:type:`iter` of :obj:`cfssl.PolicyAuth`): Auth + policies for the client. + remotes (:type:`iter` of :obj:`cfssl.Host`): Remote hosts that + client trusts. + """ super(ConfigClient, self).__init__( sign_policy_default, auth_policies, remotes, ) diff --git a/cfssl/models/config_key.py b/cfssl/models/config_key.py index 8767171..de5ca98 100644 --- a/cfssl/models/config_key.py +++ b/cfssl/models/config_key.py @@ -10,6 +10,14 @@ class ConfigKey(object): def __init__(self, algorithm=DEFAULT_ALGORITHM, strength=DEFAULT_STRENGTH): + """ Initialize a new Client Configuration. + + Args: + algorithm (:obj:`str`, optional): Algorithm to use for key, one of + ``rsa`` or ``ecdsa``. Defaults to ``rsa``. + strength (:obj:`int`, optional): Key bit strength. Defaults to + ``4096``. + """ self.algorithm = algorithm self.strength = strength diff --git a/cfssl/models/config_mixer.py b/cfssl/models/config_mixer.py index 625cfed..ffff153 100644 --- a/cfssl/models/config_mixer.py +++ b/cfssl/models/config_mixer.py @@ -7,6 +7,16 @@ class ConfigMixer(object): """ It provides a mixer for the Client and Server Configs """ def __init__(self, sign_policy_default, sign_policies_add, auth_policies): + """ Initialize a new General Configuration for Server or Client. + + Args: + sign_policy_default (:obj:`cfssl.PolicySign`): Default signing + policy for entity to use. + sign_policies_add (:type:`iter` of :obj:`cfssl.PolicySign`): + Additional signing policies to use for the entity. + auth_policies (:type:`iter` of :obj:`cfssl.PolicyAuth`): Auth + policies for the entity. + """ self.sign_policy = sign_policy_default self.sign_policies = sign_policies_add self.auth_policies = auth_policies diff --git a/cfssl/models/host.py b/cfssl/models/host.py index 1091c7c..17eabd7 100644 --- a/cfssl/models/host.py +++ b/cfssl/models/host.py @@ -7,6 +7,14 @@ class Host(object): """ It provides a Host compatible with CFSSL. """ def __init__(self, name, host, port=None): + """ Initialize a new Client Configuration. + + Args: + name (:obj:`str`): Canonical name of host/remote. + host (:obj:`str`): Advertised host name or IP for host. + port (:obj:`int`, optional): Port number advertised by host, if + any. + """ self.name = name self.host = host self.port = port diff --git a/cfssl/models/policy_auth.py b/cfssl/models/policy_auth.py index 6803074..169fa2b 100644 --- a/cfssl/models/policy_auth.py +++ b/cfssl/models/policy_auth.py @@ -7,6 +7,14 @@ class PolicyAuth(object): """ It provides a Certificate Auth policy compatible with CFSSL """ def __init__(self, name, key, key_type='standard'): + """ Initialize a new Authentication Policy. + + Args: + name (:obj:`str`): Canonical name for policy. + key (:obj:`str`): Key/password data. + key_type (:obj:`str`): Type of key. Currently only ``standard`` is + supported. + """ self.name = name self.key = key self.key_type = key_type diff --git a/cfssl/models/policy_sign.py b/cfssl/models/policy_sign.py index 1e6eab2..119cf62 100644 --- a/cfssl/models/policy_sign.py +++ b/cfssl/models/policy_sign.py @@ -2,23 +2,34 @@ # Copyright 2016 LasLabs Inc. # License MIT (https://opensource.org/licenses/MIT). -from ..defaults import DEFAULT_EXPIRE_MINUTES +from ..defaults import DEFAULT_EXPIRE_DELTA class PolicySign(object): """ It provides a Certificate Auth policy compatible with CFSSL """ def __init__(self, name, usage_policies, auth_policy, - expire_minutes=DEFAULT_EXPIRE_MINUTES): + expire_delta=DEFAULT_EXPIRE_DELTA): + """ Initialize a new Signing Policy. + + Args: + name (:obj:`str`): Canonical name for policy. + usage_policies (:type:`iter` of :obj:`cfssl.PolicyUse`): Usage + policies that should apply to this signing policy. + auth_policy (:obj:`obj.PolicyAuth`): Authentication policy that + should apply to this signing policy. + expire_delta (:obj:`datetime.timedelta`): Delta representing when + the signature should expire. + """ self.name = name self.usage_policies = usage_policies self.auth_policy = auth_policy - self.expire_minutes = expire_minutes + self.expire_delta = expire_delta def to_api(self): """ It returns an object compatible with the API. """ return { 'auth_key': self.auth_policy.name, - 'expiry': '%dm' % self.expire_minutes, + 'expiry': '%ds' % self.expire_delta.total_seconds(), 'usages': [u.to_api() for u in self.usage_policies], } diff --git a/cfssl/models/policy_use.py b/cfssl/models/policy_use.py index 5c1a25b..34cfb21 100644 --- a/cfssl/models/policy_use.py +++ b/cfssl/models/policy_use.py @@ -7,6 +7,12 @@ class PolicyUse(object): """ It provides a Certificate Use policy compatible with CFSSL """ def __init__(self, name, code): + """ Initialize a new Use Policy. + + Args: + name (:obj:`str`): Canonical name for policy. + code (:obj:`str`): CFSSL use code that policy applies to. + """ self.name = name self.code = code diff --git a/cfssl/models/subject_info.py b/cfssl/models/subject_info.py index aed18ac..06a3836 100644 --- a/cfssl/models/subject_info.py +++ b/cfssl/models/subject_info.py @@ -7,6 +7,17 @@ class SubjectInfo(object): """ It provides a SubjectInfo (Name) compatible with CFSSL. """ def __init__(self, org_name, org_unit, city, state, country): + """ Initialize a new Subject Information. + + Args: + org_name (:obj:`str`): The full legal name of the organization. Do + not abbreviate. + org_unit (:obj:`str`): Section of the organization. + city (:obj:`str`): The city where the organization is legally + located. + country (:obj:`str`): The two letter ISO abbreviation for the + country. + """ self.org_name = org_name self.org_unit = org_unit self.city = city diff --git a/cfssl/tests/test_cfssl.py b/cfssl/tests/test_cfssl.py index 566005f..7d30490 100644 --- a/cfssl/tests/test_cfssl.py +++ b/cfssl/tests/test_cfssl.py @@ -86,13 +86,17 @@ def test_new_key(self, call): expect = { 'hosts': [mock.MagicMock()], 'names': [mock.MagicMock()], - 'common_name': 'cn' + 'common_name': 'cn', + 'ca': mock.MagicMock(), + 'key': mock.MagicMock(), } self.cfssl.new_key(**expect) expect['CN'] = 'cn' del expect['common_name'] expect['hosts'][0]= expect['hosts'][0].to_api() expect['names'][0] = expect['names'][0].to_api() + expect['ca'] = expect['ca'].to_api() + expect['key'] = expect['key'].to_api() call.assert_called_once_with( 'newkey', 'POST', data=expect ) diff --git a/cfssl/tests/test_policy_sign.py b/cfssl/tests/test_policy_sign.py index bc78c85..406b9c8 100644 --- a/cfssl/tests/test_policy_sign.py +++ b/cfssl/tests/test_policy_sign.py @@ -5,6 +5,8 @@ import mock import unittest +from datetime import timedelta + from ..models.policy_sign import PolicySign @@ -16,7 +18,7 @@ def setUp(self): 'name': 'name', 'usage_policies': [mock.MagicMock()], 'auth_policy': mock.MagicMock(), - 'expire_minutes': 1234, + 'expire_delta': timedelta(seconds=1234), } self.model = PolicySign(**self.vals) @@ -25,7 +27,7 @@ def test_to_api(self): res = self.model.to_api() expect = { 'auth_key': self.vals['auth_policy'].name, - 'expiry': '1234m', + 'expiry': '1234s', 'usages': [self.vals['usage_policies'][0].to_api()], } self.assertDictEqual(res, expect)