#!/usr/bin/env ruby require 'pathname' require 'lxc' require 'etc' require_relative 'ns' require_relative 'cborio' require_relative 'lxc_extend' require_relative 'authorized_keys' class AuthorizedKeysCollector def initialize end def forked wr LXC.running_containers do |ct| pid = ct.init_pid NS.change pid, :pid, :mnt do name = ct.config_item( 'lxc.uts.name') conf = Hash.new {|h,k| h[k] = []} IO.popen %w[sshd -T], err: "/dev/null" do |s| s.each_line do |l| k, v = l.chomp.split( ' ', 2) conf[k.to_sym].push v end end akf = conf[:authorizedkeysfile].flat_map {|e| e.split ' ' } akf.map! do |pn| pn = "%h/#{pn}" if Pathname.new( pn).relative? pn.gsub( /%h/, "%s").gsub( /%u/, "%s") end while pw = Etc.getpwent wr.write [ :authkeys, ct.name, pw.name, akf.each.flat_map do |pn| pn = Pathname.new pn % {name: pw.name, home: pw.dir} pn.exist? ? pn.readlines.map( &:chomp) : [] end ] end Etc.endpwent end end end def collect pid, io = CBORIO.popen {|io| forked io } io.map do |l| case l[0].to_sym when :authkeys host, user, keys = l[1..3] keys.map! {|k| AuthorizedKeys.parse k } {host: host, user: user, keys: keys} end end end end if Pathname.new( __FILE__).expand_path == Pathname.new( $0).expand_path AuthorizedKeysCollector.new.collect.each {|e| p e } end