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

AzExt - Adding support for the v2021-09-01-preview API #1739

Merged
merged 6 commits into from
Oct 5, 2021
Merged

AzExt - Adding support for the v2021-09-01-preview API #1739

merged 6 commits into from
Oct 5, 2021

Conversation

Makdaam
Copy link
Contributor

@Makdaam Makdaam commented Sep 14, 2021

disk encryption sets, sdn selection, encryption at host options

Which issue this PR addresses:

Fixes https://msazure.visualstudio.com/AzureRedHatOpenShift/_workitems/edit/7403671/

What this PR does / why we need it:

This PR switches the Azure CLI extension to the 2021-09-01-preview API, address the additional create parameters. We need it for customers who want to use the disk encryption features and have the feature flag enabled on their subscription to access the preview API. The plan is to give those customers an extension while the API is in preview, and keep it in parallel to the officiall AzureCLI command.

I didn't find any documentation on supporting multiple API versions inside an AzureCLI extension, so I went ahead with updating it to latest. This means that the extension can't be used anymore as a step in AzureCLI command development directly.

mostly changed:
create command, parameters, added validation

unchanged:
delete, list, list-credentials, show commands, update command

Rationale for not changing the update command:

  • Migration between SDN types can't be done reliably and isn't managed by any OCP operator - option shouldn't be changable
  • Swapping a disk from under a VM to one with a different Disk Encryption Set is a non-trivial operation, also this setting in aro could be misused instead of the key refresh functionality built into Disk Encryption Sets - not allowing the customer to change DES
  • Encryption At Host requires VM reprovisioning, changing the setting doesn't enable/disable it for live VMs - this should be managed via Machine objects

Test plan for issue:

  1. Install the azure extension with make az
  2. Follow the "how to create ARO cluster" official documentation until right before the az aro create command.
  3. Run the following create commands - they should all fail validation
az aro create  --resource-group $RESOURCEGROUP  --name $CLUSTER  --vnet aro-vnet  --master-subnet master-subnet   --worker-subnet worker-subnet --disk-encryption-set 'notaresourceid'

az aro create  --resource-group $RESOURCEGROUP  --name $CLUSTER  --vnet aro-vnet  --master-subnet master-subnet   --worker-subnet worker-subnet --disk-encryption-set '/subscriptions/123/resourceGroups/v4-eastus/providers/Microsoft.Compute/diskEncryptionSets/nonexistentdiskencryptionset'

az aro create  --resource-group $RESOURCEGROUP  --name $CLUSTER  --vnet aro-vnet  --master-subnet master-subnet   --worker-subnet worker-subnet --master-encryption-at-host='notvalid'

az aro create  --resource-group $RESOURCEGROUP  --name $CLUSTER  --vnet aro-vnet  --master-subnet master-subnet   --worker-subnet worker-subnet --worker-encryption-at-host='notvalid'

az aro create  --resource-group $RESOURCEGROUP  --name $CLUSTER  --vnet aro-vnet  --master-subnet master-subnet   --worker-subnet worker-subnet --software-defined-network='notanetwork'
  1. Create and run the aro create command
  • set additional env variables
export KEYVAULT_NAME=$USER-enckv
export KEYVAULT_KEY_NAME=$USER-key
export DISK_ENCRYPTION_SET_NAME=$USER-des
  • create the KeyVault and Key

az keyvault create -n $KEYVAULT_NAME -g $RESOURCEGROUP -l $LOCATION --enable-purge-protection true --enable-soft-delete true

az keyvault key create --vault-name $KEYVAULT_NAME -n $KEYVAULT_KEY_NAME --protection software

KEYVAULT_ID=$(az keyvault show --name $KEYVAULT_NAME --query "[id]" -o tsv)

KEYVAULT_KEY_URL=$(az keyvault key show --vault-name $KEYVAULT_NAME --name $KEYVAULT_KEY_NAME --query "[key.kid]" -o tsv)
  • create the DES and add permissions to use the KeyVault
az disk-encryption-set create -n $DISK_ENCRYPTION_SET_NAME -l $LOCATION -g $RESOURCEGROUP --source-vault $KEYVAULT_ID --key-url $KEYVAULT_KEY_URL

DES_IDENTITY=$(az disk-encryption-set show -n $DISK_ENCRYPTION_SET_NAME -g $RESOURCEGROUP --query "[identity.principalId]" -o tsv)

az keyvault set-policy -n $KEYVAULT_NAME -g $RESOURCEGROUP --object-id $DES_IDENTITY --key-permissions wrapkey unwrapkey get
  • run the az aro create command
az aro create  --resource-group $RESOURCEGROUP  --name $CLUSTER  --vnet aro-vnet  --master-subnet master-subnet   --worker-subnet worker-subnet --disk-encryption-set $DES_ID

The create should complete with Success. You can check the encryption parameters on the vm disks, they should show that the encryption is customer controlled and should point to the right disk-encryption-set.

  1. Run az aro list -o table and az aro list, also the az aro show command should show exactly the same cluster document.
  2. Run az aro list-credentials -g $RESOURCEGROUP --name $CLUSTER and see if the credentials work in the web console
  3. Run az aro delete --resource-group $RESOURCEGROUP --name $CLUSTER --yes it should cleanly delete the cluster
  4. Remove the DES and Keyvault
az disk-encryption-set delete -n $DISK_ENCRYPTION_SET_NAME -g $RESOURCEGROUP
az keyvault delete -n $KEYVAULT_NAME -g $RESOURCEGROUP

clean up any Vnets and Subnets created to for cluster provisioning.

Is there any documentation that needs to be updated for this PR?

docs/disk-encryption-set.md was added to describe how to provision a disk-encryption-set and create a cluster

Edit after some dicussions:

  • we also need a clear documentation in docs.microsoft.com both for the How-To create and use the Disk Encryption Set, how it interacts with the "encryption at host" settings and what are the customer's responsibilities (they customer should know from day 1, that if they fail to maintain the keys their whole cluster will be broken beyond repair)

@Makdaam Makdaam added enhancement New feature or request ready-for-review size-medium Size medium labels Sep 15, 2021
@Makdaam Makdaam marked this pull request as ready for review September 15, 2021 11:09
@Makdaam
Copy link
Contributor Author

Makdaam commented Sep 17, 2021

Just to keep all notes in once place:

  • tested on local dev RP
  • tested on prod RP in eastus (the preview API is live, it's just a matter of using it)

petrkotas
petrkotas previously approved these changes Sep 17, 2021
Copy link
Member

@petrkotas petrkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very Good job. LGTM


c.argument('disk_encryption_set',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed with @Makdaam that encryption parameters need a clear documentation on docs.microsoft.com.
disk_encryption_set is providing customer keys and makes customer responsible for managing them. Without this option set, disks will get encrypted with Azure provided and rotated keys.

This will be documented later on.

@@ -279,6 +289,13 @@ def get_network_resources(cli_ctx, subnets, vnet):
return resources


def get_disk_encryption_resources(oc):
disk_encryption_set = oc.master_profile.disk_encryption_set_id
resources = set()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a discussion, the set() is used to keep code consistency even when there will be one object. This makes code more streamlined.

@25region
Copy link
Contributor

Tidied up documentation a bit.

mjudeikis
mjudeikis previously approved these changes Sep 22, 2021
Copy link
Contributor

@mjudeikis mjudeikis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provisional approval for this. Few nit questions

python/az/aro/azext_aro/_params.py Outdated Show resolved Hide resolved
help='ResourceID of the DiskEncryptionSet to be used for master and worker VMs.',
validator=validate_disk_encryption_set)
c.argument('master_encryption_at_host', arg_type=get_enum_type(['Enabled', 'Disabled']),
options_list=['--master-enc-at-host'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there reason we use --master-enc-at-host and not --master-encryption-at-host? Matches original flag name

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on using full name.

Also I see that az vm create uses --encryption-at-host argument as a boolean flag (either present or not, no value). If I read this code correctly our command is going to be --master-enc-at-host Enabled.

Maybe we also need to use it as boolean for simplicity? If present - send Enabled to the API, if not - send Disabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had master-encryption-at-host, but that doesn't pass validation since the parameter name is too long.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, found the linter rule, and at least one version of the parameter has to be <22 characters (not counting -- or - in front). I'm wondering if I should shorten the short versions even more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To sum up:

  • added long names and shortened the short names a bit
  • changed the param type to tri-state (so that you don't have to do "Enabled")
  • removed param validator because it's not needed.

@@ -42,7 +43,11 @@ def aro_create(cmd, # pylint: disable=too-many-locals
client_secret=None,
pod_cidr=None,
service_cidr=None,
software_defined_network=None,
disk_encryption_set=None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API Accepts separate disk encryption sets for master and workers, should we not add 2 options here too?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mjudeikis API does accept two valeus, but we decided to force worker encrpyion set id match master one for now (see code below).

if !strings.EqualFold(mp.DiskEncryptionSetID, wp.DiskEncryptionSetID) {
return api.NewCloudError(http.StatusBadRequest, api.CloudErrorCodeInvalidParameter, path+".subnetId", "The provided worker disk encryption set '%s' is invalid: must be the same as master disk encryption set '%s'.", wp.DiskEncryptionSetID, mp.DiskEncryptionSetID)
}

I don't worry much about implementation: I'm ok with aro_create accepting two separate params.

But if we are talking about exposing separate CLI params to the customers - I would be in favour of keeping 1 param for now to avoid confusion. If we decide to relax this validation - we will add a second param (--disk-encryption-set and new --master-disk-encryption-set) or rename existing and add new one (so we have, for example, --worker-disk-encryption-set and --master-disk-encryption-set).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we decide to relax I'd leave the old --disk-encryption-set, and add 2 new (one for master, one for worker). Then throw an error if the old one is specified at the same time as one of the new ones. This will keep backwards compatibility if someone uses az aro in a script.

Copy link
Contributor

@m1kola m1kola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to finish this PR as soon as possible to allow documentation work (need extension to be publisged to allow testing).

I think we need to address encryption at host params (shortened vs full name and boolean vs string balue) before we merge it.

The PR looks good overall.

python/az/aro/azext_aro/_params.py Outdated Show resolved Hide resolved
Comment on lines +75 to +80
az aro create --resource-group $RESOURCEGROUP \
--name $CLUSTER \
--vnet aro-vnet \
--master-subnet master-subnet \
--worker-subnet worker-subnet \
--disk-encryption-set $DES_ID
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we covering disk encrpytion sets (server side encryption) only in this doc or do we also want to cover encryption at host?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest I didn't add the --sdn-type documentation since the differences are described on docs.openshift.com.
I think the same applies to the encryption at host - we're just passing on a parameter to the compute RP, so the AzureDocs are the correct source here (and it's a bool flag, no setup steps or prerequisites required).

help='ResourceID of the DiskEncryptionSet to be used for master and worker VMs.',
validator=validate_disk_encryption_set)
c.argument('master_encryption_at_host', arg_type=get_enum_type(['Enabled', 'Disabled']),
options_list=['--master-enc-at-host'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on using full name.

Also I see that az vm create uses --encryption-at-host argument as a boolean flag (either present or not, no value). If I read this code correctly our command is going to be --master-enc-at-host Enabled.

Maybe we also need to use it as boolean for simplicity? If present - send Enabled to the API, if not - send Disabled.

python/az/aro/azext_aro/_validators.py Outdated Show resolved Hide resolved
python/az/aro/azext_aro/custom.py Show resolved Hide resolved
@Makdaam
Copy link
Contributor Author

Makdaam commented Oct 4, 2021

@m1kola @mjudeikis Changes applied, ready for review/more discussion.

python/az/aro/azext_aro/_params.py Outdated Show resolved Hide resolved
python/az/aro/azext_aro/_validators.py Outdated Show resolved Hide resolved
@m1kola m1kola merged commit aa13757 into Azure:master Oct 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants