|
31 | 31 | RequiredArgumentMissingError) |
32 | 32 | from azure.cli.core.commands.validators import validate_tag |
33 | 33 | from azure.cli.core.util import CLIError |
34 | | -from azure.mgmt.core.tools import is_valid_resource_id |
| 34 | +from azure.mgmt.core.tools import is_valid_resource_id, parse_resource_id |
35 | 35 | from knack.log import get_logger |
36 | 36 |
|
37 | 37 | logger = get_logger(__name__) |
@@ -701,26 +701,100 @@ def validate_crg_id(namespace): |
701 | 701 | def validate_azure_keyvault_kms_key_id(namespace): |
702 | 702 | key_id = namespace.azure_keyvault_kms_key_id |
703 | 703 | if key_id: |
704 | | - err_msg = ( |
705 | | - "--azure-keyvault-kms-key-id is not a valid Key Vault key ID. " |
706 | | - "See https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name" # pylint: disable=line-too-long |
| 704 | + # Check if PMK (Platform-Managed Keys) is enabled |
| 705 | + is_pmk_enabled = ( |
| 706 | + hasattr(namespace, 'kms_infrastructure_encryption') and |
| 707 | + namespace.kms_infrastructure_encryption == "Enabled" |
707 | 708 | ) |
708 | 709 |
|
709 | 710 | https_prefix = "https://" |
710 | 711 | if not key_id.startswith(https_prefix): |
| 712 | + err_msg = ( |
| 713 | + "--azure-keyvault-kms-key-id is not a valid Key Vault key ID. " |
| 714 | + "See https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name" # pylint: disable=line-too-long |
| 715 | + ) |
711 | 716 | raise InvalidArgumentValueError(err_msg) |
712 | 717 |
|
713 | 718 | segments = key_id[len(https_prefix):].split("/") |
714 | | - if len(segments) != 4 or segments[1] != "keys": |
715 | | - raise InvalidArgumentValueError(err_msg) |
| 719 | + |
| 720 | + if is_pmk_enabled: |
| 721 | + # PMK enabled (K2P): Only accept versionless key ID (3 segments: vault.net/keys/key-name) |
| 722 | + if len(segments) != 3 or segments[1] != "keys": |
| 723 | + err_msg = ( |
| 724 | + "--azure-keyvault-kms-key-id is not a valid versionless Key Vault key ID for PMK. " |
| 725 | + "Valid format is https://{key-vault-url}/keys/{key-name}. " |
| 726 | + "See https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name" # pylint: disable=line-too-long |
| 727 | + ) |
| 728 | + raise InvalidArgumentValueError(err_msg) |
| 729 | + else: |
| 730 | + # PMK disabled (KMS v2): Accept versioned key ID (4 segments) |
| 731 | + if len(segments) != 4 or segments[1] != "keys": |
| 732 | + err_msg = ( |
| 733 | + "--azure-keyvault-kms-key-id is not a valid Key Vault key ID. " |
| 734 | + "See https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#vault-name-and-object-name" # pylint: disable=line-too-long |
| 735 | + ) |
| 736 | + raise InvalidArgumentValueError(err_msg) |
716 | 737 |
|
717 | 738 |
|
718 | 739 | def validate_azure_keyvault_kms_key_vault_resource_id(namespace): |
719 | 740 | key_vault_resource_id = namespace.azure_keyvault_kms_key_vault_resource_id |
720 | | - if key_vault_resource_id is None or key_vault_resource_id == '': |
| 741 | + |
| 742 | + # Check if PMK (Platform-Managed Keys) is enabled |
| 743 | + is_pmk_enabled = ( |
| 744 | + hasattr(namespace, 'kms_infrastructure_encryption') and |
| 745 | + namespace.kms_infrastructure_encryption == "Enabled" |
| 746 | + ) |
| 747 | + |
| 748 | + # Check if CMK (Customer-Managed Keys) is enabled |
| 749 | + is_cmk_enabled = ( |
| 750 | + hasattr(namespace, 'enable_azure_keyvault_kms') and |
| 751 | + namespace.enable_azure_keyvault_kms |
| 752 | + ) |
| 753 | + |
| 754 | + # Validate key vault resource ID requirements |
| 755 | + key_vault_missing = key_vault_resource_id is None or key_vault_resource_id == '' |
| 756 | + |
| 757 | + if not is_cmk_enabled: |
| 758 | + if key_vault_missing: |
| 759 | + return |
| 760 | + raise RequiredArgumentMissingError( |
| 761 | + '"--azure-keyvault-kms-key-vault-resource-id" requires "--enable-azure-keyvault-kms".' |
| 762 | + ) |
| 763 | + |
| 764 | + if key_vault_missing: |
| 765 | + if is_pmk_enabled: |
| 766 | + raise RequiredArgumentMissingError( |
| 767 | + "--azure-keyvault-kms-key-vault-resource-id is required when " |
| 768 | + "--kms-infrastructure-encryption is set to Enabled (PMK)." |
| 769 | + ) |
721 | 770 | return |
| 771 | + |
722 | 772 | if not is_valid_resource_id(key_vault_resource_id): |
723 | | - raise InvalidArgumentValueError("--azure-keyvault-kms-key-vault-resource-id is not a valid Azure resource ID.") |
| 773 | + raise InvalidArgumentValueError( |
| 774 | + "--azure-keyvault-kms-key-vault-resource-id is not a valid Azure resource ID." |
| 775 | + ) |
| 776 | + |
| 777 | + try: |
| 778 | + parsed = parse_resource_id(key_vault_resource_id) |
| 779 | + provider = parsed.get('namespace', '').lower() |
| 780 | + if provider != 'microsoft.keyvault': |
| 781 | + raise InvalidArgumentValueError( |
| 782 | + "--azure-keyvault-kms-key-vault-resource-id must reference a " |
| 783 | + "Microsoft.KeyVault resource." |
| 784 | + ) |
| 785 | + resource_type = parsed.get('type', '').lower() |
| 786 | + if resource_type not in ['vaults', 'managedhsms']: |
| 787 | + raise InvalidArgumentValueError( |
| 788 | + "--azure-keyvault-kms-key-vault-resource-id must reference a Key Vault " |
| 789 | + "(vaults) or Managed HSM (managedHSMs)." |
| 790 | + ) |
| 791 | + except InvalidArgumentValueError: |
| 792 | + # Re-raise our validation errors |
| 793 | + raise |
| 794 | + except Exception as ex: |
| 795 | + raise InvalidArgumentValueError( |
| 796 | + f"--azure-keyvault-kms-key-vault-resource-id parsing failed: {str(ex)}" |
| 797 | + ) |
724 | 798 |
|
725 | 799 |
|
726 | 800 | def validate_bootstrap_container_registry_resource_id(namespace): |
|
0 commit comments