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

WIP: [cinder-csi-plugin] Add basic support for an encrypted storage class parameter #2525

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

NotTheEvilOne
Copy link
Contributor

@NotTheEvilOne NotTheEvilOne commented Jan 24, 2024

What this PR does / why we need it:
This PR introduces a basic encrypted parameter to request an volume to be encrypted in OpenStack. As we currently have no approach to provide custom keys (separate request) this PR does validating if new volumes for the given volume type are encrypted if the parameter is true and cleanup (delete and error out) the volume otherwise.

Which issue this PR fixes(if applicable):
Fixes #2524

Release note:

Add support for an `encrypted` storage class parameter.

@k8s-ci-robot
Copy link
Contributor

Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot k8s-ci-robot added do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Jan 24, 2024
@k8s-ci-robot
Copy link
Contributor

Hi @NotTheEvilOne. Thanks for your PR.

I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign zetaab for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Jan 24, 2024
@jichenjc
Copy link
Contributor

/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Jan 24, 2024
encrypted := (req.GetParameters()["encrypted"] == "true")

if encrypted && volType == "" {
volType = cinderCSIDefaultEncryptedVolumeType
Copy link
Contributor

Choose a reason for hiding this comment

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

this seems assume "LUKS", at least my devstack doesn't have this volume type at all, should we expect input instead of doing Default to LUKS here?

# openstack volume type list
+--------------------------------------+-------------+-----------+
| ID                                   | Name        | Is Public |
+--------------------------------------+-------------+-----------+
| d9bb6d66-3173-4092-807d-9536c5e70f5d | lvmdriver-1 | True      |
| cad86940-33e8-4b9e-bce4-f2e9d5f63c21 | __DEFAULT__ | True      |
+--------------------------------------+-------------+-----------+

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'm not sure which is the right way here. "LUKS" is documented as the default name but you are right, it's not guaranteed that it exist at all. In that case the API will raise an error which might be fine.

I can add another call to volumetypes.List() similar to cloud.GetVolumesByName() as searching by name is not supported by the gophercloud API. This approach would be more expensive than the built in check (as OpenStack uses the database internally to look up by name). As an advantage I can check for the encryption there before creating a volume and error out without the need to cleanup.

Copy link
Contributor

Choose a reason for hiding this comment

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

There's full freedom on the name of the volume types. You shouldn't assume the encrypted one will be named "LUKS". I don't think this PR has the right approach to the problem. What's the difference in just providing the encrypted volume type as the type parameter instead?

Instead of relying on a name you could list all the volume types and their encryption information [1] (seems like gophercloud supports this [2]) and make decisions based on that. The problem is - not all clouds will support that and what to do if there are multiple encrypted volume types? Again - I don't understand why relying on setting type is not enough to satisfy this use case.

[1] https://docs.openstack.org/api-ref/block-storage/v3/#show-an-encryption-type
[2] https://github.com/gophercloud/gophercloud/blob/ea71744690516fe42b6dba075265587990fdfa09/openstack/blockstorage/v3/volumetypes/results.go#L248-L269

@jichenjc
Copy link
Contributor

openstack-cloud-controller-manager-h7qwc   0/1     ImageInspectError   0          2m21s   10.1.0.34   k3s-master   <none>           <none>

the failure is not related to the PR , not sure what's wrong here lead to OCCM report ImageInspectError
need further check (or maybe run again tomorrow and see it's env issue)

@NotTheEvilOne
Copy link
Contributor Author

/retest

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please remove unrelated changes from this commit? You can propose them in a separate PR, but adding newline removals here make reviewing harder.

encrypted := (req.GetParameters()["encrypted"] == "true")

if encrypted && volType == "" {
volType = cinderCSIDefaultEncryptedVolumeType
Copy link
Contributor

Choose a reason for hiding this comment

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

There's full freedom on the name of the volume types. You shouldn't assume the encrypted one will be named "LUKS". I don't think this PR has the right approach to the problem. What's the difference in just providing the encrypted volume type as the type parameter instead?

Instead of relying on a name you could list all the volume types and their encryption information [1] (seems like gophercloud supports this [2]) and make decisions based on that. The problem is - not all clouds will support that and what to do if there are multiple encrypted volume types? Again - I don't understand why relying on setting type is not enough to satisfy this use case.

[1] https://docs.openstack.org/api-ref/block-storage/v3/#show-an-encryption-type
[2] https://github.com/gophercloud/gophercloud/blob/ea71744690516fe42b6dba075265587990fdfa09/openstack/blockstorage/v3/volumetypes/results.go#L248-L269

@jichenjc
Copy link
Contributor

/retest

@NotTheEvilOne
Copy link
Contributor Author

NotTheEvilOne commented Jan 30, 2024

The changes of this PR are marginal @dulek, that's true. In the issue linked I have added more details why I (we) suggested this change in the first place:

Anything else we need to know?:
Another issue will be created that requests support "bring your own key" approach to both OpenStack and the CSI driver. It's part of an effort to enhance the encryption support in OpenStack and k8s as part of the Sovereign Cloud Stack. I'll reach out to OpenStack for that first and create another PR once support is implemented.

This PR is more the ground work for the other PR intended to be requested later.

I understand your objections as follow:

  • Volume Types can be of any name and names may change to which configuration it points to
  • Just checking for the encrypted status after CreateVolume() seems to have more disadvantages than advantages.
  • I'll revise the loop over all Volume Types to find a match for the given type (name). This one will be checked if encrypted is true otherwise an error will be thrown.

Does that sound more reasonable?

@dulek
Copy link
Contributor

dulek commented Jan 31, 2024

The changes of this PR are marginal @dulek, that's true. In the issue linked I have added more details why I (we) suggested this change in the first place:

Anything else we need to know?: Another issue will be created that requests support "bring your own key" approach to both OpenStack and the CSI driver. It's part of an effort to enhance the encryption support in OpenStack and k8s as part of the Sovereign Cloud Stack. I'll reach out to OpenStack for that first and create another PR once support is implemented.

This PR is more the ground work for the other PR intended to be requested later.

I understand your objections as follow:

  • Volume Types can be of any name and names may change to which configuration it points to
  • Just checking for the encrypted status after CreateVolume() seems to have more disadvantages than advantages.
  • I'll revise the loop over all Volume Types to find a match for the given type (name). This one will be checked if encrypted is true otherwise an error will be thrown.

Does that sound more reasonable?

I don't exactly buy it, the meaning of "encrypted" parameter will be non-deterministic. What if there are multiple encrypted types? For the user it will be non-deterministic which one will be used in that case.

Can you elaborate how next steps would look like with BYOK? Is there some CSI spec explaining how provider-based encryption works?

In general I think there are problems with the API proposed here. As a counterexample - a design that would work for me:

  • We leave stuff as-is today - user needs to select encrypted volume type if encryption is required.
  • Once BYOK encryption is enabled on Cinder and user provides a key - CSI validates the volume type on volume creation and if it's not providing encryption - fails. An event explaining the problem is produced.

Approach proposed in this PR would make sense if there was something like default encrypted volume type, but there's none, it's all at admin discretion.

Comment on lines 150 to 159
} else if encrypted && !vol.Encrypted {
klog.Errorf("Failed to CreateVolume with encryption enabled. Check volume type set.")

err := cloud.DeleteVolume(vol.ID)
if err != nil && !cpoerrors.IsNotFound(err) {
klog.Errorf("Failed to CreateVolume (cleanup): %v", err)
return nil, status.Errorf(codes.Internal, "CreateVolume with encryption enabled cleanup failed with error %v", err)
}

return nil, status.Errorf(codes.InvalidArgument, "Failed to CreateVolume with encryption enabled. Check volume type set.")
Copy link
Contributor

Choose a reason for hiding this comment

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

Even if we agree that this is a good idea, we should check the volume type up front, not "try" creating a volume of that volume type to check if it's encrypted.

@NotTheEvilOne
Copy link
Contributor Author

I don't exactly buy it, the meaning of "encrypted" parameter will be non-deterministic. What if there are multiple encrypted types? For the user it will be non-deterministic which one will be used in that case.

The idea behind this PR (once changed to check for the encrypted volume type before creation) is to give the user the safety that the volume type he defines in the StorageClass really produced an volume that is encrypted. Right now for a k8s end-user (e.g. in a KaaS environment) it is a black box and as you describe is up to the "mercy" of the admin to configure things right.

Can you elaborate how next steps would look like with BYOK? Is there some CSI spec explaining how provider-based encryption works?

There's no such default specification unfortunately. Idea is to if "encrypted" is "true" to check for a secret with the key based on "CSI Driver Secrets" [1]. If that key has been given it will be used, otherwise the default internally generated key.

[...]
Approach proposed in this PR would make sense if there was something like default encrypted volume type, but there's none, it's all at admin discretion.

@NotTheEvilOne NotTheEvilOne force-pushed the pr/cinder-csi-encryption-parameter branch 3 times, most recently from 86b647f to 26829f9 Compare February 7, 2024 08:35
@NotTheEvilOne NotTheEvilOne force-pushed the pr/cinder-csi-encryption-parameter branch from 26829f9 to 9606937 Compare February 7, 2024 08:45
@NotTheEvilOne NotTheEvilOne changed the title [cinder-csi-plugin] Add basic support for an encrypted storage class parameter WIP: [cinder-csi-plugin] Add basic support for an encrypted storage class parameter Feb 8, 2024
@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Feb 8, 2024
@NotTheEvilOne
Copy link
Contributor Author

After further analysis and discussion with upstream and the author(s) image-encryption proposal in OpenStack we found out that we are currently unable to determine in advance if a volume originating from a given volume type will be encrypted or not. The topic will be brought to the next Cinder 2024.1 Virtual Midcycle 2.

Only solution available at the moment would be the original implementation of validating the "encrypted" flag provided by the OpenStack API for Volumes.Create().

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 9, 2024
@k8s-ci-robot
Copy link
Contributor

PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@NotTheEvilOne
Copy link
Contributor Author

A new solution to validate if a volume type encrypts it's content will most likely be brought to 2024.2 "Dalmation". Integration in gophercloud will be needed to reuse it for this feature request.

Please let me know how you would like to continue with this PR:

  • I can either revert to the "create volume and check if it encrypted" approach for the currently supported feature set of OpenStack
  • Close this PR and reopen it after a new approach is available
  • Leave the PR as it is until then
  • Or last but not least leave the code as it is requiring manual change of the volume_extension:volume_type_encryption:get (admin_api) permission

Copy link
Contributor

@dulek dulek left a comment

Choose a reason for hiding this comment

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

A new solution to validate if a volume type encrypts it's content will most likely be brought to 2024.2 "Dalmation". Integration in gophercloud will be needed to reuse it for this feature request.

Please let me know how you would like to continue with this PR:

  • I can either revert to the "create volume and check if it encrypted" approach for the currently supported feature set of OpenStack
  • Close this PR and reopen it after a new approach is available
  • Leave the PR as it is until then
  • Or last but not least leave the code as it is requiring manual change of the volume_extension:volume_type_encryption:get (admin_api) permission

I think I'd rather not introduce an API to check for volume encryption right now. Unfortunately the OpenStack's philosophy is that you're mostly at mercy of the admin and what they configured. I don't really see a clean way to do this properly right now.

I didn't knew that volume encryption API is admin-only, sorry about suggestions to use it then, we cannot really be requiring admin permissions in CPO code.


for _, volType := range volTypes {
if n == volType.Name {
matchingVolType = &volType
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably fail if there are more than one VolumeType of a certain name, or we're non-deterministic.

@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough contributors to adequately respond to all PRs.

This bot triages PRs according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the PR is closed

You can:

  • Mark this PR as fresh with /remove-lifecycle stale
  • Close this PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[csi-cinder-plugin] Support volume basic encryption
5 participants