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

EFI & Secure Boot #155

Merged
merged 2 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ Style/SignalException:

Metrics/ClassLength:
Enabled: false

Metrics/BlockLength:
Exclude:
- tests/**/*.rb
24 changes: 23 additions & 1 deletion lib/fog/libvirt/models/compute/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ class Server < Fog::Compute::Server

attribute :cpus
attribute :cputime
attribute :firmware
attribute :firmware_features
attribute :secure_boot
attribute :loader_attributes
attribute :os_type
attribute :memory_size
attribute :max_memory_size
Expand Down Expand Up @@ -287,14 +291,31 @@ def to_xml
end

xml.vcpu(cpus)
xml.os do
os_tags = {}

os_tags[:firmware] = firmware if firmware == 'efi'

xml.os(**os_tags) do
type = xml.type(os_type, :arch => arch)
type[:machine] = "q35" if ["i686", "x86_64"].include?(arch)

boot_order.each do |dev|
xml.boot(:dev => dev)
end

loader_attributes&.each do |key, value|
xml.loader(key => value)
end

if firmware == "efi" && firmware_features&.any?
xml.firmware do
firmware_features.each_pair do |key, value|
xml.feature(:name => key, :enabled => value)
end
end
end
end

xml.features do
xml.acpi
xml.apic
Expand Down Expand Up @@ -539,6 +560,7 @@ def defaults
:guest_agent => true,
:video => {:type => "cirrus", :vram => 9216, :heads => 1},
:virtio_rng => {},
:firmware_features => { "secure-boot" => "no" },
}
end

Expand Down
22 changes: 21 additions & 1 deletion lib/fog/libvirt/requests/compute/list_domains.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,24 @@ def boot_order xml
xml_elements(xml, "domain/os/boot", "dev")
end

def firmware(xml)
firmware_from_loader = xml_elements(xml, "domain/os/loader", "type").first
ekohl marked this conversation as resolved.
Show resolved Hide resolved

case firmware_from_loader
when 'pflash'
'efi'
when 'rom'
'bios'
else
xml_elements(xml, "domain/os", "firmware").first || 'bios'
ekohl marked this conversation as resolved.
Show resolved Hide resolved
end
end

# we rely on the fact that the secure attribute is only present when secure boot is enabled
def secure_boot_enabled?(xml)
ekohl marked this conversation as resolved.
Show resolved Hide resolved
xml_elements(xml, "domain/os/loader", "secure").first == 'yes'
ekohl marked this conversation as resolved.
Show resolved Hide resolved
end

def domain_interfaces xml
ifs = xml_elements(xml, "domain/devices/interface")
ifs.map { |i|
Expand Down Expand Up @@ -78,7 +96,9 @@ def domain_to_attributes(dom)
:boot_order => boot_order(dom.xml_desc),
:nics => domain_interfaces(dom.xml_desc),
:volumes_path => domain_volumes(dom.xml_desc),
:state => states[dom.info.state]
:state => states[dom.info.state],
:firmware => firmware(dom.xml_desc),
:secure_boot => secure_boot_enabled?(dom.xml_desc),
}
rescue ::Libvirt::RetrieveError, ::Libvirt::Error
# Catch libvirt exceptions to avoid race conditions involving
Expand Down
43 changes: 43 additions & 0 deletions tests/libvirt/models/compute/server_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
attributes = [ :id,
:cpus,
:cputime,
:firmware,
:firmware_features,
:secure_boot,
:loader_attributes,
:os_type,
:memory_size,
:max_memory_size,
Expand Down Expand Up @@ -67,6 +71,7 @@

test('be a kind of Fog::Libvirt::Compute::Server') { server.kind_of? Fog::Libvirt::Compute::Server }
tests("serializes to xml") do
test("without firmware") { server.to_xml.include?("<os>") }
test("with memory") { server.to_xml.match?(%r{<memory>\d+</memory>}) }
test("with disk of type file") do
xml = server.to_xml
Expand All @@ -86,5 +91,43 @@
end
test("with q35 machine type on x86_64") { server.to_xml.match?(%r{<type arch="x86_64" machine="q35">hvm</type>}) }
end
test("with efi firmware") do
server = Fog::Libvirt::Compute::Server.new(
{
:firmware => "efi",
:nics => [],
:volumes => []
}
)
xml = server.to_xml

os_firmware = xml.include?('<os firmware="efi">')
secure_boot = xml.include?('<feature name="secure-boot" enabled="no"/>')
loader_attributes = !xml.include?('<loader secure="yes"/>')

os_firmware && secure_boot && loader_attributes
end
test("with secure boot enabled") do
server = Fog::Libvirt::Compute::Server.new(
{
:firmware => "efi",
:firmware_features => {
"secure-boot" => "yes",
"enrolled-keys" => "yes"
},
:loader_attributes => { "secure" => "yes" },
:nics => [],
:volumes => []
}
)
xml = server.to_xml

os_firmware = xml.include?('<os firmware="efi">')
secure_boot = xml.include?('<feature name="secure-boot" enabled="yes"/>')
enrolled_keys = xml.include?('<feature name="enrolled-keys" enabled="yes"/>')
loader_attributes = xml.include?('<loader secure="yes"/>')

os_firmware && secure_boot && enrolled_keys && loader_attributes
end
end
end