Skip to content

Commit

Permalink
[Key Vault] Merge hotfix/keyvault-verify with main (Azure#26384)
Browse files Browse the repository at this point in the history
  • Loading branch information
mccoyp authored Sep 22, 2022
1 parent 0e883ff commit fe68412
Show file tree
Hide file tree
Showing 208 changed files with 4,516 additions and 4,091 deletions.
1 change: 1 addition & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@
"myacr",
"mydirectory",
"myfile",
"myvault",
"nazsdk",
"nbytes",
"noarch",
Expand Down
9 changes: 8 additions & 1 deletion sdk/keyvault/azure-keyvault-administration/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Release History

## 4.2.0b1 (Unreleased)
## 4.3.0b1 (Unreleased)

### Features Added

Expand All @@ -12,6 +12,13 @@
- Updated minimum `azure-core` version to 1.24.0
- Updated minimum `msrest` version to 0.7.1

## 4.2.0 (2022-09-19)

### Breaking Changes
- Clients verify the challenge resource matches the vault domain. This should affect few customers,
who can provide `verify_challenge_resource=False` to client constructors to disable.
See https://aka.ms/azsdk/blog/vault-uri for more information.

## 4.1.1 (2022-08-11)

### Other Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@ class KeyVaultAccessControlClient(KeyVaultClientBase):
"""Manages role-based access to Azure Key Vault.
:param str vault_url: URL of the vault the client will manage. This is also called the vault's "DNS Name".
:param credential: an object which can provide an access token for the vault, such as a credential from
You should validate that this URL references a valid Key Vault or Managed HSM resource.
See https://aka.ms/azsdk/blog/vault-uri for details.
:param credential: An object which can provide an access token for the vault, such as a credential from
:mod:`azure.identity`
:type credential: :class:`~azure.core.credentials.TokenCredential`
:keyword api_version: Version of the service API to use. Defaults to the most recent.
:paramtype api_version: ~azure.keyvault.administration.ApiVersion
:keyword bool verify_challenge_resource: Whether to verify the authentication challenge resource matches the Key
Vault or Managed HSM domain. Defaults to True.
"""

# pylint:disable=protected-access
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,16 @@ class KeyVaultBackupClient(KeyVaultClientBase):
"""Performs Key Vault backup and restore operations.
:param str vault_url: URL of the vault on which the client will operate. This is also called the vault's "DNS Name".
:param credential: an object which can provide an access token for the vault, such as a credential from
You should validate that this URL references a valid Key Vault or Managed HSM resource.
See https://aka.ms/azsdk/blog/vault-uri for details.
:param credential: An object which can provide an access token for the vault, such as a credential from
:mod:`azure.identity`
:type credential: :class:`~azure.core.credentials.TokenCredential`
:keyword api_version: Version of the service API to use. Defaults to the most recent.
:paramtype api_version: ~azure.keyvault.administration.ApiVersion
:keyword bool verify_challenge_resource: Whether to verify the authentication challenge resource matches the Key
Vault or Managed HSM domain. Defaults to True.
"""

# pylint:disable=protected-access
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import time
from typing import TYPE_CHECKING
from urllib.parse import urlparse

from azure.core.pipeline.policies import AsyncBearerTokenCredentialPolicy

Expand All @@ -36,6 +37,7 @@ def __init__(self, credential: "AsyncTokenCredential", *scopes: str, **kwargs: "
super().__init__(credential, *scopes, **kwargs)
self._credential = credential
self._token = None # type: Optional[AccessToken]
self._verify_challenge_resource = kwargs.pop("verify_challenge_resource", True)

async def on_request(self, request: "PipelineRequest") -> None:
_enforce_tls(request)
Expand Down Expand Up @@ -69,6 +71,19 @@ async def on_challenge(self, request: "PipelineRequest", response: "PipelineResp
except ValueError:
return False

if self._verify_challenge_resource:
resource_domain = urlparse(scope).netloc
if not resource_domain:
raise ValueError(f"The challenge contains invalid scope '{scope}'.")

request_domain = urlparse(request.http_request.url).netloc
if not request_domain.lower().endswith(f".{resource_domain.lower()}"):
raise ValueError(
f"The challenge resource '{resource_domain}' does not match the requested domain. Pass "
"`verify_challenge_resource=False` to your client's constructor to disable this verification. "
"See https://aka.ms/azsdk/blog/vault-uri for more information."
)

body = request.context.pop("key_vault_request_data", None)
request.http_request.set_text_body(body) # no-op when text is None
await self.authorize_request(request, scope, tenant_id=challenge.tenant_id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ def __init__(self, vault_url: str, credential: "AsyncTokenCredential", **kwargs:
}
)

verify_challenge = kwargs.pop("verify_challenge_resource", True)
self._client = _KeyVaultClient(
api_version=api_version,
authentication_policy=AsyncChallengeAuthPolicy(credential),
authentication_policy=AsyncChallengeAuthPolicy(credential, verify_challenge_resource=verify_challenge),
sdk_moniker=SDK_MONIKER,
http_logging_policy=http_logging_policy,
**kwargs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""

import time
from urllib.parse import urlparse

from azure.core.exceptions import ServiceRequestError
from azure.core.pipeline import PipelineRequest
Expand Down Expand Up @@ -63,6 +64,7 @@ def __init__(self, credential, *scopes, **kwargs):
super(ChallengeAuthPolicy, self).__init__(credential, *scopes, **kwargs)
self._credential = credential
self._token = None # type: Optional[AccessToken]
self._verify_challenge_resource = kwargs.pop("verify_challenge_resource", True)

def on_request(self, request):
# type: (PipelineRequest) -> None
Expand Down Expand Up @@ -97,6 +99,19 @@ def on_challenge(self, request, response):
except ValueError:
return False

if self._verify_challenge_resource:
resource_domain = urlparse(scope).netloc
if not resource_domain:
raise ValueError(f"The challenge contains invalid scope '{scope}'.")

request_domain = urlparse(request.http_request.url).netloc
if not request_domain.lower().endswith(f".{resource_domain.lower()}"):
raise ValueError(
f"The challenge resource '{resource_domain}' does not match the requested domain. Pass "
"`verify_challenge_resource=False` to your client's constructor to disable this verification. "
"See https://aka.ms/azsdk/blog/vault-uri for more information."
)

body = request.context.pop("key_vault_request_data", None)
request.http_request.set_text_body(body) # no-op when text is None
self.authorize_request(request, scope, tenant_id=challenge.tenant_id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ def __init__(self, vault_url, credential, **kwargs):
{"x-ms-keyvault-network-info", "x-ms-keyvault-region", "x-ms-keyvault-service-version"}
)

verify_challenge = kwargs.pop("verify_challenge_resource", True)
self._client = _KeyVaultClient(
api_version=api_version,
authentication_policy=ChallengeAuthPolicy(credential),
authentication_policy=ChallengeAuthPolicy(credential, verify_challenge_resource=verify_challenge),
sdk_moniker=SDK_MONIKER,
http_logging_policy=http_logging_policy,
**kwargs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
# Licensed under the MIT License.
# ------------------------------------

VERSION = "4.2.0b1"
VERSION = "4.3.0b1"
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,16 @@ class KeyVaultAccessControlClient(AsyncKeyVaultClientBase):
"""Manages role-based access to Azure Key Vault.
:param str vault_url: URL of the vault the client will manage. This is also called the vault's "DNS Name".
:param credential: an object which can provide an access token for the vault, such as a credential from
:mod:`azure.identity`
You should validate that this URL references a valid Key Vault or Managed HSM resource.
See https://aka.ms/azsdk/blog/vault-uri for details.
:param credential: An object which can provide an access token for the vault, such as a credential from
:mod:`azure.identity.aio`
:type credential: :class:`~azure.core.credentials_async.AsyncTokenCredential`
:keyword api_version: Version of the service API to use. Defaults to the most recent.
:paramtype api_version: ~azure.keyvault.administration.ApiVersion
:keyword bool verify_challenge_resource: Whether to verify the authentication challenge resource matches the Key
Vault or Managed HSM domain. Defaults to True.
"""

# pylint:disable=protected-access
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@ class KeyVaultBackupClient(AsyncKeyVaultClientBase):
"""Performs Key Vault backup and restore operations.
:param str vault_url: URL of the vault on which the client will operate. This is also called the vault's "DNS Name".
:param credential: an object which can provide an access token for the vault, such as a credential from
You should validate that this URL references a valid Key Vault or Managed HSM resource.
See https://aka.ms/azsdk/blog/vault-uri for details.
:param credential: An object which can provide an access token for the vault, such as a credential from
:mod:`azure.identity.aio`
:type credential: :class:`~azure.core.credentials_async.AsyncTokenCredential`
:keyword api_version: Version of the service API to use. Defaults to the most recent.
:paramtype api_version: ~azure.keyvault.administration.ApiVersion
:keyword bool verify_challenge_resource: Whether to verify the authentication challenge resource matches the Key
Vault or Managed HSM domain. Defaults to True.
"""

# pylint:disable=protected-access
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class BaseClientPreparer(AzureRecordedTestCase):
def __init__(self, **kwargs) -> None:
hsm_playback_url = "https://managedhsmvaultname.vault.azure.net"
hsm_playback_url = "https://managedhsmvaultname.managedhsm.azure.net"
container_playback_uri = "https://storagename.blob.core.windows.net/container"
playback_sas_token = "fake-sas"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class BaseClientPreparer(AzureRecordedTestCase):
def __init__(self, **kwargs) -> None:
hsm_playback_url = "https://managedhsmvaultname.vault.azure.net"
hsm_playback_url = "https://managedhsmvaultname.managedhsm.azure.net"
container_playback_uri = "https://storagename.blob.core.windows.net/container"
playback_sas_token = "fake-sas"

Expand Down
4 changes: 2 additions & 2 deletions sdk/keyvault/azure-keyvault-administration/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def add_sanitizers(test_proxy):
azure_keyvault_url = azure_keyvault_url.rstrip("/")
keyvault_tenant_id = os.getenv("keyvault_tenant_id", "keyvault_tenant_id")
keyvault_subscription_id = os.getenv("keyvault_subscription_id", "keyvault_subscription_id")
azure_managedhsm_url = os.environ.get("azure_managedhsm_url","https://managedhsmvaultname.vault.azure.net")
azure_managedhsm_url = os.environ.get("azure_managedhsm_url","https://managedhsmvaultname.managedhsm.azure.net")
azure_managedhsm_url = azure_managedhsm_url.rstrip("/")
azure_attestation_uri = os.environ.get("azure_keyvault_attestation_url","https://fakeattestation.azurewebsites.net")
azure_attestation_uri = azure_attestation_uri.rstrip('/')
Expand All @@ -33,7 +33,7 @@ def add_sanitizers(test_proxy):
add_general_regex_sanitizer(regex=azure_keyvault_url, value="https://vaultname.vault.azure.net")
add_general_regex_sanitizer(regex=keyvault_tenant_id, value="00000000-0000-0000-0000-000000000000")
add_general_regex_sanitizer(regex=keyvault_subscription_id, value="00000000-0000-0000-0000-000000000000")
add_general_regex_sanitizer(regex=azure_managedhsm_url,value="https://managedhsmvaultname.vault.azure.net")
add_general_regex_sanitizer(regex=azure_managedhsm_url,value="https://managedhsmvaultname.managedhsm.azure.net")
add_general_regex_sanitizer(regex=azure_attestation_uri,value="https://fakeattestation.azurewebsites.net")
add_general_regex_sanitizer(regex=storage_name, value = "blob_storage_account_name")
add_general_regex_sanitizer(regex=storage_endpoint_suffix, value = "keyvault_endpoint_suffix")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"Entries": [
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleDefinitions?api-version=7.2",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleDefinitions?api-version=7.2",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -200,7 +200,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleDefinitions?api-version=7.2",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleDefinitions?api-version=7.2",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -490,7 +490,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.2",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.2",
"RequestMethod": "PUT",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -531,7 +531,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.2",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.2",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -566,7 +566,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments?api-version=7.2",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments?api-version=7.2",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -645,7 +645,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.2",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.2",
"RequestMethod": "DELETE",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -680,7 +680,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments?api-version=7.2",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments?api-version=7.2",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"Entries": [
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleDefinitions?api-version=7.3",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleDefinitions?api-version=7.3",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -200,7 +200,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleDefinitions?api-version=7.3",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleDefinitions?api-version=7.3",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -490,7 +490,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.3",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.3",
"RequestMethod": "PUT",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -531,7 +531,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.3",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.3",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -566,7 +566,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments?api-version=7.3",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments?api-version=7.3",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -645,7 +645,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.3",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments/some-uuid?api-version=7.3",
"RequestMethod": "DELETE",
"RequestHeaders": {
"Accept": "application/json",
Expand Down Expand Up @@ -680,7 +680,7 @@
}
},
{
"RequestUri": "https://managedhsmvaultname.vault.azure.net/providers/Microsoft.Authorization/roleAssignments?api-version=7.3",
"RequestUri": "https://managedhsmvaultname.managedhsm.azure.net/providers/Microsoft.Authorization/roleAssignments?api-version=7.3",
"RequestMethod": "GET",
"RequestHeaders": {
"Accept": "application/json",
Expand Down
Loading

0 comments on commit fe68412

Please sign in to comment.