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

New API methods for status about SecureBoot and UEFI certs #5566

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

benjamreis
Copy link
Contributor

@benjamreis benjamreis commented Apr 17, 2024

Implement what's discussed here: #5548

New API calls:

  • VM.set_uefi_mode: calls varstore-sb-state to edit the uefi mode of a VM
    Takes in input the uuid of a VM and a mode (setup or user)
    Returns the output of the script calls

  • VM.get_secureboot_readiness API call

    Returns the SecureBoot status of a VM:

    • not_supported: VM's firmware is not UEFI
    • disabled: Secureboot is disabled on this VM
    • first_boot: Secured boot is enabled on this VM and its NVRAM.EFI-variables is empty
    • ready: Secured boot is enabled on this VM and PK, KEK, db and dbx are defined in its EFI variables
    • ready_no_dbx: Secured boot is enabled on this VM and PK, KEK, db but not dbx are defined in its EFI variables
    • setup_mode: Secured boot is enabled on this VM and PK is not defined in its EFI variables
    • certs_incomplete: Secured boot is enabled on this VM and the certificates defines in its EFI variables are incomplete
  • Pool.get_guest_secureboot_readiness API call

    Returns a pool's state for guest SecureBoot:

    • ready: the active pool UEFI certificates (custom ones first, default ones if no custom ones) contain PK, KEK, db and dbx
    • ready_no_dbx: the active pool UEFI certificates contain PK, KEK and db but not dbx
    • not_ready: otherwise

@benjamreis benjamreis force-pushed the sb-state-api branch 2 times, most recently from a0e8fa2 to 2efb70f Compare April 17, 2024 11:28
Copy link
Contributor

@lindig lindig left a comment

Choose a reason for hiding this comment

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

Looks ok otherwise.

ocaml/idl/datamodel_vm.ml Show resolved Hide resolved
@lindig
Copy link
Contributor

lindig commented Apr 18, 2024

Can this be changed from the CLI? It looks like it can't but I think it should be observable and update-able from the CLI.

@benjamreis
Copy link
Contributor Author

benjamreis commented Apr 18, 2024

Can this be changed from the CLI? It looks like it can't but I think it should be observable and update-able from the CLI.

Working on it as we speak. We will need the CLI implem for our tests. :)

Edit: Done 👍

@benjamreis benjamreis force-pushed the sb-state-api branch 6 times, most recently from afc5343 to 41cd758 Compare April 19, 2024 09:11
let tmp_auth_file = Filename.concat tmp_dir filename in
Helpers.touch_file tmp_auth_file ; tmp_auth_file

let get_guest_secureboot_readiness ~__context ~self =
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This method is a bit complex as it needs to extract the tarball in a pool (custom)_uefi_certificates db field in a temp directory and then list them before removing the extracted files...

Another (simpler) solution would be to list auth files in varstore_dir as it's supposed to always be in sync with the XAPI DB field unless a user would have manually modified it which wouldn't be supported.
What do you guys think?

Copy link
Member

Choose a reason for hiding this comment

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

As long as its limitations are documented, I don't mind using the method that doesn't rely on creating files

@benjamreis benjamreis force-pushed the sb-state-api branch 3 times, most recently from f9180a8 to 1f84bd0 Compare April 22, 2024 08:46
@benjamreis benjamreis marked this pull request as ready for review April 22, 2024 09:13
@benjamreis benjamreis requested a review from lindig April 22, 2024 13:24
@benjamreis
Copy link
Contributor Author

Hi!

Any update on this? It's really important for us to have in our next XCP-ng release and we'd like to start implementing the tests and clients side once we're assured the API won't move too much.

Thx

variables"
)
; ( "certs_incomplete"
, "Secured boot is enabled on this VM and the certificates defines in \
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: defined.

("not_supported", "VM's firmware is not UEFI")
; ("disabled", "Secureboot is disabled on this VM")
; ( "first_boot"
, "Secured boot is enabled on this VM and its NVRAM.EFI-variables is \
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: are

, {
reqd= ["uuid"; "mode"]
; optn= []
; help= "Set a VM in UEFI setup or user mode."
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe indicate that either "setup" or "user" is expected by putting them in (single) quotes.

| "user" ->
`user
| s ->
raise (Record_failure ("Expected 'user','setup', got " ^ s))
Copy link
Contributor

Choose a reason for hiding this comment

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

"Expected one of 'user', 'record' but got '%s'"

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 replicating how other Record_failure are written, I think it's better to keep the message standarize.


let get_auth_filename tmp_dir tarpath =
let filename =
if String.contains tarpath '/' then
Copy link
Contributor

Choose a reason for hiding this comment

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

Filename.basename can be called unconditionally.

else
tarpath
in
let tmp_auth_file = Filename.concat tmp_dir filename in
Copy link
Contributor

Choose a reason for hiding this comment

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

This is risky because there could be clashes over this path if tmp_dir is some public temp dir.

Copy link
Member

Choose a reason for hiding this comment

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

(fun () -> Sys.remove filename) ;
let tmp_auth_files = Sys.readdir tmp_dir in
Array.iter (fun file -> debug "*** BRS: auth file %s" file) tmp_auth_files ;
let pk_present = Array.mem "PK.auth" tmp_auth_files in
Copy link
Contributor

Choose a reason for hiding this comment

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

what happens when Array.mem fails?

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 don't see how it can fail in the doc.

@@ -3037,6 +3037,12 @@ functor
let restart_device_models ~__context ~self =
info "VM.restart_device_models: self = '%s'" (vm_uuid ~__context self) ;
Local.VM.restart_device_models ~__context ~self

let set_uefi_mode ~__context ~self ~mode =
Copy link
Member

Choose a reason for hiding this comment

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

The call is not being forwarded to the host that hosts the vm, Is the command meant to be run on the coordinator ever time?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This method eventually calls varstore-sb-state which can be called on any host of the pool as the call will be redirected where the VM is located. I did not want to add another redirection before that.

Copy link
Member

Choose a reason for hiding this comment

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

the call will be redirected where the VM is located

Which layer is doing this redirection? In xapi this is exactly the place that must do the redirection, if at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IIUC varstored-tools call XAPI from within the scripts when running to dispatch to the relevent.

defined in its EFI variables"
)
; ( "setup_mode"
, "Secured boot is enabled on this VM and PK is not defined in its EFI \
Copy link
Member

Choose a reason for hiding this comment

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

In which use cases does this state interact with set_uefi_mode call? And how? The latter doesn't affect the database value directly, while this is db-only

Copy link
Contributor Author

Choose a reason for hiding this comment

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

set_uefi_mode calls varstore-sb-state which will affect the VM's NVRAM's EFI-variables.
This method only deduct the state of the VM EFI variables.

`first_boot (* TO BE VERIFIED *)
| Some _ -> (
let varstore_ls =
Helpers.call_script !Xapi_globs.varstore_ls
Copy link
Member

Choose a reason for hiding this comment

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

What host does this need to be run on? Always on the coordinator?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as above, varstore-ls will redirect the call when relevant.

List.assoc_opt "EFI-variables" (Db.VM.get_NVRAM ~__context ~self)
with
| None ->
`first_boot (* TO BE VERIFIED *)
Copy link
Member

Choose a reason for hiding this comment

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

Is there a plan to verify this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's been tested and verified, I'll retest it after the latest changes and remove the comment after revalidation.

ocaml/xapi/xapi_vm.ml Outdated Show resolved Hide resolved
else
tarpath
in
let tmp_auth_file = Filename.concat tmp_dir filename in
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

@psafont psafont 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 the comments that need to be addressed, you should rebase the PR on top of the latest master, it will make the strange python errors go away

Calls `varstore-sb-state` to edit the uefi mode of a VM
Takes in input the uuid of a VM and a mode (`setup` or `user`)

Returns the output of the script calls

Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
Returns the SecureBoot status of a VM:
- `not_supported`: VM's firmware is not UEFI
- `disabled`: Secureboot is disabled on this VM
- `first_boot`: Secured boot is enabled on this VM and its NVRAM.EFI-variables is empty
- `ready`: Secured boot is enabled on this VM and PK, KEK, db and dbx are defined in its EFI variables
- `ready_no_dbx`: Secured boot is enabled on this VM and PK, KEK, db but not dbx are defined in its EFI variables
- `setup_mode`: Secured boot is enabled on this VM and PK is not defined in its EFI variables
- `certs_incomplete`: Secured boot is enabled on this VM and the certificates defines in its EFI variables are incomplete

Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
Returns a pool's state for guest SecureBoot:
- `ready`: the active pool UEFI certificates (custom ones first, default ones if no custom ones) contain PK, KEK, db and dbx
- `ready_no_dbx`: the active pool UEFI certificates contain PK, KEK and db but not dbx
- `not_ready`: otherwise

Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
@benjamreis benjamreis force-pushed the sb-state-api branch 2 times, most recently from 5a0e802 to 9746d6d Compare May 14, 2024 07:11
Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
benjamreis added a commit to xcp-ng/xcp-ng-tests that referenced this pull request May 15, 2024
See: xapi-project/xen-api#5566

Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
benjamreis added a commit to xcp-ng-rpms/xapi that referenced this pull request May 15, 2024
See: xapi-project/xen-api#5566

Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
benjamreis added a commit to xcp-ng-rpms/xapi that referenced this pull request May 15, 2024
See: xapi-project/xen-api#5566

Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
benjamreis added a commit to xcp-ng-rpms/xapi that referenced this pull request May 15, 2024
See: xapi-project/xen-api#5566

Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
benjamreis added a commit to xcp-ng/xcp-ng-tests that referenced this pull request May 15, 2024
See: xapi-project/xen-api#5566

Signed-off-by: Benjamin Reis <benjamin.reis@vates.tech>
@benjamreis benjamreis requested a review from psafont May 16, 2024 07:02
(fun elem ->
(* Lines follow this pattern: <GUID> <KEY>*)
let splitted = String.split_on_char ' ' elem in
List.nth splitted 1
Copy link
Member

Choose a reason for hiding this comment

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

Nth can raise with a pretty nasty error that's difficult to find where it originated. Please use nth_opt and deal with the option by replacing List.map with List.filter_map

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.

None yet

3 participants