Class: Installation::SshConfig

Inherits:
Object
  • Object
show all
Extended by:
Yast::I18n
Includes:
Yast::Logger
Defined in:
src/lib/installation/ssh_config.rb

Overview

Class that allows to memorize the list of SSH keys and config files found in a filesystem (i.e. the content of the /etc/ssh directory)

Used by the SSH keys importing functionality.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(system_name) ⇒ SshConfig

Returns a new instance of SshConfig.


107
108
109
110
111
# File 'src/lib/installation/ssh_config.rb', line 107

def initialize(system_name)
  self.system_name = system_name
  self.keys = []
  self.config_files = []
end

Instance Attribute Details

#config_filesArray<SshConfigFile>

Returns configuration files found in the partition.

Returns:

  • (Array<SshConfigFile>)

    configuration files found in the partition


105
106
107
# File 'src/lib/installation/ssh_config.rb', line 105

def config_files
  @config_files
end

#keysArray<SshKey>

Returns keys found in the partition.

Returns:

  • (Array<SshKey>)

    keys found in the partition


103
104
105
# File 'src/lib/installation/ssh_config.rb', line 103

def keys
  @keys
end

#system_nameString

Returns name to help the user identify the configuration.

Returns:

  • (String)

    name to help the user identify the configuration


101
102
103
# File 'src/lib/installation/ssh_config.rb', line 101

def system_name
  @system_name
end

Class Method Details

.from_dir(root_dir) ⇒ Object

Creates a new object with the information read from a filesystem

Parameters:

  • root_dir (String)

    Path where the original "/" is mounted


38
39
40
41
42
43
# File 'src/lib/installation/ssh_config.rb', line 38

def from_dir(root_dir)
  config = SshConfig.new(name_for(root_dir))
  dir = ssh_dir(root_dir)
  config.read_files(dir)
  config
end

.name_for(mount_point) ⇒ String (protected)

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

Parameters:

  • mount_point (String)

    Path where the original "/" is mounted

Returns:

  • (String)

    Speaking name of the Linux installation


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'src/lib/installation/ssh_config.rb', line 61

def name_for(mount_point)
  # TRANSLATORS: default name for a found Linux system (we don't know if
  # it's an openSUSE, Ubuntu...)
  default_name = _("Linux")
  os_release = parse_ini_file(os_release_file(mount_point))

  name = os_release["PRETTY_NAME"]
  if !name || name.empty?
    name = os_release["NAME"] || default_name
    name += " #{os_release["VERSION"]}"
  end
  name
rescue IOError, SystemCallError, RuntimeError => e
  log.error("Reading /etc/os-release failed with exception: #{e.inspect}")
  default_name
end

.os_release_file(root_dir) ⇒ Object (protected)


51
52
53
# File 'src/lib/installation/ssh_config.rb', line 51

def os_release_file(root_dir)
  File.join(root_dir, "etc", "os-release")
end

.parse_ini_file(filename) ⇒ Hash<String, String> (protected)

Parse a simple .ini file and return the content in a hash.

Parameters:

  • filename (String)

    Name of the file to parse

Returns:

  • (Hash<String, String>)

    file content as hash


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'src/lib/installation/ssh_config.rb', line 83

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("=")
    key.rstrip!
    value ||= "" # handle case `KEY=` (bsc#1139518)
    value.gsub!(/^\s*"/, "")
    value.gsub!(/"\s*$/, "")
    content[key] = value
  end
  content
end

.ssh_dir(root_dir) ⇒ Object


45
46
47
# File 'src/lib/installation/ssh_config.rb', line 45

def ssh_dir(root_dir)
  File.join(root_dir, "etc", "ssh")
end

Instance Method Details

#add_config_file(filename) ⇒ Object (protected)


167
168
169
170
171
# File 'src/lib/installation/ssh_config.rb', line 167

def add_config_file(filename)
  file = SshConfigFile.new(File.basename(filename))
  file.read(filename)
  config_files << file
end

#add_key(priv_filename) ⇒ Object (protected)


161
162
163
164
165
# File 'src/lib/installation/ssh_config.rb', line 161

def add_key(priv_filename)
  key = SshKey.new(File.basename(priv_filename))
  key.read_files(priv_filename)
  keys << key
end

#keys_atimeTime

Access time of the most recently accessed SSH key.

Needed to keep the default behavior backward compatible.

Returns:

  • (Time)

155
156
157
# File 'src/lib/installation/ssh_config.rb', line 155

def keys_atime
  keys.map(&:atime).max
end

#read_files(dir) ⇒ Object

Populates the list of keys and config files from a ssh configuration directory

Parameters:

  • dir (String)

    path of the SSH configuration directory


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'src/lib/installation/ssh_config.rb', line 117

def read_files(dir)
  filenames = Dir.glob("#{dir}/*").select { |f| File.file?(f) }

  # 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

#write_files(root_dir, write_keys: true, write_config_files: true) ⇒ Object

Writes keys and/or configuration files to a filesystem

Parameters:

  • root_dir (String)

    path where the target filesystem (/) is mounted

  • write_keys (Boolean) (defaults to: true)

    whether to copy the keys

  • write_config_files (Boolean) (defaults to: true)

    whether to copy the config files


140
141
142
143
144
145
146
147
148
# File 'src/lib/installation/ssh_config.rb', line 140

def write_files(root_dir, write_keys: true, write_config_files: true)
  log.info "Writing SSH keys and/or configuration: " \
           "keys: #{write_keys}, config: #{write_config_files}"
  dir = self.class.ssh_dir(root_dir)
  ::FileUtils.mkdir_p(dir)

  keys.each { |k| k.write_files(dir) } if write_keys
  config_files.each { |f| f.write(dir) } if write_config_files
end