freydis 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,60 +1,88 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optparse'
2
4
 
3
5
  module Freydis
4
6
  class Options
5
- attr_accessor :init, :backup, :restore, :encrypt,
6
- :open, :close,
7
- :disk
8
-
9
- def initialize(args)
10
- @init = false
11
- @backup = false
12
- @restore = false
13
- @encrypt = false
14
- @open = false
15
- @close = false
16
- @disk = nil
17
- parse(args)
7
+ def initialize(argv)
8
+ parse(argv)
18
9
  end
19
10
 
20
11
  private
21
12
 
22
13
  def parse(argv)
23
14
  OptionParser.new do |opts|
24
- opts.banner = "Usage: freydis.rb [options]"
15
+ opts.banner = 'Usage: freydis.rb [options]'
16
+ opts.version = VERSION
17
+
18
+ opts.on('--disk NAME', /^sd[a-z]$/, 'Use the disk NAME (e.g: sda, sdb).') do |disk|
19
+ Freydis::CONFIG.disk = Guard.disk(disk)
20
+ end
21
+
22
+ opts.on('--gpg-recipient NAME', String, 'Use gpg key NAME.') do |key|
23
+ Freydis::CONFIG.gpg_recipient = Guard.gpg(key)
24
+ end
25
+
26
+ opts.on('-p PATHS', '--paths-add PATHS', Array, 'Add absolute PATHS to the backup list.') do |paths|
27
+ paths.each do |p|
28
+ Freydis::Guard.path? p
29
+ Freydis::CONFIG.paths << p
30
+ end
31
+
32
+ end
33
+
34
+ opts.on('-d PATH', '--path-del PATH', String, 'Remove absolute PATH from the backup list.') do |p|
35
+ Freydis::Guard.path? p
36
+ Freydis::CONFIG.paths.delete p if CONFIG.paths.include? p
37
+ end
38
+
39
+ opts.on('-L', '--paths-list', 'List all paths from your list.') do
40
+ if Freydis::CONFIG.paths.nil?
41
+ puts 'Nothing in paths yet...'
42
+ else
43
+ puts Freydis::CONFIG.paths
44
+ end
45
+ end
46
+
47
+ # Engines options
48
+
49
+ opts.on('-e', '--encrypt', 'Encrypt and format (ext4) your device.') do
50
+ Freydis::DiskLuks.encrypt
51
+ end
25
52
 
26
- opts.on("-i", "--init", "Create a config file.") do
27
- @init = true
53
+ opts.on('-o', '--open', 'Open and mount encrypted disk at /mnt/freydis.') do
54
+ Freydis::DiskLuks.open
28
55
  end
29
56
 
30
- opts.on("-b", "--backup", "Perform a backup.") do
31
- @backup = true
57
+ opts.on('-c', '--close', 'Umount and close encrypted disk.') do
58
+ Freydis::DiskLuks.close
32
59
  end
33
60
 
34
- opts.on("-r", "--restore", "Restore saved datas on your system.") do
35
- @restore = true
61
+ opts.on('-b', '--backup', 'Perform a backup.') do
62
+ Freydis::Rsync.new.backup
36
63
  end
37
64
 
38
- opts.on("-e", "--encrypt", "Encrypt your device.") do
39
- @encrypt = true
65
+ opts.on('-r', '--restore', 'Restore saved datas on your system.') do
66
+ Freydis::Rsync.new.restore
40
67
  end
41
68
 
42
- opts.on("-o", "--open", "Open and mount encrypted device at /mnt/freydis.") do
43
- @open = true
69
+ opts.on('--secrets-backup', 'Backup only secrets, including GPG keys.') do |s|
70
+ Freydis::Secrets.backup
44
71
  end
45
72
 
46
- opts.on("-c", "--close", "Umount & close encrypted device.") do
47
- @close = true
73
+ opts.on('--secrets-restore', 'Restore secrets.') do |s|
74
+ Freydis::Secrets.restore
48
75
  end
49
76
 
50
- opts.on("-dNAME", "--disk NAME", "To use the disk NAME (e.g: sda, sdb).") do |disk|
51
- @disk = disk if Freydis::Guard.disk? disk
77
+ opts.on('-s', '--save', 'Save current arguments in the config file.') do
78
+ Freydis::CONFIG.save
52
79
  end
53
80
 
54
81
  begin
55
82
  opts.parse!(argv)
56
83
  rescue OptionParser::ParseError => e
57
- STDERR.puts e.message, "\n", opts
84
+ warn e.message, "\n", opts
85
+ exit 1
58
86
  end
59
87
  end
60
88
  end
data/lib/freydis/rsync.rb CHANGED
@@ -1,53 +1,47 @@
1
- # lib/rsync.rb
1
+ # frozen_string_literal: true
2
+
3
+ require 'mods/exec'
2
4
 
3
5
  module Freydis
4
6
  class Rsync
5
- def initialize(data)
6
- @data = data
7
- @mountpoint = '/mnt/freydis'
8
- @exclude_paths = [
9
- "/dev/*",
10
- "/proc/*",
11
- "/sys/*",
12
- "/tmp/*",
13
- "/run/*",
14
- "/mnt/*",
15
- "/media/*",
16
- "/home/*/.thumbnails/*",
17
- "/home/*/.cache/mozilla/*",
18
- "/home/*/.cache/chromium/*",
19
- "/home/*/.local/share/Trash/*",
20
- "/lost+found",
7
+ include Exec
8
+
9
+ def initialize
10
+ @workdir = '/mnt/freydis/backup/'
11
+ @exclude_paths = %w[
12
+ /dev/*
13
+ /proc/*
14
+ /sys/*
15
+ /tmp/*
16
+ /run/*
17
+ /mnt/*
18
+ /media/*
19
+ /var/lib/dhcpcd/*
20
+ /home/*/.gvfs
21
+ /home/*/.thumbnails/*
22
+ /home/*/.cache/*
23
+ /home/*/.local/share/*
24
+ /home/*/.Xauthority
25
+ /home/*/.xsession-errors
26
+ /lost+found
21
27
  ]
22
- @opts = "-aAXHv"
28
+ @opts = '-aAXHvRx'
23
29
  end
24
30
 
25
31
  def backup
26
- add_config
27
- exil = @exclude_paths * ","
28
- save = @data.options[:paths] * " "
29
- @opts += " --delete"
30
- exec("rsync #{@opts} --exclude={#{exil}} #{save} #{@mountpoint}")
32
+ Freydis::DiskLuks.open
33
+ mkdir @workdir
34
+ exil = @exclude_paths * ','
35
+ save = CONFIG.paths * ' '
36
+ @opts += ' --delete'
37
+ x "rsync #{@opts} --exclude={#{exil}} #{save} #{@workdir}"
38
+ Freydis::DiskLuks.close
31
39
  end
32
40
 
33
41
  def restore
34
- exil = @exclude_paths * ","
35
- exec("rsync #{@opts} --exclude={#{exil}} #{@mountpoint} /")
36
- end
37
-
38
- private
39
-
40
- def add_config
41
- if !@data.options[:paths].include?("#{ENV['HOME']}/.config/freydis")
42
- @data.options[:paths] << "#{ENV['HOME']}/.config/freydis"
43
- end
44
- end
45
-
46
- def exec(command)
47
- sudo = Process.uid != 0 ? 'sudo' : ''
48
- if !system("#{sudo} #{command}")
49
- raise StandardError, "[-] #{command}"
50
- end
42
+ Freydis::DiskLuks.open
43
+ x "rsync #{@opts} #{@workdir} /"
44
+ Freydis::DiskLuks.close
51
45
  end
52
46
  end
53
47
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'fileutils'
5
+
6
+ module Freydis
7
+ module Secrets
8
+ # Create or Restore an archive of secrets with bsdtar
9
+ class Archive
10
+ include Exec
11
+ include Msg
12
+
13
+ def initialize(gpg)
14
+ @workdir = '/mnt/freydis/secrets'
15
+ @filename = "#{@workdir}/#{CONFIG.gpg_recipient}_#{Date.today}.tar.gz"
16
+ @restore_dir = '/tmp'
17
+ @include_paths = %w[]
18
+ @gpg = gpg
19
+ end
20
+
21
+ def create
22
+ populate_include
23
+ inc_paths = @include_paths * ' '
24
+
25
+ mkdir @workdir
26
+ info "Creating archive #{@filename}..."
27
+ bsdtar "--acls --xattrs -cpvf #{@filename} #{inc_paths}"
28
+ @gpg.clean_keys
29
+ end
30
+
31
+ # Restore the most recent archive in your $HOME
32
+ def restore
33
+ last_archive = Dir.glob("#{@workdir}/*").sort[0]
34
+
35
+ mkdir @restore_dir
36
+ info "Restoring #{last_archive}..."
37
+ bsdtar "-xvf #{last_archive} -C #{@restore_dir}"
38
+ @gpg.import_keys @restore_dir
39
+ @gpg.clean_keys @restore_dir
40
+ end
41
+
42
+ protected
43
+
44
+ def populate_include
45
+ @gpg.export_keys unless File.exist? @gpg.seckey_path
46
+ search_paths(%W[#{ENV['HOME']}/.password-store
47
+ #{@gpg.seckey_path}
48
+ #{@gpg.pubkey_path}])
49
+ end
50
+
51
+ private
52
+
53
+ def search_paths(paths)
54
+ paths.each do |p|
55
+ if Dir.exist?(p) || File.exist?(p)
56
+ info "Found #{p}, add to archive..."
57
+ @include_paths << p
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Freydis
4
+ module Secrets
5
+ class GPG
6
+ include Exec
7
+ include Msg
8
+
9
+ attr_reader :seckey_path, :pubkey_path
10
+
11
+ def initialize
12
+ @recipient = Guard.gpg(CONFIG.gpg_recipient)
13
+ @seckey_path = "/tmp/#{@recipient}-secret.key"
14
+ @pubkey_path = "/tmp/#{@recipient}-public.key"
15
+ end
16
+
17
+ def export_keys
18
+ info "Exporting keys for #{@recipient}..."
19
+ gpg "-a --export-secret-keys --armor #{@recipient} >#{@seckey_path}"
20
+ gpg "-a --export --armor #{@recipient} >#{@pubkey_path}"
21
+ end
22
+
23
+ def import_keys(prefix = nil)
24
+ is_key = `gpg -K | grep #{@recipient}`.chomp
25
+ if is_key.empty?
26
+ info "Importing key #{@recipient}..."
27
+ gpg_import(prefix)
28
+ else
29
+ info "Key #{@recipient} is alrealy present, skip import."
30
+ end
31
+ end
32
+
33
+ def clean_keys(prefix = nil)
34
+ if prefix
35
+ shred "#{prefix}#{@seckey_path}", "#{prefix}#{@pubkey_path}"
36
+ else
37
+ shred @seckey_path, @pubkey_path
38
+ end
39
+ success "Clean keys."
40
+ end
41
+
42
+ protected
43
+
44
+ def gpg_import(prefix)
45
+ if prefix
46
+ gpg "--armor --import #{prefix}#{@seckey_path}"
47
+ gpg "--armor --import #{prefix}#{@pubkey_path}"
48
+ else
49
+ gpg "--armor --import #{@seckey_path}"
50
+ gpg "--armor --import #{@pubkey_path}"
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def gpg(command)
57
+ unless system("gpg #{command}")
58
+ error "Exe: gpg #{command}"
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mods/msg'
4
+ require_relative 'secrets/gpg'
5
+ require_relative 'secrets/archive'
6
+
7
+ module Freydis
8
+ module Secrets
9
+ extend Msg
10
+
11
+ def self.backup
12
+ DiskLuks.open
13
+ info 'Backup secrets...'
14
+ gpg = GPG.new
15
+ archive = Archive.new(gpg)
16
+ archive.create
17
+ DiskLuks.close
18
+ end
19
+
20
+ def self.restore
21
+ DiskLuks.open
22
+ info 'Restoring secrets...'
23
+ gpg = GPG.new
24
+ archive = Archive.new(gpg)
25
+ archive.restore
26
+ DiskLuks.close
27
+ end
28
+ end
29
+ end
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Freydis
2
- VERSION = '0.0.2'.freeze
4
+ VERSION = '0.1.0'
3
5
  end
4
6
 
data/lib/freydis.rb CHANGED
@@ -1,12 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'freydis/version'
2
4
  require_relative 'freydis/options'
3
- require_relative 'freydis/init'
4
- require_relative 'freydis/data'
5
+ require_relative 'freydis/config'
5
6
  require_relative 'freydis/disk'
7
+ require_relative 'freydis/disk_luks'
6
8
  require_relative 'freydis/cryptsetup'
7
9
  require_relative 'freydis/rsync'
10
+ require_relative 'freydis/error'
8
11
  require_relative 'freydis/guard'
12
+ require_relative 'freydis/secrets'
9
13
 
10
14
  module Freydis
11
- end
15
+ CONFIG = Config.new
16
+ CONFIG.load
17
+
18
+ class Main
19
+ def initialize(args)
20
+ @argv = args[:argv]
21
+ end
12
22
 
23
+ def start
24
+ Options.new(@argv)
25
+ end
26
+
27
+ def bye
28
+ puts
29
+ puts "Bye !"
30
+ exit
31
+ end
32
+ end
33
+ end
data/lib/mods/exec.rb ADDED
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exec
4
+ def x(command)
5
+ sudo = Process.uid != 0 ? 'sudo' : ''
6
+ unless system("#{sudo} #{command}")
7
+ Msg.error "Execute: #{command}"
8
+ end
9
+ end
10
+
11
+ def mkdir(dir)
12
+ if Process.uid == 0
13
+ FileUtils.mkdir_p dir
14
+ else
15
+ x "mkdir -p #{dir}"
16
+ end
17
+ end
18
+
19
+ def bsdtar(args)
20
+ x "bsdtar #{args}"
21
+ end
22
+
23
+ def shred(*keys)
24
+ keys_join = keys * ' '
25
+ x "shred -u #{keys_join}"
26
+ end
27
+ end
data/lib/mods/msg.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Msg
4
+ def info(msg)
5
+ puts "> #{msg}"
6
+ end
7
+
8
+ def success(msg)
9
+ puts " ===> #{msg}"
10
+ end
11
+
12
+ def error(msg)
13
+ warn "[-] #{msg}"
14
+ exit 1
15
+ end
16
+ end
data.tar.gz.sig ADDED
Binary file
metadata CHANGED
@@ -1,48 +1,80 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: freydis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - szorfein
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain:
11
- - certs/szorfein.pem
12
- date: 2021-05-18 00:00:00.000000000 Z
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEhTCCAu2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDDAhzem9y
14
+ ZmVpbjEaMBgGCgmSJomT8ixkARkWCnByb3Rvbm1haWwxEzARBgoJkiaJk/IsZAEZ
15
+ FgNjb20wHhcNMjIwOTA4MDYyNjE5WhcNMjMwOTA4MDYyNjE5WjBEMREwDwYDVQQD
16
+ DAhzem9yZmVpbjEaMBgGCgmSJomT8ixkARkWCnByb3Rvbm1haWwxEzARBgoJkiaJ
17
+ k/IsZAEZFgNjb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDEJNhl
18
+ Gd0JNHLXysR7GvbCKD+y1prQbmS333GpoFgPR2chEGv8Y7l0We2UFXCZ59CVOs1v
19
+ KBVQhhNvxWAHWhfe/8stb1JFBxZpnCi7S0BGpqeblaGBXVlhBOzbZ6d1NrOwMfDS
20
+ 6EzdX4WAOH55HnAz29T5KREUdbONVLU7HJNIIFVZvf6ethOv84pnkWbdWjV0RB3A
21
+ ERYste5QHGx1YQOYGTuJMlu8113kqTbB8wpEw6X00aJwmXcJvnKXkhN5mxd06yss
22
+ EE96lOk16raTWCh7DeYR3/ilVet3DpLlCvpFNtMIuko1HFa3HTW+57003VxD8Ozk
23
+ VGQKn823D+ReujKh+jgxbl8Q+r652C9Wl1N+C5CSma4mDtNGKr0XmEOEQycpSx0z
24
+ Z9J6/27wS8s6SJ0rLxueFQ6gb2oPEQb8jKJuNEuXWLmO3Idrwlv9Z7ymhnksjyqM
25
+ fAw+NMGEOCITNphXmssazlLX+bnxcbpr7rbTHa1xBmmHoUVudAnxAG43PrMCAwEA
26
+ AaOBgTB/MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBRzxda94CPF
27
+ Ll9UQ5l55l65RCZuEzAiBgNVHREEGzAZgRdzem9yZmVpbkBwcm90b25tYWlsLmNv
28
+ bTAiBgNVHRIEGzAZgRdzem9yZmVpbkBwcm90b25tYWlsLmNvbTANBgkqhkiG9w0B
29
+ AQsFAAOCAYEAPhavFyzIP60Zw7y40zJhzQpMK2IWtdw9HrRJq313Ea4UT1Kgv7F9
30
+ lCFtQzI5XMzooYiLMoPz7xBMXaUz+DDFOOcgGSinVrFbfPA4rOGEkBjnlwC39lBc
31
+ AiyXFzCV7Wqn4VhtqQQyvmoNYL4Q666K+nL8/nsXZWsXtRQ119LeAvrI2A+xmYAb
32
+ FPE5bD3Jx1JCoJdVN1DmE4YYdM8mVmb0XjCK9Tp1M01EDKDvAX7f3B+X6A5D7uBq
33
+ 63X6Kx09VkntVOrifd3W4TwjDlyAMpB+50OIi3ErPnH2R4i09qnCiZmcVWATBVKw
34
+ e2QSloIAUZJwEFkrRqWPNVi8sr+BcMeuKpXaOwpbkP+xq/W2EKlUQKhPXMXS4jvC
35
+ MuTi+RjpSNKZxzBrOlK2eMIpiFrugF7nzKcM9EGnWRWUb899drCcD4VJhjPtgpn+
36
+ aEJeKq4/BlIwMlXPe+W5C8zp2i8hgG1/OYbwbGE1p2iRi1NIK7G/HyRqQjOqJxzE
37
+ LLknX69FN7/G
38
+ -----END CERTIFICATE-----
39
+ date: 2022-09-20 00:00:00.000000000 Z
13
40
  dependencies: []
14
- description: " Freydis is a CLI tool to encrypt a disk device, backup and restore
15
- easyly. Freydis use `cryptsetup` and `rsync` mainly.\n"
41
+ description: 'Freydis is a CLI tool to encrypt a disk device, backup and restore easyly.
42
+ Freydis use `cryptsetup` and `rsync` mainly.
43
+
44
+ '
16
45
  email: szorfein@protonmail.com
17
46
  executables:
18
47
  - freydis
19
48
  extensions: []
20
- extra_rdoc_files:
21
- - README.md
49
+ extra_rdoc_files: []
22
50
  files:
23
51
  - CHANGELOG.md
24
52
  - LICENSE
25
53
  - README.md
26
- - Rakefile
27
54
  - bin/freydis
28
55
  - freydis.gemspec
29
56
  - lib/freydis.rb
57
+ - lib/freydis/config.rb
30
58
  - lib/freydis/cryptsetup.rb
31
- - lib/freydis/data.rb
32
59
  - lib/freydis/disk.rb
60
+ - lib/freydis/disk_luks.rb
61
+ - lib/freydis/error.rb
33
62
  - lib/freydis/guard.rb
34
- - lib/freydis/init.rb
35
63
  - lib/freydis/options.rb
36
64
  - lib/freydis/rsync.rb
65
+ - lib/freydis/secrets.rb
66
+ - lib/freydis/secrets/archive.rb
67
+ - lib/freydis/secrets/gpg.rb
37
68
  - lib/freydis/version.rb
69
+ - lib/mods/exec.rb
70
+ - lib/mods/msg.rb
38
71
  homepage: https://github.com/szorfein/freydis
39
72
  licenses:
40
73
  - MIT
41
74
  metadata:
42
75
  bug_tracker_uri: https://github.com/szorfein/freydis/issues
43
- changelog_uri: https://github.com/szorfein/freydis/blob/master/CHANGELOG.md
76
+ changelog_uri: https://github.com/szorfein/freydis/blob/main/CHANGELOG.md
44
77
  source_code_uri: https://github.com/szorfein/freydis
45
- wiki_uri: https://github.com/szorfein/freydis/wiki
46
78
  funding_uri: https://patreon.com/szorfein
47
79
  post_install_message:
48
80
  rdoc_options: []
@@ -59,9 +91,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
91
  - !ruby/object:Gem::Version
60
92
  version: '0'
61
93
  requirements:
62
- - cryptsetup, v2.3
63
- - rsync, v3.2
64
- rubygems_version: 3.0.9
94
+ - cryptsetup
95
+ - rsync
96
+ rubygems_version: 3.3.19
65
97
  signing_key:
66
98
  specification_version: 4
67
99
  summary: Backup and Restore data from encrypted device.
metadata.gz.sig ADDED
Binary file
data/Rakefile DELETED
@@ -1,21 +0,0 @@
1
- # https://github.com/seattlerb/minitest#running-your-tests-
2
- require "rake/testtask"
3
- require File.dirname(__FILE__) + "/lib/freydis/version"
4
-
5
- Rake::TestTask.new(:test) do |t|
6
- t.libs << "test"
7
- t.libs << "lib"
8
- t.test_files = FileList["test/test_*.rb"]
9
- end
10
-
11
- # Usage: rake gem:build
12
- namespace :gem do
13
- desc "build the gem"
14
- task :build do
15
- Dir["freydis*.gem"].each {|f| File.unlink(f) }
16
- system("gem build freydis.gemspec")
17
- system("gem install freydis-#{Freydis::VERSION}.gem")
18
- end
19
- end
20
-
21
- task :default => :test
data/lib/freydis/data.rb DELETED
@@ -1,39 +0,0 @@
1
- # lib/data.rb
2
-
3
- require 'yaml'
4
-
5
- module Freydis
6
- class Data
7
- attr_accessor :options
8
-
9
- def initialize
10
- @config_file = "#{ENV['HOME']}/.config/freydis/freydis.yaml"
11
- @options = {
12
- :disk => "",
13
- :disk_id => "",
14
- :disk_uuid => "",
15
- :disk_partuuid => "",
16
- :paths => []
17
- }
18
- end
19
-
20
- def load
21
- if File.exist? @config_file
22
- options_config = YAML.load_file @config_file
23
- @options.merge!(options_config)
24
- else
25
- save
26
- STDERR.puts "Initialized config at #{@config_file}"
27
- end
28
- end
29
-
30
- def save
31
- conf_dir = "#{ENV['HOME']}/.config/freydis"
32
- Dir.mkdir conf_dir if !Dir.exists? conf_dir
33
-
34
- File.open(@config_file, 'w') { |f|
35
- YAML::dump(@options, f)
36
- }
37
- end
38
- end
39
- end