Skip to content

Commit e7f51b6

Browse files
authored
sync master to feature branch (#7040)
2 parents 8f846bb + 15ec9dc commit e7f51b6

146 files changed

Lines changed: 1742 additions & 1721 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

doc/content/design/external-auth-ldaps.md

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ Given `ldaps` default to `false`, this feature is **NOT** enabled until explicit
9191

9292
#### 3.1.2 Error code
9393
Following new error codes added to indicate ldaps enable related error
94-
- AUTH_NO_CERT, no certs can be used for ldaps, refer to 4.1.2 for certs finding.
95-
- AUTH_INVALID_CERT, found certs, but none of the certs can be used to connect to DC
94+
- POOL_AUTH_ENABLE_FAILED_NO_CERTS, no certs can be used for ldaps, refer to 4.1.2 for certs finding.
95+
- POOL_AUTH_ENABLE_FAILED_INVALID_CERTS, found certs, but none of the certs can be used to connect to DC
96+
**Note**: Current error code handing infrustrucure requires the error code prefix with POOL_AUTH_ENABLE_FAILED
9697

9798
### 3.2 Set/Get Pool LDAPS Status
9899

@@ -134,10 +135,10 @@ xe pool-external-auth-set-ldaps uuid=<uuid> ldaps=<true|false>
134135

135136
#### 3.2.1.2 Error code
136137
This API may raise following errors
137-
- AUTH_NO_CERT, no certs found to enable ldaps, refer to 4.1.2 for certs finding
138-
- AUTH_INVALID_CERT, found certs, but none of the certs can be used to connect to DC
138+
- AUTH_NO_CERTS, no certs found to enable ldaps, refer to 4.1.2 for certs finding
139+
- AUTH_INVALID_CERTS, found certs, but none of the certs can be used to connect to DC
139140
- AUTH_IS_DISABLED, AD is not enabled
140-
- AUTH_LDAPS_PING_FAILED, failed to do ldaps query on all DCs with valid certs
141+
- AUTH_SET_LDAPS_FAILED, Failed to set ldaps, the error message contains the details like ldap query on domain failed
141142

142143
#### 3.2.2 Get Pool LDAPS Status
143144

@@ -211,24 +212,6 @@ This design is following [trusted-certificates.md](https://github.com/xapi-proje
211212
- `pool.external_auth_set_ldaps` API
212213
- (Re)join domain
213214

214-
### 4.2 Xapi Configuration
215-
216-
#### 4.2.1 winbind-tls-verify-peer
217-
218-
For security, xapi asks winbind to verify CA certificate. `ca_and_name_if_available` is the default.
219-
220-
However, user may want to disable this verification for debug purpose.
221-
222-
`winbind-tls-verify-peer` is introduced for xapi configuration, and the possible values are `no_check`, `ca_only`, `ca_and_name_if_available`, `ca_and_name` and `as_strict_as_possible`.
223-
The configured value will override `tls verify peer` value in xapi generated samba configuration. Refer to [smb.conf](https://www.samba.org/samba/docs/current/man-html/smb.conf.5.html) for the details.
224-
225-
226-
**Note:** This item is not intended for public documentation. This is only for debug purpose, or system tuning for specific scenarios from engineering/support team.
227-
228-
#### 4.2.2 ad-warning-message-interval
229-
230-
xapi sends warning message to user with this interval on LDAP query failure. Default to 1 week. Refer to section "Session revalidate" for the details.
231-
232215
## 5. Session Revalidate
233216

234217
xapi LDAP queries domain user status (if user has been added to manage XenServer) at configurable interval, and destroys the session created by domain user if user no longer in healthy status.
@@ -238,23 +221,11 @@ However, the LDAP query may fail due to various issues as follows:
238221
- Temporary network issues
239222
- CA certificate is not properly configured, or expired, etc.
240223

241-
Instead of destroying user session for stability, a warning message will be sent to user with the details at configurable interval `ad-warning-message-interval`.
242-
243-
- If no LDAP error, do nothing
244-
- If error happens, send the warning message if:
245-
- first time see the error through xapi start up (so no need to persist last send time) or
246-
- `current_time - last_sent_time > winbind_warning_message_interval`
247-
248-
The message is defined as follows:
249-
- name: AD_DC_LDAP_CHECK
250-
- priority: Warning
251-
- cls: `Host
252-
- Body: LDAP(S) query check to `<DC>` of `<domain>` failed from `<host>` of `<pool>`
224+
Instead of destroying user session for stability, a warning will be printed in xensource.log
253225

254226
Note:
255227
- The backend session revalidate check only performs on pool coordinator, thus the backend LDAP(S) query check only on coordinator
256228
- `external_auth_set_ldaps` perform LDAP(S) query check on every host
257-
- All previous AD_DC_LDAP_CHECK warning of a host will be cleaned on a successful LDAP(s) query from that host
258229

259230
## 6. Pool Join/Leave
260231

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
title: Handling Microsoft Secure Boot Certificate Expiry
3+
layout: default
4+
design_doc: true
5+
revision: 1
6+
status: draft
7+
---
8+
9+
## 1. Background
10+
11+
Microsoft Secure Boot certificates from 2011 are reaching end-of-life, and legacy VMs may still contain only the old certificate set. XenServer needs an out-of-band mechanism to update per-VM UEFI Secure Boot variables safely and at scale.
12+
13+
Scope of this design:
14+
15+
- Update certificate state tracking and update flow for VMs, snapshots, and templates
16+
- Provide API support for scheduling certificate updates on VM boot
17+
- Integrate xapi and varstored behavior for consistent state handling
18+
19+
## 2. System Overview
20+
21+
### 2.1 Out-of-band Update Mechanism
22+
23+
Certificate update is implemented as a dedicated API-driven workflow (not a plugin), so that:
24+
25+
- The interface is documented and SDK-generated
26+
- RBAC can be assigned precisely
27+
- xapi can route requests and coordinate host-side behavior consistently
28+
29+
### 2.2 Certificate State Tracking
30+
31+
A new VM field is introduced:
32+
33+
- `VM.secureboot_certificates_state` (enum, readonly)
34+
35+
States:
36+
37+
- `ok`: No update required (including non-applicable VM types)
38+
- `update_available`: Update required
39+
- `update_on_boot`: Update scheduled for next boot
40+
41+
~~~mermaid
42+
43+
stateDiagram
44+
update_available --> update_on_boot : Admin marks VM for update
45+
update_on_boot --> ok : VM boots, update succeeds
46+
update_on_boot --> update_on_boot : VM boots, update fails(retain state)
47+
ok --> update_available : recompute state(e.g. legacy VM import)
48+
49+
~~~
50+
51+
### 2.3 RBAC
52+
53+
The new update API follows VM-admin-level access, aligned with existing NVRAM-related VM operations.
54+
55+
## 3. Design for Components
56+
57+
### 3.1 VM Certificate State Model
58+
59+
`VM.secureboot_certificates_state` applies to these VM-class objects,
60+
61+
- VMs
62+
- Snapshots
63+
- Templates
64+
65+
Transition intent:
66+
67+
- Admin marks a VM for update: `update_available -> update_on_boot`
68+
- VM boots and update succeeds: `update_on_boot -> ok`
69+
- VM boots and update fails: remains `update_on_boot` or is reset to `update_available` based on update result handling
70+
71+
### 3.2 API: Mark/Unmark Update-on-Boot
72+
73+
New API:
74+
75+
- `VM.update_secureboot_certificates_on_boot(session, vm, mark)`
76+
77+
Behavior:
78+
79+
- `mark=true`: require current state `update_available`, then set `update_on_boot`
80+
- `mark=false`: require current state `update_on_boot`, then set `update_available`
81+
82+
Validation:
83+
84+
- Reject invalid transitions with `OPERATION_NOT_ALLOWED`
85+
86+
### 3.3 DB Upgrade and Import Handling
87+
88+
On toolstack restart after upgrade:
89+
90+
- Initialize `secureboot_certificates_state` for all VM records to `ok`
91+
- Re-evaluate NVRAM and set `update_available` where needed
92+
93+
Applied to:
94+
95+
- VMs
96+
- Snapshots
97+
- Non-default templates
98+
99+
Default templates remain `ok`.
100+
101+
For VM import and cross-pool migration:
102+
103+
- If imported metadata lacks `secureboot_certificates_state`, determine state from NVRAM and set it during import
104+
- If imported metadata contains `secureboot_certificates_state`, reserve the state during import
105+
106+
### 3.4 NVRAM and State Consistency
107+
108+
The certificate state must stay consistent with actual NVRAM content.
109+
110+
Key interface change:
111+
112+
- Extend `VM.set_NVRAM_EFI_variables` with optional parameter `update`, we call it `VM.set_NVRAM_EFI_variables_V2`
113+
114+
Rules:
115+
116+
- `update=yes` -> set state `ok`
117+
- `update=no` -> do not update state
118+
- omitted -> xapi runs certificate check helper and derives state
119+
120+
This ensures compatibility when old varstored instances are still running during rolling update windows.
121+
122+
### 3.5 Certificate Check Helper
123+
124+
A standalone program will be introduced, which xapi calls to determine the SecureBoot cert state
125+
126+
Inputs:
127+
128+
- `temp file path` which contains NVRAM EFI-variables data
129+
130+
Behavior:
131+
132+
- This program comes to use some common functions shared with varstored.
133+
- This program is launched by xapi, it is executed in a sandboxed and reduced privileges environment.
134+
- Xapi retrieves VM's NVRAM content from database and passes it to this program via command-line arguments.
135+
- If this program outputs `update_required`, xapi sets `VM.secureboot_certificates_state` to be `update_available`.
136+
- If this program outputs `update_ok`, xapi sets `VM.secureboot_certificates_state` to be `ok`.
137+
- On toolstack restart, during DB upgrade, this program is invoked to compute `VM.secureboot_certificates_state`. Since xapi process has not completed initialization at that point, this program cannot call any services of xapi.
138+
139+
### 3.6 Boot-time Automatic Update Path
140+
141+
When varstored initializes a VM and sees `secureboot_certificates_state=update_on_boot`, varstored does,
142+
143+
- Perform certificate update flow during boot-time initialization
144+
- Write updated NVRAM and synchronize state via `VM.set_NVRAM_EFI_variables_V2`
145+
146+
The `VM.set_NVRAM_EFI_variables_V2` interface performs same as `VM.set_NVRAM_EFI_variables`, uses the existing varstored-guard process to make calls to xapi.
147+
148+
If `VM.set_NVRAM_EFI_variables_V2` runs into error (e.g. there is something wrong with the communication with xapi),
149+
150+
- xapi does not update VM NVRAM and `VM.secureboot_certificates_state`
151+
- VM boot gets stuck at the firmware initialization stage, if the issue is not fixed, rebooting the VM will still encounter the same problem
152+
- Once the issue is fixed, admin can continue the secureboot certificate upgrade by VM reboot
153+
154+
### 3.7 End-to-end Workflow
155+
156+
1. Upgrade packages (`xapi-core`, `varstored`, related components)
157+
2. Restart toolstack
158+
3. xapi DB upgrade initializes and recalculates `secureboot_certificates_state`
159+
4. Admin marks selected VMs via `VM.update_secureboot_certificates_on_boot`
160+
5. VM reboot triggers varstored certificate update
161+
6. xapi updates state to reflect post-update NVRAM content
162+
163+
## 4. Out of Scope
164+
165+
- User-notification mechanism for certificate expiry
166+
- Custom certificate workflow
167+
- Template/snapshot feature expansion beyond state tracking and conversion behavior
168+
- OS-specific test-process guidance
169+
- VM with Secure Boot PCR7 binding (e.g. Windows bitlocker), provide customer documentation to guide how to resolve such issues

doc/content/xapi/cli/_index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ So each function receives a printer for sending text output to the xe client, an
156156
let mac = List.assoc_default "mac" params "" in
157157
let network = Client.Network.get_by_uuid rpc session_id network in
158158
let pifs = List.assoc "pif-uuids" params in
159-
let uuids = String.split ',' pifs in
159+
let uuids = String.split_on_char ',' pifs in
160160
let pifs = List.map (fun uuid -> Client.PIF.get_by_uuid rpc session_id uuid) uuids in
161161
let mode = Record_util.bond_mode_of_string (List.assoc_default "mode" params "") in
162162
let properties = read_map_params "properties" params in

dune-project

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@
179179
(xapi-types
180180
(= :version))
181181
(xapi-stdext-zerocheck
182+
(= :version))
183+
(xapi-work-queues
182184
(= :version)))
183185
(synopsis "A CLI for xapi storage services")
184186
(description
@@ -191,7 +193,8 @@
191193
(name xapi-schema))
192194

193195
(package
194-
(name xapi-work-queues))
196+
(name xapi-work-queues)
197+
(depends ppx_deriving_rpc xapi-stdext-threads))
195198

196199
(package
197200
(name rrdd-plugin)
@@ -327,6 +330,7 @@
327330
xapi-stdext-pervasives
328331
xapi-stdext-unix
329332
xapi-stdext-zerocheck
333+
xapi-work-queues
330334
xen-api-client
331335
xen-api-client-lwt
332336
xenctrl
@@ -365,6 +369,7 @@
365369
rrdd-plugin
366370
xapi-stdext-std
367371
xapi-tracing-export
372+
xapi-work-queues
368373
xen-api-client
369374
(alcotest :with-test)
370375
(ppx_deriving_rpc :with-test)
@@ -483,6 +488,8 @@
483488
(= :version))
484489
(xapi-types
485490
(= :version))
491+
(xapi-work-queues
492+
(= :version))
486493
(xen-api-client-lwt
487494
(= :version))
488495
xenctrl ; for quicktest

ocaml/database/parse_db_conf.ml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
*)
1414
(* !!! This needs to be moved out of xapi and into the database directory; probably being merged with db_connections !!! *)
1515

16-
open Xapi_stdext_std.Xstringext
1716
open Xapi_stdext_unix
1817

1918
module D = Debug.Make (struct let name = "parse_db_conf" end)
@@ -110,7 +109,7 @@ let parse_db_conf s =
110109
let conf = Unixext.string_of_file s in
111110
let lines : string list ref = ref [] in
112111
let consume_line () = lines := List.tl !lines in
113-
lines := String.split '\n' conf ;
112+
lines := String.split_on_char '\n' conf ;
114113
List.iter (fun line -> debug "%s" line) !lines ;
115114
let read_block () =
116115
let path_line = List.hd !lines in
@@ -120,7 +119,7 @@ let parse_db_conf s =
120119
while !lines <> [] && List.hd !lines <> "" do
121120
let line = List.hd !lines in
122121
key_values :=
123-
( match String.split ':' line with
122+
( match String.split_on_char ':' line with
124123
| k :: vs ->
125124
( String.lowercase_ascii k
126125
, String.lowercase_ascii (String.concat ":" vs)

ocaml/database/redo_log.ml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
* GNU Lesser General Public License for more details.
1313
*)
1414
open Xapi_stdext_pervasives.Pervasiveext
15-
open Xapi_stdext_std.Xstringext
1615
open Xapi_stdext_unix
1716

1817
let with_lock = Xapi_stdext_threads.Threadext.Mutex.execute

ocaml/doc/dune

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(executable
22
(modes exe)
33
(name jsapi)
4-
(libraries
4+
(libraries
55
mustache
66
rpclib.core
77
rpclib.json
@@ -10,7 +10,6 @@
1010
xapi-consts
1111
xapi-datamodel
1212
xapi-stdext-pervasives
13-
xapi-stdext-std
1413
xapi-stdext-unix
1514
)
1615
(preprocess (pps ppx_deriving_rpc))

ocaml/doc/jsapi.ml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
* GNU Lesser General Public License for more details.
1313
*)
1414

15-
open Xapi_stdext_std.Xstringext
1615
open Xapi_stdext_pervasives.Pervasiveext
1716
module Unixext = Xapi_stdext_unix.Unixext
1817
open Datamodel_types

0 commit comments

Comments
 (0)