Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Key Vault] Add ID parsing method for certificates #14518

Merged
merged 1 commit into from
Oct 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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