1# ------------------------------------
2# Copyright (c) Microsoft Corporation.
3# Licensed under the MIT License.
4# ------------------------------------
5
6# pylint: disable=too-many-lines,too-many-public-methods
7from ._shared import parse_key_vault_id
8from ._generated.v7_1 import models
9from ._enums import(
10    CertificatePolicyAction,
11    KeyUsageType,
12    KeyCurveName,
13    KeyType,
14    CertificateContentType,
15    WellKnownIssuerNames
16)
17
18try:
19    from typing import TYPE_CHECKING
20except ImportError:
21    TYPE_CHECKING = False
22
23if TYPE_CHECKING:
24    from typing import Any, Dict, Optional, Union, List
25    from datetime import datetime
26
27
28class AdministratorContact(object):
29    """Details of the organization administrator of the certificate issuer.
30
31    :param str first_name: First name of the issuer.
32    :param str last_name: Last name of the issuer.
33    :param str email: email of the issuer.
34    :param str phone: phone number of the issuer.
35    """
36
37    def __init__(self, first_name=None, last_name=None, email=None, phone=None):
38        # type: (Optional[str], Optional[str], Optional[str], Optional[str]) -> None
39        self._first_name = first_name
40        self._last_name = last_name
41        self._phone = phone
42        self._email = email
43
44    def __repr__(self):
45        # type () -> str
46        return "AdministratorContact(first_name={}, last_name={}, email={}, phone={})".format(
47            self.first_name, self.last_name, self.email, self.phone
48        )[:1024]
49
50    @classmethod
51    def _from_admin_detail(cls, admin_detail):
52        # type: (models.AdministratorDetails) -> AdministratorContact
53        """Construct a AdministratorContact from an autorest-generated AdministratorDetailsBundle"""
54        return cls(
55            email=admin_detail.email_address,
56            first_name=admin_detail.first_name,
57            last_name=admin_detail.last_name,
58            phone=admin_detail.phone,
59        )
60
61    @property
62    def email(self):
63        # type: () -> str
64        """:rtype: str"""
65        return self._email
66
67    @property
68    def first_name(self):
69        # type: () -> str
70        """:rtype: str"""
71        return self._first_name
72
73    @property
74    def last_name(self):
75        # type: () -> str
76        """:rtype: str"""
77        return self._last_name
78
79    @property
80    def phone(self):
81        # type: () -> str
82        """:rtype: str"""
83        return self._phone
84
85
86class CertificateOperationError(object):
87    """The key vault server error.
88
89    :param str code: The error code.
90    :param str message: The error message.
91    :param inner_error: The error object itself
92    :type inner_error: ~azure.keyvault.certificates.CertificateOperationError
93    """
94
95    def __init__(self, code, message, inner_error):
96        # type: (str, str, CertificateOperationError) -> None
97        self._code = code
98        self._message = message
99        self._inner_error = inner_error
100
101    def __repr__(self):
102        # type () -> str
103        return "CertificateOperationError({}, {}, {})".format(self.code, self.message, self.inner_error)[:1024]
104
105    @classmethod
106    def _from_error_bundle(cls, error_bundle):
107        # type: (models.Error) -> CertificateOperationError
108        return cls(
109            code=error_bundle.code,
110            message=error_bundle.message,
111            inner_error=cls._from_error_bundle(error_bundle.inner_error)
112        )
113
114    @property
115    def code(self):
116        # type: () -> str
117        """The error code.
118
119        :rtype: str
120        """
121        return self._code
122
123    @property
124    def message(self):
125        # type: () -> str
126        """The error message.
127
128        :rtype: str
129        """
130        return self._message
131
132    @property
133    def inner_error(self):
134        # type: () -> CertificateOperationError
135        """The error itself
136
137        :return ~azure.keyvault.certificates.CertificateOperationError:
138        """
139        return self._inner_error
140
141
142class CertificateProperties(object):
143    """Certificate properties consists of a certificates metadata.
144    """
145
146    def __init__(self, **kwargs):
147        # type: (**Any) -> None
148        self._attributes = kwargs.pop("attributes", None)
149        self._id = kwargs.pop("cert_id", None)
150        self._vault_id = KeyVaultCertificateIdentifier(self._id)
151        self._x509_thumbprint = kwargs.pop("x509_thumbprint", None)
152        self._tags = kwargs.pop("tags", None)
153
154    def __repr__(self):
155        # type () -> str
156        return "<CertificateProperties [{}]>".format(self.id)[:1024]
157
158    @classmethod
159    def _from_certificate_item(cls, certificate_item):
160        # type: (models.CertificateItem) -> CertificateProperties
161        """Construct a CertificateProperties from an autorest-generated CertificateItem"""
162        return cls(
163            attributes=certificate_item.attributes,
164            cert_id=certificate_item.id,
165            x509_thumbprint=certificate_item.x509_thumbprint,
166            tags=certificate_item.tags,
167        )
168
169    @property
170    def id(self):
171        # type: () -> str
172        """Certificate identifier.
173
174        :rtype: str
175        """
176        return self._id
177
178    @property
179    def name(self):
180        # type: () -> str
181        """The name of the certificate.
182
183        :rtype: str
184        """
185        return self._vault_id.name
186
187    @property
188    def enabled(self):
189        # type: () -> bool
190        """Whether the certificate is enabled or not.
191
192        :rtype: bool
193        """
194        return self._attributes.enabled if self._attributes else None
195
196    @property
197    def not_before(self):
198        # type: () -> datetime
199        """The datetime before which the certificate is not valid.
200
201        :rtype: ~datetime.datetime
202        """
203        return self._attributes.not_before if self._attributes else None
204
205    @property
206    def expires_on(self):
207        # type: () -> datetime
208        """The datetime when the certificate expires.
209
210        :rtype: ~datetime.datetime
211        """
212        return self._attributes.expires if self._attributes else None
213
214    @property
215    def created_on(self):
216        # type: () -> datetime
217        """The datetime when the certificate is created.
218
219        :rtype: ~datetime.datetime
220        """
221        return self._attributes.created if self._attributes else None
222
223    @property
224    def updated_on(self):
225        # type: () -> datetime
226        """The datetime when the certificate was last updated.
227
228        :rtype: ~datetime.datetime
229        """
230        return self._attributes.updated if self._attributes else None
231
232    @property
233    def recoverable_days(self):
234        # type: () -> Optional[int]
235        """The number of days the certificate is retained before being deleted from a soft-delete enabled Key Vault.
236
237        :rtype: int
238        """
239        # recoverable_days was added in 7.1-preview
240        if self._attributes and hasattr(self._attributes, "recoverable_days"):
241            return self._attributes.recoverable_days
242        return None
243
244    @property
245    def recovery_level(self):
246        # type: () -> models.DeletionRecoveryLevel
247        """The deletion recovery level currently in effect for the certificate.
248
249        :rtype: models.DeletionRecoveryLevel
250        """
251        return self._attributes.recovery_level if self._attributes else None
252
253    @property
254    def vault_url(self):
255        # type: () -> str
256        """URL of the vault containing the certificate
257
258        :rtype: str
259        """
260        return self._vault_id.vault_url
261
262    @property
263    def x509_thumbprint(self):
264        # type: () -> bytes
265        """Thumbprint of the certificate.
266
267        :rtype: bytes
268        """
269        return self._x509_thumbprint
270
271    @property
272    def tags(self):
273        # type: () -> Dict[str, str]
274        """Application specific metadata in the form of key-value pairs.
275
276        :rtype: str
277        """
278        return self._tags
279
280    @property
281    def version(self):
282        # type: () -> str
283        """The version of the certificate
284
285        :rtype: str
286        """
287        return self._vault_id.version
288
289
290class KeyVaultCertificate(object):
291    """Consists of a certificate and its attributes
292
293    :param policy: The management policy for the certificate.
294    :type policy: ~azure.keyvault.certificates.CertificatePolicy
295    :param properties: The certificate's properties.
296    :type properties: ~azure.keyvault.certificates.CertificateProperties
297    :param bytearray cer: CER contents of the X509 certificate.
298    """
299
300    def __init__(
301        self,
302        policy=None,  # type: Optional[CertificatePolicy]
303        properties=None,  # type: Optional[CertificateProperties]
304        cer=None,  # type: Optional[bytes]
305        **kwargs  # type: Any
306    ):
307        # type: (...) -> None
308        self._properties = properties
309        self._key_id = kwargs.get("key_id", None)
310        self._secret_id = kwargs.get("secret_id")
311        self._policy = policy
312        self._cer = cer
313
314    def __repr__(self):
315        # type () -> str
316        return "<KeyVaultCertificate [{}]>".format(self.id)[:1024]
317
318    @classmethod
319    def _from_certificate_bundle(cls, certificate_bundle):
320        # type: (models.CertificateBundle) -> KeyVaultCertificate
321        """Construct a certificate from an autorest-generated certificateBundle"""
322        # pylint:disable=protected-access
323
324        if certificate_bundle.policy:
325            policy = CertificatePolicy._from_certificate_policy_bundle(certificate_bundle.policy)
326        else:
327            policy = None
328
329        return cls(
330            properties=CertificateProperties._from_certificate_item(certificate_bundle),
331            key_id=certificate_bundle.kid,
332            secret_id=certificate_bundle.sid,
333            policy=policy,
334            cer=certificate_bundle.cer,
335        )
336
337    @property
338    def id(self):
339        # type: () -> str
340        """Certificate identifier.
341
342        :rtype: str
343        """
344        return self._properties.id
345
346    @property
347    def name(self):
348        # type: () -> str
349        """The name of the certificate.
350
351        :rtype: str
352        """
353        return self._properties.name
354
355    @property
356    def properties(self):
357        # type: () -> CertificateProperties
358        """The certificate's properties
359
360        :rtype: ~azure.keyvault.certificates.CertificateProperties
361        """
362        return self._properties
363
364    @property
365    def key_id(self):
366        # type: () -> str
367        """:rtype: str"""
368        return self._key_id
369
370    @property
371    def secret_id(self):
372        # type: () -> str
373        """:rtype: str"""
374        return self._secret_id
375
376    @property
377    def policy(self):
378        # type: () -> CertificatePolicy
379        """The management policy of the certificate.
380
381        :rtype: ~azure.keyvault.certificates.CertificatePolicy
382        """
383        return self._policy
384
385    @property
386    def cer(self):
387        # type: () -> bytes
388        """The CER contents of the certificate.
389
390        :rtype: bytes
391        """
392        return self._cer
393
394
395class KeyVaultCertificateIdentifier(object):
396    """Information about a KeyVaultCertificate parsed from a certificate ID.
397
398    :param str source_id: the full original identifier of a certificate
399    :raises ValueError: if the certificate ID is improperly formatted
400    Example:
401        .. literalinclude:: ../tests/test_parse_id.py
402            :start-after: [START parse_key_vault_certificate_id]
403            :end-before: [END parse_key_vault_certificate_id]
404            :language: python
405            :caption: Parse a certificate's ID
406            :dedent: 8
407    """
408
409    def __init__(self, source_id):
410        # type: (str) -> None
411        self._resource_id = parse_key_vault_id(source_id)
412
413    @property
414    def source_id(self):
415        # type: () -> str
416        return self._resource_id.source_id
417
418    @property
419    def vault_url(self):
420        # type: () -> str
421        return self._resource_id.vault_url
422
423    @property
424    def name(self):
425        # type: () -> str
426        return self._resource_id.name
427
428    @property
429    def version(self):
430        # type: () -> Optional[str]
431        return self._resource_id.version
432
433
434class CertificateOperation(object):
435    # pylint:disable=too-many-instance-attributes
436    """A certificate operation is returned in case of long running requests.
437
438    :param str cert_operation_id: The certificate id.
439    :param issuer_name: Name of the operation's issuer object or reserved names.
440    :type issuer_name: str or ~azure.keyvault.certificates.WellKnownIssuerNames
441    :param str certificate_type: Type of certificate requested from the issuer provider.
442    :param bool certificate_transparency: Indicates if the certificate this operation is
443        running for is published to certificate transparency logs.
444    :param bytearray csr: The certificate signing request (CSR) that is being used in the certificate
445        operation.
446    :param bool cancellation_requested: Indicates if cancellation was requested on the certificate
447        operation.
448    :param str status: Status of the certificate operation.
449    :param str status_details: The status details of the certificate operation
450    :param error: Error encountered, if any, during the certificate operation.
451    :type error: ~azure.keyvault.certificates.CertificateOperationError
452    :param str target: Location which contains the result of the certificate operation.
453    :param str request_id: Identifier for the certificate operation.
454    """
455
456    def __init__(
457        self,
458        cert_operation_id=None,  # type: Optional[str]
459        issuer_name=None,  # type: Optional[Union[str, WellKnownIssuerNames]]
460        certificate_type=None,  # type: Optional[str]
461        certificate_transparency=False,  # type: Optional[bool]
462        csr=None,  # type: Optional[bytes]
463        cancellation_requested=False,  # type: Optional[bool]
464        status=None,  # type: Optional[str]
465        status_details=None,  # type: Optional[str]
466        error=None,  # type: Optional[CertificateOperationError]
467        target=None,  # type: Optional[str]
468        request_id=None,  # type: Optional[str]
469    ):
470        # type: (...) -> None
471        self._id = cert_operation_id
472        self._vault_id = parse_key_vault_id(cert_operation_id)
473        self._issuer_name = issuer_name
474        self._certificate_type = certificate_type
475        self._certificate_transparency = certificate_transparency
476        self._csr = csr
477        self._cancellation_requested = cancellation_requested
478        self._status = status
479        self._status_details = status_details
480        self._error = error
481        self._target = target
482        self._request_id = request_id
483
484    def __repr__(self):
485        # type () -> str
486        return "<CertificateOperation [{}]>".format(self.id)[:1024]
487
488    @classmethod
489    def _from_certificate_operation_bundle(cls, certificate_operation_bundle):
490        # type: (models.CertificateOperation) -> CertificateOperation
491        """Construct a CertificateOperation from an autorest-generated CertificateOperation"""
492
493        issuer_parameters = certificate_operation_bundle.issuer_parameters
494        return cls(
495            cert_operation_id=certificate_operation_bundle.id,
496            issuer_name=issuer_parameters.name,
497            certificate_type=(
498                certificate_operation_bundle.issuer_parameters.certificate_type
499                if certificate_operation_bundle.issuer_parameters
500                else None
501            ),
502            # 2016-10-01 IssuerParameters doesn't have certificate_transparency
503            certificate_transparency=getattr(issuer_parameters, "certificate_transparency", None),
504            csr=certificate_operation_bundle.csr,
505            cancellation_requested=certificate_operation_bundle.cancellation_requested,
506            status=certificate_operation_bundle.status,
507            status_details=certificate_operation_bundle.status_details,
508            error=(CertificateOperationError._from_error_bundle(certificate_operation_bundle.error)  # pylint: disable=protected-access
509                   if certificate_operation_bundle.error else None),
510            target=certificate_operation_bundle.target,
511            request_id=certificate_operation_bundle.request_id,
512        )
513
514    @property
515    def id(self):
516        # type: () -> str
517        """:rtype: str"""
518        return self._id
519
520    @property
521    def name(self):
522        # type: () -> str
523        """:rtype: str"""
524        return self._vault_id.name
525
526    @property
527    def vault_url(self):
528        # type: () -> str
529        """URL of the vault containing the CertificateOperation
530
531        :rtype: str
532        """
533        return self._vault_id.vault_url
534
535    @property
536    def issuer_name(self):
537        # type: () -> str
538        """The name of the issuer of the certificate.
539
540        :rtype: str
541        """
542        return self._issuer_name
543
544    @property
545    def certificate_type(self):
546        # type: () -> str
547        """Type of certificate to be requested from the issuer provider.
548
549        :rtype: str
550        """
551        return self._certificate_type
552
553    @property
554    def certificate_transparency(self):
555        # type: () -> bool
556        """Whether certificates generated under this policy should be published to certificate
557        transparency logs.
558
559        :rtype: bool
560        """
561        return self._certificate_transparency
562
563    @property
564    def csr(self):
565        # type: () -> bytes
566        """The certificate signing request that is being used in this certificate operation.
567
568        :rtype: bytes
569        """
570        return self._csr
571
572    @property
573    def cancellation_requested(self):
574        # type: () -> bool
575        """Whether cancellation was requested on the certificate operation.
576
577        :rtype: bool
578        """
579        return self._cancellation_requested
580
581    @property
582    def status(self):
583        # type: () -> str
584        """:rtype: str"""
585        return self._status
586
587    @property
588    def status_details(self):
589        # type: () -> str
590        """:rtype: str"""
591        return self._status_details
592
593    @property
594    def error(self):
595        # type: () -> CertificateOperationError
596        """:rtype: ~azure.keyvault.certificates.CertificateOperationError"""
597        return self._error
598
599    @property
600    def target(self):
601        # type: () -> str
602        """Location which contains the result of the certificate operation.
603
604        :rtype: str
605        """
606        return self._target
607
608    @property
609    def request_id(self):
610        # type: () -> str
611        """Identifier for the certificate operation.
612
613        :rtype: str
614        """
615        return self._request_id
616
617
618class CertificatePolicy(object):
619    """Management policy for a certificate.
620
621    :param Optional[str] issuer_name: Optional. Name of the referenced issuer object or reserved names; for example,
622        :attr:`~azure.keyvault.certificates.WellKnownIssuerNames.self` or
623        :attr:`~azure.keyvault.certificates.WellKnownIssuerNames.unknown`
624    :keyword str subject: The subject name of the certificate. Should be a valid X509
625        distinguished name. Either subject or one of the subject alternative name parameters are required for
626        creating a certificate. This will be ignored when importing a certificate; the subject will be parsed from
627        the imported certificate.
628    :keyword Iterable[str] san_emails: Subject alternative emails of the X509 object. Either
629        subject or one of the subject alternative name parameters are required for creating a certificate.
630    :keyword Iterable[str] san_dns_names: Subject alternative DNS names of the X509 object. Either
631        subject or one of the subject alternative name parameters are required for creating a certificate.
632    :keyword Iterable[str] san_user_principal_names: Subject alternative user principal names of the X509 object.
633        Either subject or one of the subject alternative name parameters are required for creating a certificate.
634    :keyword bool exportable: Indicates if the private key can be exported. For valid values,
635        see KeyType.
636    :keyword key_type: The type of key pair to be used for the certificate.
637    :paramtype key_type: str or ~azure.keyvault.certificates.KeyType
638    :keyword int key_size: The key size in bits. For example: 2048, 3072, or 4096
639        for RSA.
640    :keyword bool reuse_key: Indicates if the same key pair will be used on certificate
641        renewal.
642    :keyword key_curve_name: Elliptic curve name. For valid values, see KeyCurveName.
643    :paramtype key_curve_name: str or ~azure.keyvault.certificates.KeyCurveName
644    :keyword enhanced_key_usage: The extended ways the key of the certificate can be used.
645    :paramtype enhanced_key_usage: list[str]
646    :keyword key_usage: List of key usages.
647    :paramtype key_usage: list[str or ~azure.keyvault.certificates.KeyUsageType]
648    :keyword content_type: The media type (MIME type) of the secret backing the certificate.  If not specified,
649        :attr:`CertificateContentType.pkcs12` is assumed.
650    :paramtype content_type: str or ~azure.keyvault.certificates.CertificateContentType
651    :keyword int validity_in_months: The duration that the certificate is valid in months.
652    :keyword lifetime_actions: Actions that will be performed by Key Vault over the lifetime
653        of a certificate
654    :paramtype lifetime_actions: Iterable[~azure.keyvault.certificates.LifetimeAction]
655    :keyword str certificate_type: Type of certificate to be requested from the issuer provider.
656    :keyword bool certificate_transparency: Indicates if the certificates generated under this policy
657        should be published to certificate transparency logs.
658
659    """
660
661    # pylint:disable=too-many-instance-attributes
662    def __init__(
663        self,
664        issuer_name=None,  # type: Optional[str]
665        **kwargs  # type: Any
666    ):
667        # type: (...) -> None
668        self._issuer_name = issuer_name
669        self._subject = kwargs.pop("subject", None)
670        self._attributes = kwargs.pop("attributes", None)
671        self._exportable = kwargs.pop("exportable", None)
672        self._key_type = kwargs.pop("key_type", None)
673        self._key_size = kwargs.pop("key_size", None)
674        self._reuse_key = kwargs.pop("reuse_key", None)
675        self._key_curve_name = kwargs.pop("key_curve_name", None)
676        self._enhanced_key_usage = kwargs.pop("enhanced_key_usage", None)
677        self._key_usage = kwargs.pop("key_usage", None)
678        self._content_type = kwargs.pop("content_type", None)
679        self._validity_in_months = kwargs.pop("validity_in_months", None)
680        self._lifetime_actions = kwargs.pop("lifetime_actions", None)
681        self._certificate_type = kwargs.pop("certificate_type", None)
682        self._certificate_transparency = kwargs.pop("certificate_transparency", None)
683        self._san_emails = kwargs.pop("san_emails", None) or None
684        self._san_dns_names = kwargs.pop("san_dns_names", None) or None
685        self._san_user_principal_names = kwargs.pop("san_user_principal_names", None) or None
686
687    @classmethod
688    def get_default(cls):
689        return cls(issuer_name=WellKnownIssuerNames.self, subject="CN=DefaultPolicy")
690
691    def __repr__(self):
692        # type () -> str
693        return "<CertificatePolicy [issuer_name: {}]>".format(self.issuer_name)[:1024]
694
695    def _to_certificate_policy_bundle(self):
696        # type: (CertificatePolicy) -> models.CertificatePolicy
697
698        """Construct a version emulating the generated CertificatePolicy from a wrapped CertificatePolicy"""
699        if self.issuer_name or self.certificate_type or self.certificate_transparency:
700            issuer_parameters = models.IssuerParameters(
701                name=self.issuer_name,
702                certificate_type=self.certificate_type,
703                certificate_transparency=self.certificate_transparency,  # 2016-10-01 model will ignore this
704            )
705        else:
706            issuer_parameters = None
707
708        # pylint:disable=too-many-boolean-expressions
709        if (
710            self.enabled is not None
711            or self.created_on is not None
712            or self.updated_on is not None
713        ):
714            attributes = models.CertificateAttributes(
715                enabled=self.enabled,
716                created=self.created_on,
717                updated=self.updated_on,
718            )
719        else:
720            attributes = None
721
722        if self.lifetime_actions:
723            lifetime_actions = []
724            for lifetime_action in self.lifetime_actions:
725                lifetime_actions.append(
726                    models.LifetimeAction(
727                        trigger=models.Trigger(
728                            lifetime_percentage=lifetime_action.lifetime_percentage,
729                            days_before_expiry=lifetime_action.days_before_expiry,
730                        ),
731                        action=models.Action(action_type=lifetime_action.action),
732                    )
733                )
734        else:
735            lifetime_actions = None
736
737        # pylint:disable=too-many-boolean-expressions
738        if (
739            self.subject
740            or self.enhanced_key_usage
741            or self.key_usage
742            or self.san_emails
743            or self.san_user_principal_names
744            or self.san_dns_names
745            or self.validity_in_months
746        ):
747            if self.key_usage:
748                key_usage = [k.value if not isinstance(k, str) else k for k in self.key_usage]
749            else:
750                key_usage = None
751
752            x509_certificate_properties = models.X509CertificateProperties(
753                subject=self.subject,
754                ekus=self.enhanced_key_usage,
755                subject_alternative_names=models.SubjectAlternativeNames(
756                    emails=self.san_emails, upns=self.san_user_principal_names, dns_names=self.san_dns_names
757                ),
758                key_usage=key_usage,
759                validity_in_months=self.validity_in_months,
760            )
761        else:
762            x509_certificate_properties = None
763
764        if self.exportable or self.key_type or self.key_size or self.reuse_key or self.key_curve_name:
765            key_properties = models.KeyProperties(
766                exportable=self.exportable,
767                key_type=self.key_type,
768                key_size=self.key_size,
769                reuse_key=self.reuse_key,
770                curve=self.key_curve_name,
771            )
772        else:
773            key_properties = None
774
775        if self.content_type:
776            secret_properties = models.SecretProperties(content_type=self.content_type)
777        else:
778            secret_properties = None
779
780        policy_bundle = models.CertificatePolicy(
781            key_properties=key_properties,
782            secret_properties=secret_properties,
783            x509_certificate_properties=x509_certificate_properties,
784            lifetime_actions=lifetime_actions,
785            issuer_parameters=issuer_parameters,
786            attributes=attributes,
787        )
788        return policy_bundle
789
790    @classmethod
791    def _from_certificate_policy_bundle(cls, certificate_policy_bundle):
792        # type: (models.CertificatePolicy) -> CertificatePolicy
793        """Construct a CertificatePolicy from an autorest-generated CertificatePolicy"""
794        if certificate_policy_bundle.lifetime_actions:
795            lifetime_actions = [
796                LifetimeAction(
797                    action=(CertificatePolicyAction(item.action.action_type) if item.action.action_type else None),
798                    lifetime_percentage=item.trigger.lifetime_percentage,
799                    days_before_expiry=item.trigger.days_before_expiry,
800                )
801                for item in certificate_policy_bundle.lifetime_actions
802            ]
803        else:
804            lifetime_actions = None
805        x509_certificate_properties = certificate_policy_bundle.x509_certificate_properties
806        if x509_certificate_properties and x509_certificate_properties.key_usage:
807            key_usage = [KeyUsageType(k) for k in x509_certificate_properties.key_usage]
808        else:
809            key_usage = None
810        key_properties = certificate_policy_bundle.key_properties
811        curve_name = getattr(key_properties, "curve", None)  # missing from 2016-10-01 KeyProperties
812        if curve_name:
813            curve_name = KeyCurveName(curve_name)
814
815        issuer_parameters = certificate_policy_bundle.issuer_parameters
816        return cls(
817            issuer_name=issuer_parameters.name,
818            subject=(x509_certificate_properties.subject if x509_certificate_properties else None),
819            certificate_type=issuer_parameters.certificate_type,
820            # 2016-10-01 IssuerParameters doesn't have certificate_transparency
821            certificate_transparency=getattr(issuer_parameters, "certificate_transparency", None),
822            lifetime_actions=lifetime_actions,
823            exportable=key_properties.exportable if key_properties else None,
824            key_type=KeyType(key_properties.key_type) if key_properties and key_properties.key_type else None,
825            key_size=key_properties.key_size if key_properties else None,
826            reuse_key=key_properties.reuse_key if key_properties else None,
827            key_curve_name=curve_name,
828            enhanced_key_usage=x509_certificate_properties.ekus if x509_certificate_properties else None,
829            key_usage=key_usage,
830            content_type=(
831                CertificateContentType(certificate_policy_bundle.secret_properties.content_type)
832                if certificate_policy_bundle.secret_properties and
833                certificate_policy_bundle.secret_properties.content_type
834                else None
835            ),
836            attributes=certificate_policy_bundle.attributes,
837            san_emails=(
838                x509_certificate_properties.subject_alternative_names.emails
839                if x509_certificate_properties and x509_certificate_properties.subject_alternative_names
840                else None
841            ),
842            san_user_principal_names=(
843                x509_certificate_properties.subject_alternative_names.upns
844                if x509_certificate_properties and x509_certificate_properties.subject_alternative_names
845                else None
846            ),
847            san_dns_names=(
848                x509_certificate_properties.subject_alternative_names.dns_names
849                if x509_certificate_properties and x509_certificate_properties.subject_alternative_names
850                else None
851            ),
852            validity_in_months=(
853                x509_certificate_properties.validity_in_months if x509_certificate_properties else None
854            ),
855        )
856
857    @property
858    def exportable(self):
859        # type: () -> bool
860        """Whether the private key can be exported.
861
862        :rtype: bool
863        """
864        return self._exportable
865
866    @property
867    def key_type(self):
868        # type: () -> KeyType
869        """The type of key pair to be used for the certificate.
870
871        :rtype: ~azure.keyvault.certificates.KeyType
872        """
873        return self._key_type
874
875    @property
876    def key_size(self):
877        # type: () -> int
878        """The key size in bits.
879
880        :rtype: int
881        """
882        return self._key_size
883
884    @property
885    def reuse_key(self):
886        # type: () -> bool
887        """Whether the same key pair will be used on certificate renewal.
888
889        :rtype: bool
890        """
891        return self._reuse_key
892
893    @property
894    def key_curve_name(self):
895        # type: () -> KeyCurveName
896        """Elliptic curve name.
897
898        :rtype: ~azure.keyvault.certificates.KeyCurveName
899        """
900        return self._key_curve_name
901
902    @property
903    def enhanced_key_usage(self):
904        # type: () -> List[str]
905        """The enhanced key usage.
906
907        :rtype: list[str]
908        """
909        return self._enhanced_key_usage
910
911    @property
912    def key_usage(self):
913        # type: () -> List[KeyUsageType]
914        """List of key usages.
915
916        :rtype: list[~azure.keyvault.certificates.KeyUsageType]
917        """
918        return self._key_usage
919
920    @property
921    def content_type(self):
922        # type: () -> CertificateContentType
923        """The media type (MIME type).
924
925        :rtype: ~azure.keyvault.certificates.CertificateContentType
926        """
927        return self._content_type
928
929    @property
930    def subject(self):
931        # type: () -> str
932        """The subject name of the certificate.
933
934        :rtype: str
935        """
936        return self._subject
937
938    @property
939    def san_emails(self):
940        # type: () -> List[str]
941        """The subject alternative email addresses.
942
943        :rtype: list[str]
944        """
945        return self._san_emails
946
947    @property
948    def san_dns_names(self):
949        # type: () -> List[str]
950        """The subject alternative domain names.
951
952        :rtype: list[str]
953        """
954        return self._san_dns_names
955
956    @property
957    def san_user_principal_names(self):
958        # type: () -> List[str]
959        """The subject alternative user principal names.
960
961        :rtype: list[str]
962        """
963        return self._san_user_principal_names
964
965    @property
966    def validity_in_months(self):
967        # type: () -> int
968        """The duration that the certificate is valid for in months.
969
970        :rtype: int
971        """
972        return self._validity_in_months
973
974    @property
975    def lifetime_actions(self):
976        # type: () -> List[LifetimeAction]
977        """Actions and their triggers that will be performed by Key Vault over
978        the lifetime of the certificate.
979
980        :rtype: list[~azure.keyvault.certificates.LifetimeAction]
981        """
982        return self._lifetime_actions
983
984    @property
985    def issuer_name(self):
986        # type: () -> Optional[str]
987        """Name of the referenced issuer object or reserved names for the issuer
988        of the certificate.
989
990        :rtype: str
991        """
992        return self._issuer_name
993
994    @property
995    def certificate_type(self):
996        # type: () -> str
997        """Type of certificate requested from the issuer provider.
998
999        :rtype: str
1000        """
1001        return self._certificate_type
1002
1003    @property
1004    def certificate_transparency(self):
1005        # type: () -> bool
1006        """Whether the certificates generated under this policy should be published
1007        to certificate transparency logs.
1008
1009        :rtype: bool
1010        """
1011        return self._certificate_transparency
1012
1013    @property
1014    def enabled(self):
1015        # type: () -> bool
1016        """Whether the certificate is enabled or not.
1017
1018        :rtype: bool
1019        """
1020        return self._attributes.enabled if self._attributes else None
1021
1022    @property
1023    def created_on(self):
1024        # type: () -> datetime
1025        """The datetime when the certificate is created.
1026
1027        :rtype: ~datetime.datetime
1028        """
1029        return self._attributes.created if self._attributes else None
1030
1031    @property
1032    def updated_on(self):
1033        # type: () -> datetime
1034        """The datetime when the certificate was last updated.
1035
1036        :rtype: ~datetime.datetime
1037        """
1038        return self._attributes.updated if self._attributes else None
1039
1040
1041class CertificateContact(object):
1042    """The contact information for the vault certificates.
1043
1044    :param str email: Email address of a contact for the certificate.
1045    :param str name: Name of a contact for the certificate.
1046    :param str phone: phone number of a contact for the certificate.
1047    """
1048
1049    def __init__(self, email=None, name=None, phone=None):
1050        # type: (Optional[str], Optional[str], Optional[str]) -> None
1051        self._email = email
1052        self._name = name
1053        self._phone = phone
1054
1055    def __repr__(self):
1056        # type () -> str
1057        return "CertificateContact(email={}, name={}, phone={})".format(self.email, self.name, self.phone)[:1024]
1058
1059    def _to_certificate_contacts_item(self):
1060        # type: (CertificateContact) -> models.Contact
1061        return models.Contact(email_address=self.email, name=self.name, phone=self.phone)
1062
1063    @classmethod
1064    def _from_certificate_contacts_item(cls, contact_item):
1065        # type: (models.Contact) -> CertificateContact
1066        """Construct a CertificateContact from an autorest-generated ContactItem."""
1067        return cls(email=contact_item.email_address, name=contact_item.name, phone=contact_item.phone)
1068
1069    @property
1070    def email(self):
1071        # type: () -> str
1072        """:rtype: str"""
1073        return self._email
1074
1075    @property
1076    def name(self):
1077        # type: () -> str
1078        """:rtype: str"""
1079        return self._name
1080
1081    @property
1082    def phone(self):
1083        # type: () -> str
1084        """:rtype: str"""
1085        return self._phone
1086
1087
1088class IssuerProperties(object):
1089    """The properties of an issuer containing the issuer metadata.
1090
1091    :param str provider: The issuer provider.
1092    """
1093
1094    def __init__(self, provider=None, **kwargs):
1095        # type: (Optional[str], **Any) -> None
1096        self._id = kwargs.pop("issuer_id", None)
1097        self._vault_id = parse_key_vault_id(self._id)
1098        self._provider = provider
1099
1100    def __repr__(self):
1101        # type () -> str
1102        return "IssuerProperties(issuer_id={}, provider={})".format(self.id, self.provider)[:1024]
1103
1104    @classmethod
1105    def _from_issuer_item(cls, issuer_item):
1106        # type: (models.CertificateIssuerItem) -> IssuerProperties
1107        """Construct a IssuerProperties from an autorest-generated CertificateIssuerItem"""
1108        return cls(issuer_id=issuer_item.id, provider=issuer_item.provider)
1109
1110    @property
1111    def id(self):
1112        # type: () -> str
1113        """:rtype: str"""
1114        return self._id
1115
1116    @property
1117    def name(self):
1118        # type: () -> str
1119        # Issuer name is listed under version under vault_id
1120        """:rtype: str"""
1121        return self._vault_id.version
1122
1123    @property
1124    def provider(self):
1125        # type: () -> str
1126        """:rtype: str"""
1127        return self._provider
1128
1129
1130class CertificateIssuer(object):
1131    """The issuer for a Key Vault certificate.
1132
1133    :param str provider: The issuer provider
1134    :param str account_id: The username / account name / account id.
1135    :param str password: The password / secret / account key.
1136    :param str organization_id: The ID of the organization.
1137    :param admin_contacts: Details of the organization administrator.
1138    :type admin_contacts: list[~azure.keyvault.certificates.AdministratorContact]
1139    """
1140
1141    def __init__(
1142        self,
1143        provider,  # type: str
1144        attributes=None,  # type: Optional[models.IssuerAttributes]
1145        account_id=None,  # type: Optional[str]
1146        password=None,  # type: Optional[str]
1147        organization_id=None,  # type: Optional[str]
1148        admin_contacts=None,  # type: Optional[List[AdministratorContact]]
1149        **kwargs  # type: Any
1150    ):
1151        # type: (...) -> None
1152        self._provider = provider
1153        self._attributes = attributes
1154        self._account_id = account_id
1155        self._password = password
1156        self._organization_id = organization_id
1157        self._admin_contacts = admin_contacts
1158        self._id = kwargs.pop("issuer_id", None)
1159        self._vault_id = parse_key_vault_id(self._id)
1160
1161    def __repr__(self):
1162        # type () -> str
1163        return "<CertificateIssuer [{}]>".format(self.id)[:1024]
1164
1165    @classmethod
1166    def _from_issuer_bundle(cls, issuer_bundle):
1167        # type: (models.IssuerBundle) -> CertificateIssuer
1168        """Construct a CertificateIssuer from an autorest-generated IssuerBundle"""
1169        admin_contacts = []
1170        admin_details = (
1171            issuer_bundle.organization_details.admin_details if issuer_bundle.organization_details else None
1172        )
1173        if admin_details:
1174            # pylint:disable=protected-access
1175            for admin_detail in admin_details:
1176                admin_contacts.append(AdministratorContact._from_admin_detail(admin_detail))
1177        return cls(
1178            provider=IssuerProperties._from_issuer_item(issuer_bundle).provider,  # pylint: disable=protected-access
1179            attributes=issuer_bundle.attributes,
1180            account_id=issuer_bundle.credentials.account_id if issuer_bundle.credentials else None,
1181            password=issuer_bundle.credentials.password if issuer_bundle.credentials else None,
1182            organization_id=issuer_bundle.organization_details.id if issuer_bundle.organization_details else None,
1183            admin_contacts=admin_contacts,
1184            issuer_id=issuer_bundle.id,
1185        )
1186
1187    @property
1188    def id(self):
1189        # type: () -> str
1190        """:rtype: str"""
1191        return self._id
1192
1193    @property
1194    def name(self):
1195        # type: () -> str
1196        # Issuer name is listed under version under vault_id.
1197        # This is because the id we pass to parse_key_vault_id has an extra segment, so where most cases the version of
1198        # the general pattern is certificates/name/version, but here we have certificates/issuers/name/version.
1199        # Issuers are not versioned.
1200        """:rtype: str"""
1201        return self._vault_id.version
1202
1203    @property
1204    def provider(self):
1205        # type: () -> str
1206        """The issuer provider.
1207
1208        :rtype: str
1209        """
1210        return self._provider
1211
1212    @property
1213    def enabled(self):
1214        # type: () -> bool
1215        """Whether the certificate is enabled or not.
1216
1217        :rtype: bool
1218        """
1219        return self._attributes.enabled if self._attributes else None
1220
1221    @property
1222    def created_on(self):
1223        # type: () -> datetime
1224        """The datetime when the certificate is created.
1225
1226        :rtype: ~datetime.datetime
1227        """
1228        return self._attributes.created if self._attributes else None
1229
1230    @property
1231    def updated_on(self):
1232        # type: () -> datetime
1233        """The datetime when the certificate was last updated.
1234
1235        :rtype: ~datetime.datetime
1236        """
1237        return self._attributes.updated if self._attributes else None
1238
1239    @property
1240    def account_id(self):
1241        # type: () -> str
1242        """The username/ account name/ account id.
1243
1244        :rtype: str
1245        """
1246        return self._account_id
1247
1248    @property
1249    def password(self):
1250        # type: () -> str
1251        """The password / secret / account key.
1252
1253        :rtype: str
1254        """
1255        return self._password
1256
1257    @property
1258    def organization_id(self):
1259        # type: () -> str
1260        """:rtype: str"""
1261        return self._organization_id
1262
1263    @property
1264    def admin_contacts(self):
1265        # type: () -> List[AdministratorContact]
1266        """Contact details of the organization administrator of this issuer.
1267
1268        :rtype: list[~azure.keyvault.certificates.AdministratorContact]
1269        """
1270        return self._admin_contacts
1271
1272
1273class LifetimeAction(object):
1274    """Action and its trigger that will be performed by certificate Vault over the
1275    lifetime of a certificate.
1276
1277    :param action: The type of the action. For valid values, see CertificatePolicyAction
1278    :type action: str or ~azure.keyvault.certificates.CertificatePolicyAction
1279    :param int lifetime_percentage: Percentage of lifetime at which to trigger. Value
1280        should be between 1 and 99.
1281    :param int days_before_expiry: Days before expiry to attempt renewal. Value should be between
1282        1 and validity_in_months multiplied by 27. I.e., if validity_in_months is 36, then value
1283        should be between 1 and 972 (36 * 27).
1284    """
1285
1286    def __init__(self, action, lifetime_percentage=None, days_before_expiry=None):
1287        # type: (CertificatePolicyAction, Optional[int], Optional[int]) -> None
1288        self._lifetime_percentage = lifetime_percentage
1289        self._days_before_expiry = days_before_expiry
1290        self._action = action
1291
1292    def __repr__(self):
1293        # type () -> str
1294        return "LifetimeAction(action={}, lifetime_percentage={}, days_before_expiry={})".format(
1295            self.action, self.lifetime_percentage, self.days_before_expiry
1296        )[:1024]
1297
1298    @property
1299    def lifetime_percentage(self):
1300        # type: () -> int
1301        """Percentage of lifetime at which to trigger.
1302
1303        :rtype: int
1304        """
1305        return self._lifetime_percentage
1306
1307    @property
1308    def days_before_expiry(self):
1309        # type: () -> int
1310        """Days before expiry to attempt renewal.
1311
1312        :rtype: int
1313        """
1314        return self._days_before_expiry
1315
1316    @property
1317    def action(self):
1318        # type: () -> CertificatePolicyAction
1319        """The type of the action that will be executed.
1320        Valid values are "EmailContacts" and "AutoRenew"
1321
1322        :rtype: ~azure.keyvault.certificates.CertificatePolicyAction
1323        """
1324        return self._action
1325
1326
1327class DeletedCertificate(KeyVaultCertificate):
1328    """A Deleted Certificate consisting of its previous id, attributes and its
1329    tags, as well as information on when it will be purged.
1330
1331    :param policy: The management policy of the deleted certificate.
1332    :type policy: ~azure.keyvault.certificates.CertificatePolicy
1333    :param bytearray cer: CER contents of the X509 certificate.
1334    :param datetime deleted_on: The time when the certificate was deleted, in UTC
1335    :param str recovery_id: The url of the recovery object, used to identify and
1336        recover the deleted certificate.
1337    :param datetime scheduled_purge_date: The time when the certificate is scheduled to
1338        be purged, in UTC
1339    """
1340
1341    def __init__(
1342        self,
1343        properties=None,  # type: Optional[CertificateProperties]
1344        policy=None,  # type: Optional[CertificatePolicy]
1345        cer=None,  # type: Optional[bytes]
1346        **kwargs  # type: Any
1347    ):
1348        # type: (...) -> None
1349        super(DeletedCertificate, self).__init__(properties=properties, policy=policy, cer=cer, **kwargs)
1350        self._deleted_on = kwargs.get("deleted_on", None)
1351        self._recovery_id = kwargs.get("recovery_id", None)
1352        self._scheduled_purge_date = kwargs.get("scheduled_purge_date", None)
1353
1354    def __repr__(self):
1355        # type () -> str
1356        return "<DeletedCertificate [{}]>".format(self.id)[:1024]
1357
1358    @classmethod
1359    def _from_deleted_certificate_item(cls, deleted_certificate_item):
1360        # type: (models.DeletedCertificateItem) -> DeletedCertificate
1361        """Construct a DeletedCertificate from an autorest-generated DeletedCertificateItem"""
1362        return cls(
1363            properties=CertificateProperties._from_certificate_item(  # pylint: disable=protected-access
1364                deleted_certificate_item
1365            ),
1366            key_id=None,
1367            secret_id=None,
1368            policy=None,
1369            cer=None,
1370            deleted_on=deleted_certificate_item.deleted_date,
1371            recovery_id=deleted_certificate_item.recovery_id,
1372            scheduled_purge_date=deleted_certificate_item.scheduled_purge_date,
1373        )
1374
1375    @classmethod
1376    def _from_deleted_certificate_bundle(cls, deleted_certificate_bundle):
1377        # type: (models.DeletedCertificateBundle) -> DeletedCertificate
1378        """Construct a DeletedCertificate from an autorest-generated DeletedCertificateItem"""
1379        # pylint:disable=protected-access
1380        return cls(
1381            properties=CertificateProperties._from_certificate_item(deleted_certificate_bundle),
1382            key_id=deleted_certificate_bundle.kid,
1383            secret_id=deleted_certificate_bundle.sid,
1384            policy=CertificatePolicy._from_certificate_policy_bundle(deleted_certificate_bundle.policy),
1385            cer=deleted_certificate_bundle.cer,
1386            deleted_on=deleted_certificate_bundle.deleted_date,
1387            recovery_id=deleted_certificate_bundle.recovery_id,
1388            scheduled_purge_date=deleted_certificate_bundle.scheduled_purge_date,
1389        )
1390
1391    @property
1392    def deleted_on(self):
1393        # type: () -> datetime
1394        """The datetime that the certificate was deleted.
1395
1396        :rtype: ~datetime.datetime
1397        """
1398        return self._deleted_on
1399
1400    @property
1401    def recovery_id(self):
1402        # type: () -> str
1403        """The url of the recovery object, used to identify and recover the deleted certificate.
1404
1405        :rtype: str
1406        """
1407        return self._recovery_id
1408
1409    @property
1410    def scheduled_purge_date(self):
1411        # type: () -> datetime
1412        """The datetime when the certificate is scheduled to be purged.
1413
1414        :rtype: str
1415        """
1416        return self._scheduled_purge_date
1417