Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First version of classes for importing SSH configuration
- Loading branch information
Showing
19 changed files
with
441 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
# Copyright (c) 2016 SUSE LLC. | ||
# All Rights Reserved. | ||
|
||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of version 2 or 3 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 about this file by physical or electronic mail, | ||
# you may find current contact information at www.suse.com | ||
|
||
require "installation/ssh_key" | ||
require "installation/ssh_config_file" | ||
|
||
module Installation | ||
# Class that allows to memorize the list of SSH keys and config files found in | ||
# a partition (i.e. the content of the /etc/ssh directory) | ||
# | ||
# Used by the SSH keys importing functionality. | ||
# | ||
# It provides class methods to hold a list of configurations | ||
class SshConfig | ||
DEFAULT_NAME = "Linux" | ||
|
||
@all = [] | ||
|
||
class << self | ||
# List of all the known configurations. Populated by .import. | ||
# @see .import | ||
# @see .export | ||
def all | ||
@all | ||
end | ||
|
||
# Imports ssh keys and config files from a given root directory and stores | ||
# the information in the global list (.all) | ||
# | ||
# @param root_dir [String] Path where the original "/" is mounted | ||
# @param device [String] Name of the mounted device | ||
def import(root_dir, device) | ||
config = from_dir(root_dir, device) | ||
return if config.keys.empty? && config.config_files.empty? | ||
|
||
@all << config | ||
end | ||
|
||
# Writes the selected ssh keys and config files in the ssh directory. | ||
# | ||
# Only files and keys with the flag #to_export? are written. | ||
# | ||
# @param root_dir [String] Path to use as "/" to locate the ssh directory | ||
def export(root_dir) | ||
dir = ssh_dir(root_dir) | ||
all.each { |config| config.write_files(dir) } | ||
end | ||
|
||
protected | ||
|
||
# Creates a new object with the information read from a directory | ||
# | ||
# @param root_dir [String] Path where the original "/" is mounted | ||
# @param device [String] Name of the mounted device | ||
def from_dir(root_dir, device) | ||
config = SshConfig.new(name_for(root_dir), device) | ||
dir = ssh_dir(root_dir) | ||
config.read_files(dir) | ||
config | ||
end | ||
|
||
def ssh_dir(root_dir) | ||
File.join(root_dir, "etc", "ssh") | ||
end | ||
|
||
def os_release_file(root_dir) | ||
File.join(root_dir, "etc", "os-release") | ||
end | ||
|
||
# Find out the name for a previous Linux installation. | ||
# This uses /etc/os-release which is specified in | ||
# https://www.freedesktop.org/software/systemd/man/os-release.html | ||
# | ||
# @param mount_point [String] Path where the original "/" is mounted | ||
# @return [String] Speaking name of the Linux installation | ||
# | ||
def name_for(mount_point) | ||
os_release = parse_ini_file(os_release_file(mount_point)) | ||
name = os_release["PRETTY_NAME"] | ||
if name.empty? || name == DEFAULT_NAME | ||
name = os_release[NAME] || DEFAULT_NAME | ||
name += os_release[VERSION] | ||
end | ||
name | ||
rescue Errno::ENOENT # No /etc/os-release found | ||
DEFAULT_NAME | ||
end | ||
|
||
# Parse a simple .ini file and return the content in a hash. | ||
# | ||
# @param filename [String] Name of the file to parse | ||
# @return [Hash<String, String>] file content as hash | ||
# | ||
def parse_ini_file(filename) | ||
content = {} | ||
File.readlines(filename).each do |line| | ||
line = line.lstrip.chomp | ||
next if line.empty? || line.start_with?("#") | ||
(key, value) = line.split("=") | ||
value.gsub!(/^\s*"/, "") | ||
value.gsub!(/"\s*$/, "") | ||
content[key] = value | ||
end | ||
content | ||
end | ||
end | ||
|
||
# @return [String] name to help the user identify the configuration | ||
attr_accessor :system_name | ||
# @return [String] device name of the partition | ||
attr_accessor :device | ||
# @return [Array<SshKey>] keys found in the partition | ||
attr_accessor :keys | ||
# @return [Array<SshConfigFile>] configuration files found in the partition | ||
attr_accessor :config_files | ||
|
||
def initialize(system_name, device) | ||
self.system_name = system_name | ||
self.device = device | ||
self.keys = [] | ||
self.config_files = [] | ||
end | ||
|
||
# Populates the list of keys and config files from a ssh directory | ||
# | ||
# @param dir [String] path of the SSH directory | ||
def read_files(dir) | ||
filenames = Dir.glob("#{dir}/*") | ||
|
||
# Let's process keys first, pairs of files like "xyz" & "xyz.pub" | ||
pub_key_filenames = filenames.select { |f| f.end_with?(SshKey::PUBLIC_FILE_SUFFIX) } | ||
pub_key_filenames.each do |pub_file| | ||
# Remove the .pub suffix | ||
priv_file = pub_file.chomp(SshKey::PUBLIC_FILE_SUFFIX) | ||
add_key(priv_file) | ||
filenames.delete(pub_file) | ||
filenames.delete(priv_file) | ||
end | ||
|
||
filenames.each do |name| | ||
add_config_file(name) | ||
end | ||
end | ||
|
||
# Writes the files to a directory | ||
# | ||
# @param dir [String] path of the target SSH directory | ||
def write_files(dir) | ||
keys.select(&:to_export?).each do |key| | ||
key.write_files(dir) | ||
end | ||
config_files.select(&:to_export?).each do |file| | ||
file.write(dir) | ||
end | ||
end | ||
|
||
# Access time of the most recently accessed SSH key. | ||
# | ||
# Needed to keep the default behavior backward compatible. | ||
# | ||
# @return [Time] | ||
def keys_atime | ||
keys.map(&:atime).max | ||
end | ||
|
||
# @return [Array<SshKey>] | ||
def keys_to_export | ||
keys.select(&:to_export?) | ||
end | ||
|
||
# @return [Array<SshConfigFile>] | ||
def config_files_to_export | ||
config_files.select(&:to_export?) | ||
end | ||
|
||
protected | ||
|
||
def add_key(priv_filename) | ||
key = SshKey.new(File.basename(priv_filename)) | ||
key.read_files(priv_filename) | ||
self.keys << key | ||
end | ||
|
||
def add_config_file(filename) | ||
file = SshConfigFile.new(File.basename(filename)) | ||
file.read(filename) | ||
config_files << file | ||
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 @@ | ||
# Copyright (c) 2016 SUSE LLC. | ||
# All Rights Reserved. | ||
|
||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of version 2 or 3 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 about this file by physical or electronic mail, | ||
# you may find current contact information at www.suse.com | ||
|
||
require "fileutils" | ||
|
||
module Installation | ||
# Class that allows to memorize a particular SSH config file found in a | ||
# partition. | ||
# | ||
# Used by the SSH configuration importing functionality. | ||
class SshConfigFile | ||
BACKUP_SUFFIX = ".yast.orig" | ||
|
||
# @return [String] file name | ||
attr_accessor :name | ||
# @return [Time] access time of the original file | ||
attr_accessor :atime | ||
# @return [String] content of the file | ||
attr_accessor :content | ||
# @return [Fixmum] mode of the original file. @see File.chmod | ||
attr_accessor :permissions | ||
# @return [Boolean] whether the file should be copied in the target system | ||
attr_writer :to_export | ||
|
||
def initialize(name) | ||
@name = name | ||
@to_export = false | ||
end | ||
|
||
def read(path) | ||
self.content = IO.read(path) | ||
self.atime = File.atime(path) | ||
self.permissions = File.stat(path).mode | ||
end | ||
|
||
def write(dir) | ||
path = File.join(dir, name) | ||
backup(path) | ||
IO.write(path, content) | ||
File.chmod(permissions, path) | ||
end | ||
|
||
# @return [Boolean] whether the file should be copied in the target system | ||
def to_export? | ||
!!@to_export | ||
end | ||
|
||
protected | ||
|
||
def backup(filename) | ||
::FileUtils.mv(filename, filename + BACKUP_SUFFIX) if File.exist?(filename) | ||
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,72 @@ | ||
# Copyright (c) 2016 SUSE LLC. | ||
# All Rights Reserved. | ||
|
||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of version 2 or 3 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 about this file by physical or electronic mail, | ||
# you may find current contact information at www.suse.com | ||
|
||
module Installation | ||
# Class that allows to memorize a particular SSH keys found in a partition. | ||
# | ||
# Used to implement the SSH keys importing functionality. | ||
class SshKey | ||
PUBLIC_FILE_SUFFIX = ".pub" | ||
|
||
# @return [String] name for the user to identify the key | ||
attr_accessor :name | ||
# @return [Time] access time of the most recently accessed file | ||
attr_accessor :atime | ||
# @return [Array<Keyfile>] list of files associated to the key | ||
attr_accessor :files | ||
# @return [Boolean] whether the key should be copied in the target system | ||
attr_writer :to_export | ||
|
||
def initialize(name) | ||
@name = name | ||
@files = [] | ||
@to_export = false | ||
end | ||
|
||
def read_files(priv_filename) | ||
add_file(priv_filename) if File.exist?(priv_filename) | ||
pub_filename = priv_filename + PUBLIC_FILE_SUFFIX | ||
add_file(pub_filename) if File.exist?(pub_filename) | ||
end | ||
|
||
def write_files(dir) | ||
files.each do |file| | ||
path = File.join(dir, file.filename) | ||
IO.write(path, file.content) | ||
File.chmod(file.permissions, path) | ||
end | ||
end | ||
|
||
# @return [Boolean] whether the key should be copied in the target system | ||
def to_export? | ||
!!@to_export | ||
end | ||
|
||
protected | ||
|
||
KeyFile = Struct.new(:filename, :content, :permissions) | ||
|
||
def add_file(path) | ||
content = IO.read(path) | ||
permissions = File.stat(path).mode | ||
self.files << KeyFile.new(File.basename(path), content, permissions) | ||
atime = File.atime(path) | ||
self.atime = atime unless self.atime && self.atime > atime | ||
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 @@ | ||
PRETTY_NAME="Operating system 1" |
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 @@ | ||
root1: content of moduli file |
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 @@ | ||
root1: content of ssh_config file |
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 @@ | ||
root1: content of ssh_host_dsa_key file |
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 @@ | ||
root1: content of ssh_host_dsa_key.pub file |
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 @@ | ||
root1: content of ssh_host_key file |
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 @@ | ||
root1: content of ssh_host_key.pub file |
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 @@ | ||
root1: content of sshd_config file |
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 @@ | ||
root2: content of known_hosts file |
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 @@ | ||
root2: content of ssh_config file |
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 @@ | ||
root2: content of ssh_host_ed25519_key file |
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 @@ | ||
root2: content of ssh_host_ed25519_key.pub file |
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 @@ | ||
root2: content of ssh_host_key file |
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 @@ | ||
root2: content of ssh_host_key.pub file |
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 @@ | ||
root2: content of sshd_config file |
Oops, something went wrong.