Skip to content

Commit

Permalink
[dataprotection] Adding support for CMK encryption settings (#7585)
Browse files Browse the repository at this point in the history
* CMK parameters added

* tests added

* Updated tests and added aliases for parameters

* updating test results

* cmk test updated

* added test for switching from UserAssigned to SystemAssigned identity-type

test updated

* Revert "added test for switching from UserAssigned to SystemAssigned identity-type"

This reverts commit a22734f.

* updating setup.py

---------

Co-authored-by: Kartik Mahajan (from Dev Box) <karmahajan@microsoft.com>
  • Loading branch information
Karmah24 and Kartik Mahajan (from Dev Box) authored May 10, 2024
1 parent 1f3e6e0 commit 5d48b18
Show file tree
Hide file tree
Showing 36 changed files with 5,969 additions and 28,949 deletions.
9 changes: 9 additions & 0 deletions src/dataprotection/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
Release History
===============
1.4.0
+++++
* Added support for cmk encryption on backup vault
* `az dataprotection backup-vault create ` Added parameters `--user-assigned-identities` to provide list of user assigned managed identities to backup-vault
* `az dataprotection backup-vault create ` Added parameters `--cmk-encryption-state`, `cmk-infrastructure-encryption`, `--cmk-encryption-key-uri`, `--cmk-identity-type`, `--cmk-user-assigned-identity-id` to enable cmk encryption on backup-vault
* `az dataprotection backup-vault update ` Added parameters `--user-assigned-identities` to update list of user assigned managed identities to backup-vault
* `az dataprotection backup-vault update ` Added parameters `--cmk-encryption-state`, `--cmk-encryption-key-uri`, `--cmk-identity-type`, `--cmk-user-assigned-identity-id` to update cmk encryption settings on backup-vault


1.3.0
+++++
* Added support for vaulted blob backup and restore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
#
# Code generated by aaz-dev-tools
# --------------------------------------------------------------------------------------------

# pylint: skip-file
# flake8: noqa

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class Create(AAZCommand):
:example: Create BackupVault With MSI
az dataprotection backup-vault create --type "systemAssigned" --location "WestUS" --azure-monitor-alerts-for-job-failures "Enabled" --storage-setting "[{type:'LocallyRedundant',datastore-type:'VaultStore'}]" --tags key1="val1" --resource-group "SampleResourceGroup" --vault-name "swaggerExample"
:example: Create BackupVault With CMK Encryption
az dataprotection backup-vault create -g "resourceGroupName" -v "vaultName" --location "eastasia" --storage-setting "[{type:'LocallyRedundant',datastore-type:'VaultStore'}]" --type "UserAssigned" --user-assigned-identities '{"/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/samplerg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/sampleuami":{}}' --cmk-encryption-key-uri "https://samplekvazbckp.vault.azure.net/keys/testkey/3cd5235ad6ac4c11b40a6f35444bcbe1" --cmk-encryption-state "Enabled" --cmk-identity-type "UserAssigned" --cmk-infrastructure-encryption "Enabled" --cmk-user-assigned-identity-id "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/samplerg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/sampleuami"
"""

_aaz_info = {
Expand Down Expand Up @@ -67,6 +70,38 @@ def _build_arguments_schema(cls, *args, **kwargs):
enum={"Disabled": "Disabled", "Enabled": "Enabled"},
)

# define Arg Group "EncryptionSettings"

_args_schema = cls._args_schema
_args_schema.cmk_infrastructure_encryption = AAZStrArg(
options=["--cmk-infra-encryption", "--cmk-infrastructure-encryption"],
arg_group="EncryptionSettings",
help="Enable/Disable infrastructure encryption with CMK on this vault. Infrastructure encryption must be configured only when creating the vault.",
enum={"Disabled": "Disabled", "Enabled": "Enabled"},
)
_args_schema.cmk_user_assigned_identity_id = AAZStrArg(
options=["--cmk-uami", "--cmk-user-assigned-identity-id"],
arg_group="EncryptionSettings",
help="This parameter is required if the identity type is UserAssigned. Add the user assigned managed identity id to be used which has access permissions to the Key Vault.",
)
_args_schema.cmk_identity_type = AAZStrArg(
options=["--cmk-identity-type"],
arg_group="EncryptionSettings",
help="The identity type to be used for CMK encryption - SystemAssigned or UserAssigned Identity.",
enum={"SystemAssigned": "SystemAssigned", "UserAssigned": "UserAssigned"},
)
_args_schema.cmk_encryption_key_uri = AAZStrArg(
options=["--cmk-encryption-key-uri"],
arg_group="EncryptionSettings",
help="The Key URI of the CMK key to be used for encryption. To enable auto-rotation of keys, exclude the version component from the Key URI.",
)
_args_schema.cmk_encryption_state = AAZStrArg(
options=["--cmk-encryption-state"],
arg_group="EncryptionSettings",
help="Enable CMK encryption state for a Backup Vault.",
enum={"Disabled": "Disabled", "Enabled": "Enabled", "Inconsistent": "Inconsistent"},
)

# define Arg Group "FeatureSettings"

_args_schema = cls._args_schema
Expand All @@ -83,7 +118,17 @@ def _build_arguments_schema(cls, *args, **kwargs):
_args_schema.type = AAZStrArg(
options=["--type"],
arg_group="Identity",
help="The identityType which can be either SystemAssigned or None",
help="The identityType which can be \"SystemAssigned\", \"UserAssigned\", \"SystemAssigned,UserAssigned\" or \"None\"",
)
_args_schema.user_assigned_identities = AAZDictArg(
options=["--uami", "--user-assigned-identities"],
arg_group="Identity",
help="Gets or sets the user assigned identities.",
)

user_assigned_identities = cls._args_schema.user_assigned_identities
user_assigned_identities.Element = AAZObjectArg(
blank={},
)

# define Arg Group "Monitoring Settings Azure Monitor Alert Settings"
Expand Down Expand Up @@ -290,6 +335,11 @@ def content(self):
identity = _builder.get(".identity")
if identity is not None:
identity.set_prop("type", AAZStrType, ".type")
identity.set_prop("userAssignedIdentities", AAZDictType, ".user_assigned_identities")

user_assigned_identities = _builder.get(".identity.userAssignedIdentities")
if user_assigned_identities is not None:
user_assigned_identities.set_elements(AAZObjectType, ".")

properties = _builder.get(".properties")
if properties is not None:
Expand Down Expand Up @@ -321,9 +371,26 @@ def content(self):

security_settings = _builder.get(".properties.securitySettings")
if security_settings is not None:
security_settings.set_prop("encryptionSettings", AAZObjectType)
security_settings.set_prop("immutabilitySettings", AAZObjectType)
security_settings.set_prop("softDeleteSettings", AAZObjectType)

encryption_settings = _builder.get(".properties.securitySettings.encryptionSettings")
if encryption_settings is not None:
encryption_settings.set_prop("infrastructureEncryption", AAZStrType, ".cmk_infrastructure_encryption")
encryption_settings.set_prop("kekIdentity", AAZObjectType)
encryption_settings.set_prop("keyVaultProperties", AAZObjectType)
encryption_settings.set_prop("state", AAZStrType, ".cmk_encryption_state")

kek_identity = _builder.get(".properties.securitySettings.encryptionSettings.kekIdentity")
if kek_identity is not None:
kek_identity.set_prop("identityId", AAZStrType, ".cmk_user_assigned_identity_id")
kek_identity.set_prop("identityType", AAZStrType, ".cmk_identity_type")

key_vault_properties = _builder.get(".properties.securitySettings.encryptionSettings.keyVaultProperties")
if key_vault_properties is not None:
key_vault_properties.set_prop("keyUri", AAZStrType, ".cmk_encryption_key_uri")

immutability_settings = _builder.get(".properties.securitySettings.immutabilitySettings")
if immutability_settings is not None:
immutability_settings.set_prop("state", AAZStrType, ".immutability_state")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ def _build_arguments_schema(cls, *args, **kwargs):

def _execute_operations(self):
self.pre_operations()
condition_0 = has_value(self.ctx.args.resource_group) and has_value(self.ctx.subscription_id)
condition_1 = has_value(self.ctx.subscription_id) and has_value(self.ctx.args.resource_group) is not True
condition_0 = has_value(self.ctx.subscription_id) and has_value(self.ctx.args.resource_group) is not True
condition_1 = has_value(self.ctx.args.resource_group) and has_value(self.ctx.subscription_id)
if condition_0:
self.BackupVaultsGetInResourceGroup(ctx=self.ctx)()
if condition_1:
self.BackupVaultsGetInSubscription(ctx=self.ctx)()
if condition_1:
self.BackupVaultsGetInResourceGroup(ctx=self.ctx)()
self.post_operations()

@register_callback
Expand All @@ -75,7 +75,7 @@ def _output(self, *args, **kwargs):
next_link = self.deserialize_output(self.ctx.vars.instance.next_link)
return result, next_link

class BackupVaultsGetInResourceGroup(AAZHttpOperation):
class BackupVaultsGetInSubscription(AAZHttpOperation):
CLIENT_TYPE = "MgmtClient"

def __call__(self, *args, **kwargs):
Expand All @@ -89,7 +89,7 @@ def __call__(self, *args, **kwargs):
@property
def url(self):
return self.client.format_url(
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DataProtection/backupVaults",
"/subscriptions/{subscriptionId}/providers/Microsoft.DataProtection/backupVaults",
**self.url_parameters
)

Expand All @@ -104,10 +104,6 @@ def error_format(self):
@property
def url_parameters(self):
parameters = {
**self.serialize_url_param(
"resourceGroupName", self.ctx.args.resource_group,
required=True,
),
**self.serialize_url_param(
"subscriptionId", self.ctx.subscription_id,
required=True,
Expand Down Expand Up @@ -383,7 +379,7 @@ def _build_schema_on_200(cls):

return cls._schema_on_200

class BackupVaultsGetInSubscription(AAZHttpOperation):
class BackupVaultsGetInResourceGroup(AAZHttpOperation):
CLIENT_TYPE = "MgmtClient"

def __call__(self, *args, **kwargs):
Expand All @@ -397,7 +393,7 @@ def __call__(self, *args, **kwargs):
@property
def url(self):
return self.client.format_url(
"/subscriptions/{subscriptionId}/providers/Microsoft.DataProtection/backupVaults",
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DataProtection/backupVaults",
**self.url_parameters
)

Expand All @@ -412,6 +408,10 @@ def error_format(self):
@property
def url_parameters(self):
parameters = {
**self.serialize_url_param(
"resourceGroupName", self.ctx.args.resource_group,
required=True,
),
**self.serialize_url_param(
"subscriptionId", self.ctx.subscription_id,
required=True,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,36 @@ def _build_arguments_schema(cls, *args, **kwargs):
enum={"Disabled": "Disabled", "Enabled": "Enabled"},
)

# define Arg Group "EncryptionSettings"

_args_schema = cls._args_schema
_args_schema.cmk_user_assigned_identity_id = AAZStrArg(
options=["--cmk-uami", "--cmk-user-assigned-identity-id"],
arg_group="EncryptionSettings",
help="This parameter is required if the identity type is UserAssigned. Add the user assigned managed identity id to be used which has access permissions to the Key Vault.",
nullable=True,
)
_args_schema.cmk_identity_type = AAZStrArg(
options=["--cmk-identity-type"],
arg_group="EncryptionSettings",
help="The identity type to be used for CMK encryption - SystemAssigned or UserAssigned Identity.",
nullable=True,
enum={"SystemAssigned": "SystemAssigned", "UserAssigned": "UserAssigned"},
)
_args_schema.cmk_encryption_key_uri = AAZStrArg(
options=["--cmk-encryption-key-uri"],
arg_group="EncryptionSettings",
help="The key uri of the Customer Managed Key",
nullable=True,
)
_args_schema.cmk_encryption_state = AAZStrArg(
options=["--cmk-encryption-state"],
arg_group="EncryptionSettings",
help="Enable CMK encryption state for a Backup Vault.",
nullable=True,
enum={"Disabled": "Disabled", "Enabled": "Enabled", "Inconsistent": "Inconsistent"},
)

# define Arg Group "FeatureSettings"

_args_schema = cls._args_schema
Expand All @@ -85,9 +115,21 @@ def _build_arguments_schema(cls, *args, **kwargs):
_args_schema.type = AAZStrArg(
options=["--type"],
arg_group="Identity",
help="The identityType which can be either SystemAssigned or None",
help="The identityType which can be \"SystemAssigned\", \"UserAssigned\", \"SystemAssigned,UserAssigned\" or \"None\"",
nullable=True,
)
_args_schema.user_assigned_identities = AAZDictArg(
options=["--uami", "--user-assigned-identities"],
arg_group="Identity",
help="Gets or sets the user assigned identities.",
nullable=True,
)

user_assigned_identities = cls._args_schema.user_assigned_identities
user_assigned_identities.Element = AAZObjectArg(
nullable=True,
blank={},
)

# define Arg Group "Monitoring Settings Azure Monitor Alert Settings"

Expand Down Expand Up @@ -122,7 +164,7 @@ def _build_arguments_schema(cls, *args, **kwargs):
options=["--resource-guard-operation-requests"],
singular_options=["--operation-requests"],
arg_group="Properties",
help="Critical operation request which is protected by the resourceGuard",
help="ResourceGuardOperationRequests on which LAC check will be performed",
nullable=True,
)

Expand Down Expand Up @@ -402,6 +444,11 @@ def _update_instance(self, instance):
identity = _builder.get(".identity")
if identity is not None:
identity.set_prop("type", AAZStrType, ".type")
identity.set_prop("userAssignedIdentities", AAZDictType, ".user_assigned_identities")

user_assigned_identities = _builder.get(".identity.userAssignedIdentities")
if user_assigned_identities is not None:
user_assigned_identities.set_elements(AAZObjectType, ".")

properties = _builder.get(".properties")
if properties is not None:
Expand Down Expand Up @@ -437,9 +484,25 @@ def _update_instance(self, instance):

security_settings = _builder.get(".properties.securitySettings")
if security_settings is not None:
security_settings.set_prop("encryptionSettings", AAZObjectType)
security_settings.set_prop("immutabilitySettings", AAZObjectType)
security_settings.set_prop("softDeleteSettings", AAZObjectType)

encryption_settings = _builder.get(".properties.securitySettings.encryptionSettings")
if encryption_settings is not None:
encryption_settings.set_prop("kekIdentity", AAZObjectType)
encryption_settings.set_prop("keyVaultProperties", AAZObjectType)
encryption_settings.set_prop("state", AAZStrType, ".cmk_encryption_state")

kek_identity = _builder.get(".properties.securitySettings.encryptionSettings.kekIdentity")
if kek_identity is not None:
kek_identity.set_prop("identityId", AAZStrType, ".cmk_user_assigned_identity_id")
kek_identity.set_prop("identityType", AAZStrType, ".cmk_identity_type")

key_vault_properties = _builder.get(".properties.securitySettings.encryptionSettings.keyVaultProperties")
if key_vault_properties is not None:
key_vault_properties.set_prop("keyUri", AAZStrType, ".cmk_encryption_key_uri")

immutability_settings = _builder.get(".properties.securitySettings.immutabilitySettings")
if immutability_settings is not None:
immutability_settings.set_prop("state", AAZStrType, ".immutability_state")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"azext.minCliCoreVersion": "2.51.0"
"azext.minCliCoreVersion": "2.57.0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ def pre_operations(self):
if has_value(self.ctx.args.tenant_id):
# ValueError is raised when providing an incorrect tenant ID. Capturing it in a try block does not work.
self.ctx.update_aux_tenants(str(self.ctx.args.tenant_id))
if has_value(self.ctx.args.cmk_identity_type):
cmk_identity_type = self.ctx.args.cmk_identity_type.to_serialized_data()
if cmk_identity_type == "SystemAssigned":
self.ctx.args.cmk_user_assigned_identity_id = None
1 change: 1 addition & 0 deletions src/dataprotection/azext_dataprotection/manual/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
ForbiddenError,
UnauthorizedError
)
# from azure.cli.core.aaz import has_value
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.cli.command_modules.role.custom import list_role_assignments, create_role_assignment
from knack.log import get_logger
Expand Down
Loading

0 comments on commit 5d48b18

Please sign in to comment.