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

rego and hardening: add enforcement and hardening for encrypted scratch #1538

Merged
merged 10 commits into from
Nov 6, 2022

Conversation

anmaxvl
Copy link
Contributor

@anmaxvl anmaxvl commented Oct 7, 2022

rego and hardening: add enforcement and hardening for encrypted scratch

The request to encrypt scratch comes from the host, but in confidential
scenario, the host cannot be trusted and it may attempt to mount the
read-write overlay of a container under an unencrypted path or omit the
encryption request altogether.

To address the issue, add scratch_mount, scratch_unmount enforcement
points and allow_unencrypted_scratch policy config, which can be used
to (you guessed it) allow containers to run with unencrypted scratch.

Since the request to add encrypted read-write scratch disk and mounting
container overlayfs come at different times, we also introduced minimal
(for now) hardening around adding read-write devices to the UVM. We
record the mounted read-write devices when they arrive and at the time
of adding overlayfs we check if the scratch path encrypted or not and
validate against the policy before enforcing overlay policy.

The policy config can be set at the top level, e.g.:

allow_unencrypted_scratch := true

containers := [...]

The scratch_mount enforcement point takes an input with the following
members:

{
    "target": "<mount target>",
    "encrypted": [true|false],
}

Add /internal/guest/runtime/hcsv2/uvm_state.go, which adds a new
hostMounts struct which keeps track of mounted RW devices. This can
be extended in the future for more GCS hardening purposes, e.g. overlay,
RO layer mounts and other container lifecycle management.

Signed-off-by: Maksim An maksiman@microsoft.com

@anmaxvl
Copy link
Contributor Author

anmaxvl commented Oct 7, 2022

@SeanTAllen @matajoh @helsaawy putting as draft to get early feedback. The code hasn't been tested yet, working on the unit tests.

@anmaxvl anmaxvl force-pushed the encrypted-scratch-policy branch 2 times, most recently from 149326b to ec141d0 Compare October 7, 2022 07:01
if err != nil {
return errors.Wrapf(err, "unmounting scsi device at %s denied by policy", mvd.MountPath)
}
if mvd.ReadOnly {
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this logic change behavior? If ReadOnly and Encrypted is false, there is no policy enforcement.

Copy link
Contributor Author

@anmaxvl anmaxvl Oct 7, 2022

Choose a reason for hiding this comment

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

I think we just missed this during review, but currently we don't have any enforcement for non-readonly devices: https://github.com/microsoft/hcsshim/blob/main/internal/guest/runtime/hcsv2/uvm.go#L657-L668.

pkg/securitypolicy/framework.rego Outdated Show resolved Hide resolved
pkg/securitypolicy/framework.rego Outdated Show resolved Hide resolved
pkg/securitypolicy/framework.rego Outdated Show resolved Hide resolved
pkg/securitypolicy/regopolicy_test.go Outdated Show resolved Hide resolved
pkg/securitypolicy/securitypolicyenforcer.go Outdated Show resolved Hide resolved
@SeanTAllen
Copy link
Contributor

This doesnt match my understanding of what we were going to be doing. Im going to set up a meeting.

@anmaxvl
Copy link
Contributor Author

anmaxvl commented Oct 7, 2022

This doesnt match my understanding of what we were going to be doing. Im going to set up a meeting.

After discussing more, we came to a conclusion that in the current implementation we're doing more of a hardening inside the policy, instead we should do the hardening in GCS. The plan is to have a policy config that'll tell us whether running with unencrypted scratch is allowed or not and GCS will make sure that the overlays are mounted under encrypted mount points.

@anmaxvl anmaxvl changed the title policy enforcement: add encrypted scratch enforcement rego and hardening: add enforcement and hardening for encrypted scratch Oct 10, 2022
@anmaxvl anmaxvl marked this pull request as ready for review October 10, 2022 09:15
@anmaxvl anmaxvl requested a review from a team as a code owner October 10, 2022 09:15
internal/guest/runtime/hcsv2/uvm.go Show resolved Hide resolved
internal/guest/runtime/hcsv2/uvm_state.go Outdated Show resolved Hide resolved
pkg/securitypolicy/regopolicy_scratch_test.go Outdated Show resolved Hide resolved
@anmaxvl anmaxvl force-pushed the encrypted-scratch-policy branch 2 times, most recently from 586492b to 776fe7a Compare October 10, 2022 20:24
@anmaxvl anmaxvl force-pushed the encrypted-scratch-policy branch 3 times, most recently from f557838 to 23cad7b Compare October 13, 2022 21:41
Copy link
Contributor

@helsaawy helsaawy left a comment

Choose a reason for hiding this comment

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

Aside from merge conflicts and comments bellow, LGTM

internal/guest/runtime/hcsv2/uvm_state.go Outdated Show resolved Hide resolved
internal/guest/runtime/hcsv2/uvm.go Outdated Show resolved Hide resolved
"testing"
)

func Test_Add_Remove_RWDevice(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

probably should add functional or gcs tests for this as well in a future pr

@anmaxvl anmaxvl force-pushed the encrypted-scratch-policy branch 2 times, most recently from dede668 to 6b8a53f Compare October 19, 2022 16:24
AllowPropertiesAccess bool
AllowDumpStacks bool
AllowRuntimeLogging bool
Containers []*securityPolicyContainer
Copy link
Contributor

Choose a reason for hiding this comment

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

Hi Maksim, the continued addition of bools to this function signature makes a good case for refactoring. I recommend a type or similar construct to avoid unreadable code at the function invocation:

code, err = marshalRego(
securityPolicy.AllowAll,
containers,
[]ExternalProcessConfig{},
true,
true,
true,
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.

yeah, we have "post feature complete" list of improvements and this one is on it 😄

@@ -1968,6 +1968,55 @@ func Test_EnforceRuntimeLogging_Not_Allowed(t *testing.T) {
}
}

func Test_Rego_Scratch_Mount_Policy(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Kudos for your continued inclusion of test modules. Unit tests should be considered a requirement for all new code, and you consistently are a role model for this habit.

internal/guest/storage/scsi/scsi.go Outdated Show resolved Hide resolved
pkg/securitypolicy/policy.rego Outdated Show resolved Hide resolved
@anmaxvl anmaxvl force-pushed the encrypted-scratch-policy branch 3 times, most recently from 596f978 to 3407acb Compare October 26, 2022 07:25
The request to encrypt scratch comes from the host, but in confidential
scenario, the host cannot be trusted and it may attempt to mount the
read-write overlay of a container under an unencrypted path or omit the
encryption request altogether.

To address the issue, add `scratch_mount`, `scratch_unmount` enforcement
points and `allow_unencrypted_scratch` policy config, which can be used
to (you guessed it) allow containers to run with unencrypted scratch.

Since the request to add encrypted read-write scratch disk and mounting
container overlayfs come at different times, we also introduced minimal
(for now) hardening around adding read-write devices to the UVM. We
record the mounted read-write devices when they arrive and at the time
of adding overlayfs we check if the scratch path encrypted or not and
validate against the policy before enforcing overlay policy.

The policy config can be set at the top level, e.g.:
```
allow_unencrypted_scratch := true

containers := [...]
```

The `scratch_mount` enforcement point takes an input with the following
members:
```
{
    "target": "<mount target>",
    "encrypted": [true|false],
}
```

Add `/internal/guest/runtime/hcsv2/uvm_state.go`, which adds a new
`hostMounts` struct which keeps track of mounted RW devices. This can
be extended in the future for more GCS hardening purposes, e.g. overlay,
RO layer mounts and other container lifecycle management.

Signed-off-by: Maksim An <maksiman@microsoft.com>
Signed-off-by: Maksim An <maksiman@microsoft.com>
Signed-off-by: Maksim An <maksiman@microsoft.com>
Signed-off-by: Maksim An <maksiman@microsoft.com>
Signed-off-by: Maksim An <maksiman@microsoft.com>
Signed-off-by: Maksim An <maksiman@microsoft.com>
Signed-off-by: Maksim An <maksiman@microsoft.com>
Signed-off-by: Maksim An <maksiman@microsoft.com>
As part of enforcing encrypted scratch policy, we need to make
sure that the source matches. To figure out the source for a
SCSI attachment we need to first find the actual controller number
where the SCSI is presented, which can be different from what hcsshim
has requested originally.
Rename and export `fetchActualControllerNumber` as `ActualControllerNumber`
and figure out the correct controller before calling to scsi Mount/Unmount.
Remove wrappers and update unit tests.

Signed-off-by: Maksim An <maksiman@microsoft.com>
Signed-off-by: Maksim An <maksiman@microsoft.com>
Copy link
Contributor

@msscotb msscotb left a comment

Choose a reason for hiding this comment

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

lgtm

@anmaxvl anmaxvl merged commit 0a55db7 into microsoft:main Nov 6, 2022
@anmaxvl anmaxvl deleted the encrypted-scratch-policy branch November 6, 2022 22:18
anmaxvl pushed a commit that referenced this pull request Feb 7, 2023
PR is for updating hcsshim ADO branch from github equivalent.

Related work items: #1538, #1539, #1544, #1545, #1550, #1551, #1552, #1553, #1559, #1561
princepereira pushed a commit to princepereira/hcsshim that referenced this pull request Aug 29, 2024
…ch (microsoft#1538)

* rego and hardening: add enforcement and hardening for encrypted scratch

The request to encrypt scratch comes from the host, but in confidential
scenario, the host cannot be trusted and it may attempt to mount the
read-write overlay of a container under an unencrypted path or omit the
encryption request altogether.

To address the issue, add `scratch_mount`, `scratch_unmount` enforcement
points and `allow_unencrypted_scratch` policy config, which can be used
to (you guessed it) allow containers to run with unencrypted scratch.

Since the request to add encrypted read-write scratch disk and mounting
container overlayfs come at different times, we also introduced minimal
(for now) hardening around adding read-write devices to the UVM. We
record the mounted read-write devices when they arrive and at the time
of adding overlayfs we check if the scratch path encrypted or not and
validate against the policy before enforcing overlay policy.

The policy config can be set at the top level, e.g.:
```
allow_unencrypted_scratch := true

containers := [...]
```

The `scratch_mount` enforcement point takes an input with the following
members:
```
{
    "target": "<mount target>",
    "encrypted": [true|false],
}
```

Add `/internal/guest/runtime/hcsv2/uvm_state.go`, which adds a new
`hostMounts` struct which keeps track of mounted RW devices. This can
be extended in the future for more GCS hardening purposes, e.g. overlay,
RO layer mounts and other container lifecycle management.

* crypt package refactor and adding more unit tests

* tests: add e2e tests for scratch encryption policy

* export and rename fetchActualControllerNumber

As part of enforcing encrypted scratch policy, we need to make
sure that the source matches. To figure out the source for a
SCSI attachment we need to first find the actual controller number
where the SCSI is presented, which can be different from what hcsshim
has requested originally.
Rename and export `fetchActualControllerNumber` as `ActualControllerNumber`
and figure out the correct controller before calling to scsi Mount/Unmount.
Remove wrappers and update unit tests.

Signed-off-by: Maksim An <maksiman@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants