-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
596 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
# encoding: utf-8 | ||
|
||
# Copyright (c) [2018] SUSE LLC | ||
# | ||
# All Rights Reserved. | ||
# | ||
# This program is free software; you can redistribute it and/or modify it | ||
# under the terms of version 2 of the GNU General Public License as published | ||
# by the Free Software Foundation. | ||
# | ||
# This program is distributed in the hope that it will be useful, but WITHOUT | ||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
# more details. | ||
# | ||
# You should have received a copy of the GNU General Public License along | ||
# with this program; if not, contact SUSE LLC. | ||
# | ||
# To contact SUSE LLC about this file by physical or electronic mail, you may | ||
# find current contact information at www.suse.com. | ||
|
||
require "json" | ||
require "yast2/execute" | ||
|
||
module Y2Users | ||
# This class represents a block device reported by `lsblk` as a leaf node | ||
# | ||
# As we cannot use a devicegraph for the time being, this class extracts the | ||
# block devices information from the lsblk command. Only the leaf devices | ||
# are taken into account and it only includes information which is relevant | ||
# for the {Y2Users::Widgets::DiskSelector} widget. | ||
class LeafBlkDevice | ||
class << self | ||
# Returns all relevant block devices | ||
# | ||
# @note It takes the information from `lsblk` | ||
# | ||
# @return [Array<LeafBlkDevice>] List of relevant block devices | ||
def all | ||
@all ||= lsblk["blockdevices"].map { |h| new_from_hash(h) } | ||
end | ||
|
||
# Instantiates a new object | ||
# | ||
# @note It uses a Hash with information from `lsblk`. | ||
# | ||
# @return [LeafBlkDevice] New LeafBlkDevice instance | ||
def new_from_hash(hash) | ||
parent = find_root_device(hash) | ||
removable = hash["rm"] == "1" | ||
new( | ||
name: hash["name"], disk: parent["name"], fstype: hash["fstype"], | ||
model: parent["model"], removable: removable | ||
) | ||
end | ||
|
||
private | ||
|
||
# Gets `lsblk` into a Hash | ||
# | ||
# @note The output is in inverse order, as we are only interested in leaf nodes. | ||
# | ||
# @return [Hash] Hash containing data from `lsblk` | ||
def lsblk | ||
output = Yast::Execute.locally( | ||
"/usr/bin/lsblk", "--inverse", "--json", "--paths", | ||
"--output", "NAME,TRAN,FSTYPE,RM,MODEL", stdout: :capture | ||
) | ||
JSON.parse(output) | ||
end | ||
|
||
# Finds the root for a given device | ||
# | ||
# @return [Hash] | ||
def find_root_device(hash) | ||
hash.key?("children") ? find_root_device(hash["children"][0]) : hash | ||
end | ||
end | ||
|
||
# @return [String] Kernel name | ||
attr_reader :name | ||
|
||
# @return [String] Hardware model | ||
attr_reader :model | ||
|
||
# @return [String] Disk's kernel name | ||
attr_reader :disk | ||
|
||
# @return [Symbol] Filesystem type | ||
attr_reader :fstype | ||
|
||
# @return [Boolean] Indicates whether the device is mountable or not | ||
attr_reader :removable | ||
|
||
alias_method :removable?, :removable | ||
|
||
# Constructor | ||
# | ||
# @param name [String] Kernel name | ||
# @param model [String] Hardware model | ||
# @param disk [String] Disk's kernel name | ||
# @param fstype [Symbol] Filesystem type | ||
# @param removable [Boolean] Indicates whether the device is mountable or not | ||
def initialize(name:, model:, disk:, fstype:, removable:) | ||
@name = name | ||
@model = model | ||
@disk = disk | ||
@fstype = fstype.to_sym if fstype | ||
@removable = removable | ||
end | ||
|
||
# Determines whether the device has a filesystem | ||
# | ||
# @return [Boolean] | ||
def filesystem? | ||
!!fstype | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# encoding: utf-8 | ||
|
||
# Copyright (c) [2018] SUSE LLC | ||
# | ||
# All Rights Reserved. | ||
# | ||
# This program is free software; you can redistribute it and/or modify it | ||
# under the terms of version 2 of the GNU General Public License as published | ||
# by the Free Software Foundation. | ||
# | ||
# This program is distributed in the hope that it will be useful, but WITHOUT | ||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
# more details. | ||
# | ||
# You should have received a copy of the GNU General Public License along | ||
# with this program; if not, contact SUSE LLC. | ||
# | ||
# To contact SUSE LLC about this file by physical or electronic mail, you may | ||
# find current contact information at www.suse.com. | ||
|
||
require "cwm" | ||
require "users/leaf_blk_device" | ||
|
||
module Y2Users | ||
module Widgets | ||
# This widget allows to select a removable device | ||
class DiskSelector < ::CWM::ComboBox | ||
# Constructor | ||
def initialize | ||
textdomain "users" | ||
self.widget_id = "disk_selector" | ||
end | ||
|
||
# @see CWM::AbstractWidget | ||
def label | ||
"" | ||
end | ||
|
||
# @see CWM::AbstractWidget | ||
def init | ||
self.value = devices.first.name unless devices.empty? | ||
end | ||
|
||
# @see CWM::ComboBox#items | ||
def items | ||
devices.map { |d| [d.name, item_label(d)] } | ||
end | ||
|
||
private | ||
|
||
# Returns the list of devices that can be selected | ||
# | ||
# @note Basically only removable devices are supported. | ||
# | ||
# @return [Array<LeafBlkDevice>] | ||
def devices | ||
@devices ||= LeafBlkDevice.all.select(&:filesystem?) | ||
end | ||
|
||
# Returns the description to be used for a given item | ||
# | ||
# @return [String] | ||
def item_label(dev) | ||
"#{dev.model} (#{dev.name})" | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
# encoding: utf-8 | ||
|
||
# Copyright (c) [2018] SUSE LLC | ||
# | ||
# All Rights Reserved. | ||
# | ||
# This program is free software; you can redistribute it and/or modify it | ||
# under the terms of version 2 of the GNU General Public License as published | ||
# by the Free Software Foundation. | ||
# | ||
# This program is distributed in the hope that it will be useful, but WITHOUT | ||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
# more details. | ||
# | ||
# You should have received a copy of the GNU General Public License along | ||
# with this program; if not, contact SUSE LLC. | ||
# | ||
# To contact SUSE LLC about this file by physical or electronic mail, you may | ||
# find current contact information at www.suse.com. | ||
|
||
require "cwm" | ||
require "users/widgets/disk_selector" | ||
require "yast2/execute" | ||
require "yast2/popup" | ||
require "tmpdir" | ||
|
||
Yast.import "UI" | ||
Yast.import "SSHAuthorizedKeys" | ||
|
||
module Y2Users | ||
module Widgets | ||
# This widget allows to select a public key from a removable device | ||
class PublicKeySelector < ::CWM::CustomWidget | ||
# @!attribute [r] | ||
# @return [String] Public key content | ||
attr_reader :value | ||
|
||
# Constructor | ||
def initialize | ||
textdomain "users" | ||
end | ||
|
||
# @return [String] Widget label | ||
def label | ||
_("Import Public Key") | ||
end | ||
|
||
# @return [Yast::Term] Dialog content | ||
# @see CWM::CustomWidget | ||
def contents | ||
VBox( | ||
Left(Label(label)), | ||
HBox( | ||
disk_selector, | ||
HStretch(), | ||
PushButton(Id(:browse), "Browse..."), | ||
), | ||
ReplacePoint(Id(:fingerprint), Empty()) | ||
) | ||
end | ||
|
||
# Events handler | ||
# | ||
# @see CWM::AbstractWdiget | ||
def handle(event) | ||
read_key if event["ID"] == :browse | ||
nil | ||
end | ||
|
||
# @see CWM::AbstractWdiget | ||
def store | ||
Yast::SSHAuthorizedKeys.import_keys("/root", [value]) if value | ||
nil | ||
end | ||
|
||
private | ||
|
||
attr_writer :value | ||
|
||
# Builds a widget to select the disk to read the public key from | ||
# | ||
# @return [DiskSelector] Disk selection widget | ||
def disk_selector | ||
@disk_selector ||= DiskSelector.new | ||
end | ||
|
||
# Reads the key selected by the user | ||
# | ||
# @note This method mounts the selected filesystem. | ||
# | ||
# @return [String] Key content | ||
def read_key | ||
dir = Dir.mktmpdir | ||
begin | ||
mounted = Yast::SCR.Execute( | ||
Yast::Path.new(".target.mount"), [disk_selector.value, dir], "-o ro" | ||
) | ||
if mounted | ||
self.value = read_key_from(dir) | ||
refresh_fingerprint | ||
else | ||
report_mount_error(disk_selector.value) | ||
end | ||
ensure | ||
Yast::SCR.Execute(Yast::Path.new(".target.umount"), dir) if mounted | ||
FileUtils.remove_entry_secure(dir) | ||
end | ||
end | ||
|
||
# Reads a the key from the given directory | ||
# | ||
# @note Asks the user to select a file and tries to read it. | ||
def read_key_from(dir) | ||
path = Yast::UI.AskForExistingFile(dir, "*", _("Select a public key")) | ||
File.read(path) if path && File.exist?(path) | ||
end | ||
|
||
# Refreshes the fingerprint which is shown in the UI. | ||
def refresh_fingerprint | ||
Yast::UI::ReplaceWidget( | ||
Id(:fingerprint), Left(Label(fingerprint(value))) | ||
) | ||
end | ||
|
||
# Displays an error about the device which failed to be mounted | ||
# | ||
# @param device [String] Device's name | ||
def report_mount_error(device) | ||
message = format(_("Could not mount device %s"), device) | ||
Yast2::Popup.show(message, headline: :error) | ||
end | ||
|
||
# Calculates the fingerprint for a given key | ||
# | ||
# @param key [String] SSH public key | ||
# @return [String] Key's fingerprint | ||
def fingerprint(key) | ||
return "" unless key | ||
output = Yast::Execute.locally!( | ||
["echo", key], ["ssh-keygen", "-l", "-f", "/dev/stdin"], stdout: :capture | ||
) | ||
output.split(" ").at(1).to_s | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCpZC8ctjmn90B/MxLOdSjYM3Yl3qd+BhTWYdBNgO3B1fJ1JSegTgCpDM0krMHqd/OAslW5H3MRED7g7g9WkKZh5xTMGvH56yRitJySfSiK8uSxCu6Jg7NM11kqOs5/RwycHO8955QrEYyiWOx80unD+CBJxGEZCOu/DH3ca4yEigAt2HSuC8NPicmRJWua6IbDa+VSICvdOTdFTM8izScSd5WBFH1ULz0bBfLnyi/pIiMjuHB69AN4gsUGYgKjzUsnufKli+DmzACgVWTdQ3Ukax/4/wgXFMr3KsDNpTbn7ZZOKzPpIXpzlP9AwbHQdym6J2NAPYV+DDY3Kcr/vql9 dummy1@example.net |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"blockdevices": [ | ||
{"name": "/dev/sda1", "tran": null, "fstype": "vfat", "rm": "0", "model": null, | ||
"children": [ | ||
{"name": "/dev/sda", "tran": "sata", "fstype": null, "rm": "0", "model": "WDC WD10EZEX-75M"} | ||
] | ||
}, | ||
{"name": "/dev/sda2", "tran": null, "fstype": "ext4", "rm": "0", "model": null, | ||
"children": [ | ||
{"name": "/dev/sda", "tran": "sata", "fstype": null, "rm": "0", "model": "WDC WD10EZEX-75M"} | ||
] | ||
}, | ||
{"name": "/dev/sr0", "tran": "sata", "fstype": null, "rm": "1", "model": "DVD-ROM DS-8DBSH"}, | ||
{"name": "/dev/sr1", "tran": "usb", "fstype": "iso9660", "rm": "1", "model": "File-CD Gadget "} | ||
] | ||
} |
Oops, something went wrong.