freydis 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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