Skip to content

Commit

Permalink
Add parse_key_vault_certificate_id method and tests (#14518)
Browse files Browse the repository at this point in the history
  • Loading branch information
mccoyp authored Oct 16, 2020
1 parent bdc2e9f commit 2635f65
Show file tree
Hide file tree
Showing 9 changed files with 490 additions and 41 deletions.
3 changes: 3 additions & 0 deletions sdk/keyvault/azure-keyvault-certificates/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Release History

## 4.2.2 (Unreleased)
### Added
- Added method `parse_key_vault_certificate_id` that parses out a full ID returned by Key Vault, so users can easily
access the certificate's `name`, `vault_url`, and `version`.


## 4.2.1 (2020-09-08)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
LifetimeAction,
KeyVaultCertificate
)
from ._parse_id import parse_key_vault_certificate_id
from ._shared.client_base import ApiVersion
from ._shared import KeyVaultResourceId

__all__ = [
"ApiVersion",
Expand All @@ -47,7 +49,9 @@
"CertificateContentType",
"WellKnownIssuerNames",
"CertificateIssuer",
"IssuerProperties"
"IssuerProperties",
"parse_key_vault_certificate_id",
"KeyVaultResourceId"
]

from ._version import VERSION
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# ------------------------------------

# pylint: disable=too-many-lines,too-many-public-methods
from ._shared import parse_vault_id
from ._shared import parse_key_vault_id
from ._generated.v7_1 import models
from ._enums import(
CertificatePolicyAction,
Expand Down Expand Up @@ -147,7 +147,7 @@ def __init__(self, **kwargs):
# type: (**Any) -> None
self._attributes = kwargs.pop("attributes", None)
self._id = kwargs.pop("cert_id", None)
self._vault_id = parse_vault_id(self._id)
self._vault_id = parse_key_vault_id(self._id)
self._x509_thumbprint = kwargs.pop("x509_thumbprint", None)
self._tags = kwargs.pop("tags", None)

Expand Down Expand Up @@ -430,7 +430,7 @@ def __init__(
):
# type: (...) -> None
self._id = cert_operation_id
self._vault_id = parse_vault_id(cert_operation_id)
self._vault_id = parse_key_vault_id(cert_operation_id)
self._issuer_name = issuer_name
self._certificate_type = certificate_type
self._certificate_transparency = certificate_transparency
Expand Down Expand Up @@ -1058,7 +1058,7 @@ class IssuerProperties(object):
def __init__(self, provider=None, **kwargs):
# type: (Optional[str], **Any) -> None
self._id = kwargs.pop("issuer_id", None)
self._vault_id = parse_vault_id(self._id)
self._vault_id = parse_key_vault_id(self._id)
self._provider = provider

def __repr__(self):
Expand Down Expand Up @@ -1120,7 +1120,7 @@ def __init__(
self._organization_id = organization_id
self._admin_contacts = admin_contacts
self._id = kwargs.pop("issuer_id", None)
self._vault_id = parse_vault_id(self._id)
self._vault_id = parse_key_vault_id(self._id)

def __repr__(self):
# type () -> str
Expand Down Expand Up @@ -1157,9 +1157,9 @@ def id(self):
@property
def name(self):
# type: () -> str
# Issuer name is listed under version under vault_id
# This is because the id we pass to parse_vault_id has an extra segment, so where most cases the version of
# The general pattern is certificates/name/version, but here we have certificates/issuers/name/version
# Issuer name is listed under version under vault_id.
# This is because the id we pass to parse_key_vault_id has an extra segment, so where most cases the version of
# the general pattern is certificates/name/version, but here we have certificates/issuers/name/version.
# Issuers are not versioned.
""":rtype: str"""
return self._vault_id.version
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------

from ._shared import parse_key_vault_id, KeyVaultResourceId


def parse_key_vault_certificate_id(source_id):
# type: (str) -> KeyVaultResourceId
"""Parses a certificate's full ID into a class with parsed contents as attributes.
:param str source_id: the full original identifier of a certificate
:returns: Returns a parsed certificate ID as a :class:`KeyVaultResourceId`
:rtype: ~azure.keyvault.certificates.KeyVaultResourceId
:raises: ValueError
Example:
.. literalinclude:: ../tests/test_parse_id.py
:start-after: [START parse_key_vault_certificate_id]
:end-before: [END parse_key_vault_certificate_id]
:language: python
:caption: Parse a certificate's ID
:dedent: 8
"""
parsed_id = parse_key_vault_id(source_id)

return KeyVaultResourceId(
name=parsed_id.name, source_id=parsed_id.source_id, vault_url=parsed_id.vault_url, version=parsed_id.version
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
from collections import namedtuple

try:
import urllib.parse as parse
except ImportError:
# pylint:disable=import-error
import urlparse as parse # type: ignore

from typing import TYPE_CHECKING
from .challenge_auth_policy import ChallengeAuthPolicy, ChallengeAuthPolicyBase
from .client_base import KeyVaultClientBase
from .http_challenge import HttpChallenge
from . import http_challenge_cache as HttpChallengeCache

if TYPE_CHECKING:
# pylint: disable=unused-import
from typing import Optional


__all__ = [
"ChallengeAuthPolicy",
Expand All @@ -24,25 +27,45 @@
"KeyVaultClientBase",
]

_VaultId = namedtuple("VaultId", ["vault_url", "collection", "name", "version"])
class KeyVaultResourceId():
"""Represents a Key Vault identifier and its parsed contents.
:param str source_id: The complete identifier received from Key Vault
:param str vault_url: The vault URL
:param str name: The name extracted from the ID
:param str version: The version extracted from the ID
"""

def __init__(
self,
source_id, # type: str
vault_url, # type: str
name, # type: str
version=None # type: Optional[str]
):
self.source_id = source_id
self.vault_url = vault_url
self.name = name
self.version = version


def parse_vault_id(url):
def parse_key_vault_id(source_id):
# type: (str) -> KeyVaultResourceId
try:
parsed_uri = parse.urlparse(url)
parsed_uri = parse.urlparse(source_id)
except Exception: # pylint: disable=broad-except
raise ValueError("'{}' is not not a valid url".format(url))
raise ValueError("'{}' is not not a valid ID".format(source_id))
if not (parsed_uri.scheme and parsed_uri.hostname):
raise ValueError("'{}' is not not a valid url".format(url))
raise ValueError("'{}' is not not a valid ID".format(source_id))

path = list(filter(None, parsed_uri.path.split("/")))

if len(path) < 2 or len(path) > 3:
raise ValueError("'{}' is not not a valid vault url".format(url))
raise ValueError("'{}' is not not a valid vault ID".format(source_id))

return _VaultId(
return KeyVaultResourceId(
source_id=source_id,
vault_url="{}://{}".format(parsed_uri.scheme, parsed_uri.hostname),
collection=path[0],
name=path[1],
version=path[2] if len(path) == 3 else None,
)
Expand Down
Loading

0 comments on commit 2635f65

Please sign in to comment.