interu-backup 3.0.16
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.
- data/.gitignore +2 -0
- data/Gemfile +31 -0
- data/Gemfile.lock +117 -0
- data/Guardfile +17 -0
- data/LICENSE.md +24 -0
- data/README.md +332 -0
- data/backup.gemspec +31 -0
- data/bin/backup +267 -0
- data/lib/backup.rb +181 -0
- data/lib/backup/archive.rb +73 -0
- data/lib/backup/cli.rb +82 -0
- data/lib/backup/compressor/base.rb +17 -0
- data/lib/backup/compressor/bzip2.rb +64 -0
- data/lib/backup/compressor/gzip.rb +61 -0
- data/lib/backup/configuration/base.rb +15 -0
- data/lib/backup/configuration/compressor/base.rb +10 -0
- data/lib/backup/configuration/compressor/bzip2.rb +23 -0
- data/lib/backup/configuration/compressor/gzip.rb +23 -0
- data/lib/backup/configuration/database/base.rb +18 -0
- data/lib/backup/configuration/database/mongodb.rb +41 -0
- data/lib/backup/configuration/database/mysql.rb +37 -0
- data/lib/backup/configuration/database/postgresql.rb +37 -0
- data/lib/backup/configuration/database/redis.rb +35 -0
- data/lib/backup/configuration/encryptor/base.rb +10 -0
- data/lib/backup/configuration/encryptor/gpg.rb +17 -0
- data/lib/backup/configuration/encryptor/open_ssl.rb +26 -0
- data/lib/backup/configuration/helpers.rb +54 -0
- data/lib/backup/configuration/notifier/base.rb +39 -0
- data/lib/backup/configuration/notifier/campfire.rb +25 -0
- data/lib/backup/configuration/notifier/mail.rb +52 -0
- data/lib/backup/configuration/notifier/presently.rb +25 -0
- data/lib/backup/configuration/notifier/twitter.rb +21 -0
- data/lib/backup/configuration/storage/base.rb +18 -0
- data/lib/backup/configuration/storage/cloudfiles.rb +21 -0
- data/lib/backup/configuration/storage/dropbox.rb +29 -0
- data/lib/backup/configuration/storage/ftp.rb +25 -0
- data/lib/backup/configuration/storage/rsync.rb +25 -0
- data/lib/backup/configuration/storage/s3.rb +25 -0
- data/lib/backup/configuration/storage/scp.rb +25 -0
- data/lib/backup/configuration/storage/sftp.rb +25 -0
- data/lib/backup/configuration/syncer/rsync.rb +45 -0
- data/lib/backup/configuration/syncer/s3.rb +33 -0
- data/lib/backup/database/base.rb +33 -0
- data/lib/backup/database/mongodb.rb +179 -0
- data/lib/backup/database/mysql.rb +104 -0
- data/lib/backup/database/postgresql.rb +111 -0
- data/lib/backup/database/redis.rb +105 -0
- data/lib/backup/dependency.rb +96 -0
- data/lib/backup/encryptor/base.rb +17 -0
- data/lib/backup/encryptor/gpg.rb +78 -0
- data/lib/backup/encryptor/open_ssl.rb +67 -0
- data/lib/backup/exception/command_not_found.rb +8 -0
- data/lib/backup/finder.rb +39 -0
- data/lib/backup/logger.rb +102 -0
- data/lib/backup/model.rb +272 -0
- data/lib/backup/notifier/base.rb +29 -0
- data/lib/backup/notifier/binder.rb +32 -0
- data/lib/backup/notifier/campfire.rb +194 -0
- data/lib/backup/notifier/mail.rb +141 -0
- data/lib/backup/notifier/presently.rb +105 -0
- data/lib/backup/notifier/templates/notify_failure.erb +33 -0
- data/lib/backup/notifier/templates/notify_success.erb +16 -0
- data/lib/backup/notifier/twitter.rb +87 -0
- data/lib/backup/storage/base.rb +67 -0
- data/lib/backup/storage/cloudfiles.rb +95 -0
- data/lib/backup/storage/dropbox.rb +91 -0
- data/lib/backup/storage/ftp.rb +114 -0
- data/lib/backup/storage/object.rb +45 -0
- data/lib/backup/storage/rsync.rb +129 -0
- data/lib/backup/storage/s3.rb +180 -0
- data/lib/backup/storage/scp.rb +106 -0
- data/lib/backup/storage/sftp.rb +106 -0
- data/lib/backup/syncer/base.rb +10 -0
- data/lib/backup/syncer/rsync.rb +152 -0
- data/lib/backup/syncer/s3.rb +118 -0
- data/lib/backup/version.rb +43 -0
- data/lib/templates/archive +7 -0
- data/lib/templates/compressor/bzip2 +7 -0
- data/lib/templates/compressor/gzip +7 -0
- data/lib/templates/database/mongodb +14 -0
- data/lib/templates/database/mysql +14 -0
- data/lib/templates/database/postgresql +14 -0
- data/lib/templates/database/redis +13 -0
- data/lib/templates/encryptor/gpg +12 -0
- data/lib/templates/encryptor/openssl +8 -0
- data/lib/templates/notifier/campfire +11 -0
- data/lib/templates/notifier/mail +17 -0
- data/lib/templates/notifier/presently +12 -0
- data/lib/templates/notifier/twitter +12 -0
- data/lib/templates/readme +15 -0
- data/lib/templates/storage/cloudfiles +10 -0
- data/lib/templates/storage/dropbox +12 -0
- data/lib/templates/storage/ftp +11 -0
- data/lib/templates/storage/rsync +10 -0
- data/lib/templates/storage/s3 +21 -0
- data/lib/templates/storage/scp +11 -0
- data/lib/templates/storage/sftp +11 -0
- data/lib/templates/syncer/rsync +17 -0
- data/lib/templates/syncer/s3 +15 -0
- data/spec/archive_spec.rb +90 -0
- data/spec/backup_spec.rb +11 -0
- data/spec/compressor/bzip2_spec.rb +59 -0
- data/spec/compressor/gzip_spec.rb +59 -0
- data/spec/configuration/base_spec.rb +35 -0
- data/spec/configuration/compressor/gzip_spec.rb +28 -0
- data/spec/configuration/database/base_spec.rb +16 -0
- data/spec/configuration/database/mongodb_spec.rb +30 -0
- data/spec/configuration/database/mysql_spec.rb +32 -0
- data/spec/configuration/database/postgresql_spec.rb +32 -0
- data/spec/configuration/database/redis_spec.rb +30 -0
- data/spec/configuration/encryptor/gpg_spec.rb +25 -0
- data/spec/configuration/encryptor/open_ssl_spec.rb +31 -0
- data/spec/configuration/notifier/campfire_spec.rb +20 -0
- data/spec/configuration/notifier/mail_spec.rb +32 -0
- data/spec/configuration/notifier/twitter_spec.rb +22 -0
- data/spec/configuration/storage/cloudfiles_spec.rb +34 -0
- data/spec/configuration/storage/dropbox_spec.rb +43 -0
- data/spec/configuration/storage/ftp_spec.rb +40 -0
- data/spec/configuration/storage/rsync_spec.rb +37 -0
- data/spec/configuration/storage/s3_spec.rb +37 -0
- data/spec/configuration/storage/scp_spec.rb +40 -0
- data/spec/configuration/storage/sftp_spec.rb +40 -0
- data/spec/configuration/syncer/rsync_spec.rb +46 -0
- data/spec/configuration/syncer/s3_spec.rb +43 -0
- data/spec/database/base_spec.rb +30 -0
- data/spec/database/mongodb_spec.rb +181 -0
- data/spec/database/mysql_spec.rb +150 -0
- data/spec/database/postgresql_spec.rb +164 -0
- data/spec/database/redis_spec.rb +122 -0
- data/spec/encryptor/gpg_spec.rb +57 -0
- data/spec/encryptor/open_ssl_spec.rb +102 -0
- data/spec/logger_spec.rb +58 -0
- data/spec/model_spec.rb +236 -0
- data/spec/notifier/campfire_spec.rb +96 -0
- data/spec/notifier/mail_spec.rb +97 -0
- data/spec/notifier/presently_spec.rb +99 -0
- data/spec/notifier/twitter_spec.rb +86 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/storage/base_spec.rb +33 -0
- data/spec/storage/cloudfiles_spec.rb +102 -0
- data/spec/storage/dropbox_spec.rb +105 -0
- data/spec/storage/ftp_spec.rb +133 -0
- data/spec/storage/object_spec.rb +74 -0
- data/spec/storage/rsync_spec.rb +131 -0
- data/spec/storage/s3_spec.rb +110 -0
- data/spec/storage/scp_spec.rb +129 -0
- data/spec/storage/sftp_spec.rb +125 -0
- data/spec/syncer/rsync_spec.rb +195 -0
- data/spec/syncer/s3_spec.rb +139 -0
- data/spec/version_spec.rb +21 -0
- metadata +231 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
module Database
|
|
5
|
+
class PostgreSQL < Base
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Name of the database that needs to get dumped
|
|
9
|
+
attr_accessor :name
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Credentials for the specified database
|
|
13
|
+
attr_accessor :username, :password
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Connectivity options
|
|
17
|
+
attr_accessor :host, :port, :socket
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# Tables to skip while dumping the database
|
|
21
|
+
attr_accessor :skip_tables
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Tables to dump, tables that aren't specified won't get dumped
|
|
25
|
+
attr_accessor :only_tables
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# Additional "pg_dump" options
|
|
29
|
+
attr_accessor :additional_options
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Creates a new instance of the PostgreSQL adapter object
|
|
33
|
+
# Sets the PGPASSWORD environment variable to the password
|
|
34
|
+
# so it doesn't prompt and hang in the process
|
|
35
|
+
def initialize(&block)
|
|
36
|
+
load_defaults!
|
|
37
|
+
|
|
38
|
+
@skip_tables ||= Array.new
|
|
39
|
+
@only_tables ||= Array.new
|
|
40
|
+
@additional_options ||= Array.new
|
|
41
|
+
|
|
42
|
+
instance_eval(&block)
|
|
43
|
+
prepare!
|
|
44
|
+
ENV['PGPASSWORD'] = password
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Builds the PostgreSQL syntax for specifying which tables to skip
|
|
49
|
+
# during the dumping of the database
|
|
50
|
+
def tables_to_skip
|
|
51
|
+
skip_tables.map do |table|
|
|
52
|
+
"--exclude-table='#{table}'"
|
|
53
|
+
end.join("\s")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# Builds the PostgreSQL syntax for specifying which tables to dump
|
|
58
|
+
# during the dumping of the database
|
|
59
|
+
def tables_to_dump
|
|
60
|
+
only_tables.map do |table|
|
|
61
|
+
"--table='#{table}'"
|
|
62
|
+
end.join("\s")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
# Builds the credentials PostgreSQL syntax to authenticate the user
|
|
67
|
+
# to perform the database dumping process
|
|
68
|
+
def credential_options
|
|
69
|
+
return '' unless username.is_a?(String) and not username.empty?
|
|
70
|
+
"--username='#{username}'"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
##
|
|
74
|
+
# Builds the PostgreSQL connectivity options syntax to connect the user
|
|
75
|
+
# to perform the database dumping process, socket gets gsub'd to host since
|
|
76
|
+
# that's the option PostgreSQL takes for socket connections as well. In case
|
|
77
|
+
# both the host and the socket are specified, the socket will take priority over the host
|
|
78
|
+
def connectivity_options
|
|
79
|
+
%w[host port socket].map do |option|
|
|
80
|
+
next if send(option).nil? or (send(option).respond_to?(:empty?) and send(option).empty?)
|
|
81
|
+
"--#{option}='#{send(option)}'".gsub('--socket=', '--host=')
|
|
82
|
+
end.compact.join("\s")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
##
|
|
86
|
+
# Builds a PostgreSQL compatible string for the additional options
|
|
87
|
+
# specified by the user
|
|
88
|
+
def options
|
|
89
|
+
additional_options.join("\s")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
##
|
|
93
|
+
# Builds the full pgdump string based on all attributes
|
|
94
|
+
def pgdump
|
|
95
|
+
"#{ utility(:pg_dump) } #{ credential_options } #{ connectivity_options } " +
|
|
96
|
+
"#{ options } #{ tables_to_dump } #{ tables_to_skip } #{ name }"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
##
|
|
100
|
+
# Performs the pgdump command and outputs the
|
|
101
|
+
# data to the specified path based on the 'trigger'
|
|
102
|
+
# and resets the 'PGPASSWORD' environment variable to nil
|
|
103
|
+
def perform!
|
|
104
|
+
log!
|
|
105
|
+
run("#{pgdump} > '#{File.join(dump_path, name)}.sql'")
|
|
106
|
+
ENV['PGPASSWORD'] = nil
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
module Database
|
|
5
|
+
class Redis < Base
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# Name of and path to the database that needs to get dumped
|
|
9
|
+
attr_accessor :name, :path
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Credentials for the specified database
|
|
13
|
+
attr_accessor :password
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Determines whether Backup should invoke the SAVE command through
|
|
17
|
+
# the 'redis-cli' utility to persist the most recent data before
|
|
18
|
+
# copying over the dump file
|
|
19
|
+
attr_accessor :invoke_save
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# Connectivity options
|
|
23
|
+
attr_accessor :host, :port, :socket
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# Additional "redis-cli" options
|
|
27
|
+
attr_accessor :additional_options
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# Creates a new instance of the Redis database object
|
|
31
|
+
def initialize(&block)
|
|
32
|
+
load_defaults!
|
|
33
|
+
|
|
34
|
+
@additional_options ||= Array.new
|
|
35
|
+
|
|
36
|
+
instance_eval(&block)
|
|
37
|
+
prepare!
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
##
|
|
41
|
+
# Builds the Redis credentials syntax to authenticate the user
|
|
42
|
+
# to perform the database dumping process
|
|
43
|
+
def credential_options
|
|
44
|
+
return "-a '#{password}'" if password; String.new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Builds the Redis connectivity options syntax to connect the user
|
|
49
|
+
# to perform the database dumping process
|
|
50
|
+
def connectivity_options
|
|
51
|
+
%w[host port socket].map do |option|
|
|
52
|
+
next if send(option).nil?; "-#{option[0,1]} '#{send(option)}'"
|
|
53
|
+
end.compact.join("\s")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# Builds a Redis compatible string for the
|
|
58
|
+
# additional options specified by the user
|
|
59
|
+
def additional_options
|
|
60
|
+
@additional_options.join("\s")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Returns the Redis database file name
|
|
65
|
+
def database
|
|
66
|
+
"#{ name }.rdb"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Performs the Redis backup by using the 'cp' unix utility
|
|
71
|
+
# to copy the persisted Redis dump file to the Backup archive.
|
|
72
|
+
# Additionally, when 'invoke_save' is set to true, it'll tell
|
|
73
|
+
# the Redis server to persist the current state to the dump file
|
|
74
|
+
# before copying the dump to get the most recent updates in to the backup
|
|
75
|
+
def perform!
|
|
76
|
+
log!
|
|
77
|
+
|
|
78
|
+
invoke_save! if invoke_save
|
|
79
|
+
copy!
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
##
|
|
83
|
+
# Tells Redis to persist the current state of the
|
|
84
|
+
# in-memory database to the persisted dump file
|
|
85
|
+
def invoke_save!
|
|
86
|
+
response = run("#{ utility('redis-cli') } #{ credential_options } #{ connectivity_options } #{ additional_options } SAVE")
|
|
87
|
+
unless response =~ /OK/
|
|
88
|
+
Logger.error "Could not invoke the Redis SAVE command. The #{ database } file might not be contain the most recent data."
|
|
89
|
+
Logger.error "Please check if the server is running, the credentials (if any) are correct, and the host/port/socket are correct."
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
##
|
|
94
|
+
# Performs the copy command to copy over the Redis dump file to the Backup archive
|
|
95
|
+
def copy!
|
|
96
|
+
unless File.exist?(File.join(path, database))
|
|
97
|
+
Logger.error "Redis database dump not found in '#{ File.join(path, database) }'"
|
|
98
|
+
exit
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
run("#{ utility(:cp) } '#{ File.join(path, database) }' '#{ File.join(dump_path, database) }'")
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# A little self-contained gem manager for Backup.
|
|
7
|
+
# Rather than specifying hard dependencies in the gemspec, forcing users
|
|
8
|
+
# to install gems they do not want/need, Backup will notify them when a gem
|
|
9
|
+
# has not been installed, or when the gem's version is incorrect, and provide the
|
|
10
|
+
# command to install the gem. These dependencies are dynamically loaded in the Gemfile
|
|
11
|
+
class Dependency
|
|
12
|
+
extend Backup::CLI
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# Returns a hash of dependencies that Backup requires
|
|
16
|
+
# in order to run every available feature
|
|
17
|
+
def self.all
|
|
18
|
+
{
|
|
19
|
+
'fog' => {
|
|
20
|
+
:require => 'fog',
|
|
21
|
+
:version => '~> 0.7.0',
|
|
22
|
+
:for => 'Amazon S3, Rackspace Cloud Files (S3, CloudFiles Storages)'
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
'dropbox' => {
|
|
26
|
+
:require => 'dropbox',
|
|
27
|
+
:version => '~> 1.2.3',
|
|
28
|
+
:for => 'Dropbox Web Service (Dropbox Storage)'
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
'net-sftp' => {
|
|
32
|
+
:require => 'net/sftp',
|
|
33
|
+
:version => '~> 2.0.5',
|
|
34
|
+
:for => 'SFTP Protocol (SFTP Storage)'
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
'net-scp' => {
|
|
38
|
+
:require => 'net/scp',
|
|
39
|
+
:version => '~> 1.0.4',
|
|
40
|
+
:for => 'SCP Protocol (SCP Storage)'
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
'net-ssh' => {
|
|
44
|
+
:require => 'net/ssh',
|
|
45
|
+
:version => '~> 2.1.3',
|
|
46
|
+
:for => 'SSH Protocol (SSH Storage)'
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
'mail' => {
|
|
50
|
+
:require => 'mail',
|
|
51
|
+
:version => '~> 2.2.15',
|
|
52
|
+
:for => 'Sending Emails (Mail Notifier)'
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
'twitter' => {
|
|
56
|
+
:require => 'twitter',
|
|
57
|
+
:version => '~> 1.1.2',
|
|
58
|
+
:for => 'Sending Twitter Updates (Twitter Notifier)'
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
'httparty' => {
|
|
62
|
+
:require => 'httparty',
|
|
63
|
+
:version => '~> 0.7.4',
|
|
64
|
+
:for => 'Sending Http Updates'
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
'json' => {
|
|
68
|
+
:require => 'json',
|
|
69
|
+
:version => '~> 1.5.1',
|
|
70
|
+
:for => 'Parsing JSON for HTTParty'
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
##
|
|
76
|
+
# Attempts to load the specified gem (by name and version).
|
|
77
|
+
# If the gem with the correct version cannot be found, it'll display a message
|
|
78
|
+
# to the user with instructions on how to install the required gem
|
|
79
|
+
def self.load(name)
|
|
80
|
+
begin
|
|
81
|
+
gem(name, all[name][:version])
|
|
82
|
+
require(all[name][:require])
|
|
83
|
+
rescue LoadError
|
|
84
|
+
Backup::Logger.error("Dependency missing. Please install #{name} version #{all[name][:version]} and try again.")
|
|
85
|
+
puts "\n\s\sgem install #{name} -v '#{all[name][:version]}'\n\n"
|
|
86
|
+
puts "Dependency required for:"
|
|
87
|
+
puts "\n\s\s#{all[name][:for]}"
|
|
88
|
+
puts "\nTrying to install the #{name} gem for you.. please wait."
|
|
89
|
+
puts "Once installed, retry the backup procedure.\n\n"
|
|
90
|
+
puts run("#{ utility(:gem) } install #{name} -v '#{all[name][:version]}'")
|
|
91
|
+
exit
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
module Encryptor
|
|
5
|
+
class Base
|
|
6
|
+
include Backup::CLI
|
|
7
|
+
include Backup::Configuration::Helpers
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# Logs a message to the console and log file to inform
|
|
11
|
+
# the client that Backup is encrypting the archive
|
|
12
|
+
def log!
|
|
13
|
+
Logger.message "#{ self.class } started encrypting the archive."
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
# Require the tempfile Ruby library when Backup::Encryptor::GPG is loaded
|
|
5
|
+
require 'tempfile'
|
|
6
|
+
|
|
7
|
+
module Backup
|
|
8
|
+
module Encryptor
|
|
9
|
+
class GPG < Base
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# The GPG Public key that'll be used to encrypt the backup
|
|
13
|
+
attr_accessor :key
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Contains the GPG encryption key id which'll be extracted from the public key file
|
|
17
|
+
attr_accessor :encryption_key_id
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
# Contains the temporary file with the public key
|
|
21
|
+
attr_accessor :tmp_file
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Creates a new instance of Backup::Encryptor::GPG and
|
|
25
|
+
# sets the key to the provided GPG key. To enhance the DSL
|
|
26
|
+
# the user may use tabs and spaces to indent the multi-line key string
|
|
27
|
+
# since we gsub() every preceding 'space' and 'tab' on each line
|
|
28
|
+
def initialize(&block)
|
|
29
|
+
load_defaults!
|
|
30
|
+
|
|
31
|
+
instance_eval(&block) if block_given?
|
|
32
|
+
|
|
33
|
+
@key = key.gsub(/^[[:blank:]]+/, '')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# Performs the encrypting of the backup file and will
|
|
38
|
+
# remove the unencrypted backup file, as well as the temp file
|
|
39
|
+
def perform!
|
|
40
|
+
log!
|
|
41
|
+
write_tmp_file!
|
|
42
|
+
extract_encryption_key_id!
|
|
43
|
+
|
|
44
|
+
run("#{ utility(:gpg) } #{ options } -o '#{ Backup::Model.file }.gpg' '#{ Backup::Model.file }'")
|
|
45
|
+
|
|
46
|
+
rm(Backup::Model.file)
|
|
47
|
+
tmp_file.unlink
|
|
48
|
+
|
|
49
|
+
Backup::Model.extension += '.gpg'
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# GPG options
|
|
56
|
+
# Sets the gpg mode to 'encrypt' and passes in the encryption_key_id
|
|
57
|
+
def options
|
|
58
|
+
"-e --trust-model always -r '#{ encryption_key_id }'"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
##
|
|
62
|
+
# Creates a new temp file and writes the provided public gpg key to it
|
|
63
|
+
def write_tmp_file!
|
|
64
|
+
@tmp_file = Tempfile.new('backup.pub')
|
|
65
|
+
@tmp_file.write(key)
|
|
66
|
+
@tmp_file.close
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Extracts the 'encryption key id' from the '@tmp_file'
|
|
71
|
+
# and stores it in '@encryption_key_id'
|
|
72
|
+
def extract_encryption_key_id!
|
|
73
|
+
@encryption_key_id = run("#{ utility(:gpg) } --import '#{tmp_file.path}' 2>&1").match(/<(.+)>/)[1]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Backup
|
|
4
|
+
module Encryptor
|
|
5
|
+
class OpenSSL < Base
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# The password that'll be used to encrypt the backup. This
|
|
9
|
+
# password will be required to decrypt the backup later on.
|
|
10
|
+
attr_accessor :password
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Determines whether the 'base64' should be used or not
|
|
14
|
+
attr_writer :base64
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Determines whether the 'salt' flag should be used
|
|
18
|
+
attr_writer :salt
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Creates a new instance of Backup::Encryptor::OpenSSL and
|
|
22
|
+
# sets the password attribute to what was provided
|
|
23
|
+
def initialize(&block)
|
|
24
|
+
load_defaults!
|
|
25
|
+
|
|
26
|
+
@base64 ||= false
|
|
27
|
+
@salt ||= false
|
|
28
|
+
|
|
29
|
+
instance_eval(&block) if block_given?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# Performs the encryption of the backup file
|
|
34
|
+
def perform!
|
|
35
|
+
log!
|
|
36
|
+
run("#{ utility(:openssl) } #{ options } -in '#{ Backup::Model.file }' -out '#{ Backup::Model.file }.enc' -k '#{ password }'")
|
|
37
|
+
rm(Backup::Model.file)
|
|
38
|
+
Backup::Model.extension += '.enc'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Backup::Encryptor::OpenSSL uses the 256bit AES encryption cipher.
|
|
45
|
+
# 256bit AES is what the US Government uses to encrypt information at the "Top Secret" level.
|
|
46
|
+
def options
|
|
47
|
+
(['aes-256-cbc'] + base64 + salt).join("\s")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
##
|
|
51
|
+
# Returns '-a' if @base64 is set to 'true'.
|
|
52
|
+
# This option will make the encrypted output base64 encoded,
|
|
53
|
+
# this makes the encrypted file readable using text editors
|
|
54
|
+
def base64
|
|
55
|
+
return ['-base64'] if @base64; []
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
# Returns '-salt' if @salt is set to 'true'.
|
|
60
|
+
# This options adds strength to the encryption
|
|
61
|
+
def salt
|
|
62
|
+
return ['-salt'] if @salt; []
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|