Class: SymmetricEncryption::CLI

Inherits:
Object
  • Object
show all
Defined in:
lib/symmetric_encryption/cli.rb

Constant Summary collapse

KEYSTORES =
%i[aws heroku environment file gcp].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(argv) ⇒ CLI

Returns a new instance of CLI.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/symmetric_encryption/cli.rb', line 17

def initialize(argv)
  @version          = current_version
  @environment      = ENV["SYMMETRIC_ENCRYPTION_ENV"] || ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
  @config_file_path = File.expand_path(ENV["SYMMETRIC_ENCRYPTION_CONFIG"] || "config/symmetric-encryption.yml")
  @app_name         = "symmetric-encryption"
  @key_path         = "#{ENV['HOME']}/.symmetric-encryption"
  @cipher_name      = "aes-256-cbc"
  @rolling_deploy   = false
  @prompt           = false
  @show_version     = false
  @keystore         = :file

  if argv.empty?
    puts parser
    exit(-10)
  end
  parser.parse!(argv)
end

Instance Attribute Details

#activate_keyObject (readonly)

Returns the value of attribute activate_key.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def activate_key
  @activate_key
end

#app_nameObject (readonly)

Returns the value of attribute app_name.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def app_name
  @app_name
end

#cipher_nameObject (readonly)

Returns the value of attribute cipher_name.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def cipher_name
  @cipher_name
end

#cleanup_keysObject (readonly)

Returns the value of attribute cleanup_keys.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def cleanup_keys
  @cleanup_keys
end

#compressObject (readonly)

Returns the value of attribute compress.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def compress
  @compress
end

#config_file_pathObject (readonly)

Returns the value of attribute config_file_path.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def config_file_path
  @config_file_path
end

#decryptObject (readonly)

Returns the value of attribute decrypt.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def decrypt
  @decrypt
end

#encryptObject (readonly)

Returns the value of attribute encrypt.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def encrypt
  @encrypt
end

#environmentObject (readonly)

Returns the value of attribute environment.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def environment
  @environment
end

#environmentsObject

Returns the value of attribute environments.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def environments
  @environments
end

#generateObject (readonly)

Returns the value of attribute generate.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def generate
  @generate
end

#key_pathObject (readonly)

Returns the value of attribute key_path.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def key_path
  @key_path
end

#keystoreObject (readonly)

Returns the value of attribute keystore.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def keystore
  @keystore
end

#migrateObject (readonly)

Returns the value of attribute migrate.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def migrate
  @migrate
end

#new_keysObject (readonly)

Returns the value of attribute new_keys.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def new_keys
  @new_keys
end

#output_file_nameObject (readonly)

Returns the value of attribute output_file_name.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def output_file_name
  @output_file_name
end

#promptObject (readonly)

Returns the value of attribute prompt.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def prompt
  @prompt
end

#random_passwordObject (readonly)

Returns the value of attribute random_password.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def random_password
  @random_password
end

#re_encryptObject (readonly)

Returns the value of attribute re_encrypt.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def re_encrypt
  @re_encrypt
end

#regionsObject (readonly)

Returns the value of attribute regions.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def regions
  @regions
end

#rolling_deployObject (readonly)

Returns the value of attribute rolling_deploy.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def rolling_deploy
  @rolling_deploy
end

#rotate_kekObject (readonly)

Returns the value of attribute rotate_kek.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def rotate_kek
  @rotate_kek
end

#rotate_keysObject (readonly)

Returns the value of attribute rotate_keys.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def rotate_keys
  @rotate_keys
end

#show_versionObject (readonly)

Returns the value of attribute show_version.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def show_version
  @show_version
end

#versionObject (readonly)

Returns the value of attribute version.



5
6
7
# File 'lib/symmetric_encryption/cli.rb', line 5

def version
  @version
end

Class Method Details

.run!(argv) ⇒ Object



13
14
15
# File 'lib/symmetric_encryption/cli.rb', line 13

def self.run!(argv)
  new(argv).run!
end

Instance Method Details

#parserObject



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/symmetric_encryption/cli.rb', line 72

def parser
  @parser ||= OptionParser.new do |opts|
    opts.banner = <<~BANNER
      Symmetric Encryption v#{VERSION}

        For more information, see: https://encryption.rocketjob.io/

        Note:
          It is recommended to backup the current configuration file, or place it in version control before running
          the configuration manipulation commands below.

      symmetric-encryption [options]
    BANNER

    opts.on "-e", "--encrypt [FILE_NAME]", "Encrypt a file, or read from stdin if no file name is supplied." do |file_name|
      @encrypt = file_name || STDIN
    end

    opts.on "-d", "--decrypt [FILE_NAME]", "Decrypt a file, or read from stdin if no file name is supplied." do |file_name|
      @decrypt = file_name || STDIN
    end

    opts.on "-o", "--output FILE_NAME",
            "Write encrypted or decrypted file to this file, otherwise output goes to stdout." do |file_name|
      @output_file_name = file_name
    end

    opts.on "-P", "--prompt", "When encrypting or decrypting, prompt for a string encrypt or decrypt." do
      @prompt = true
    end

    opts.on "-z", "--compress", "Compress encrypted output file. [Default for encrypting files]" do
      @compress = true
    end

    opts.on "-Z", "--no-compress", "Does not compress the output file. [Default for encrypting strings]" do
      @compress = false
    end

    opts.on "-E", "--env ENVIRONMENT",
            "Environment to use in the config file. Default: SYMMETRIC_ENCRYPTION_ENV || RACK_ENV || RAILS_ENV || 'development'" do |environment|
      @environment = environment
    end

    opts.on "-c", "--config CONFIG_FILE_PATH",
            "File name & path to the Symmetric Encryption configuration file. Default: config/symmetric-encryption.yml or Env var: `SYMMETRIC_ENCRYPTION_CONFIG`" do |path|
      @config_file_path = path
    end

    opts.on "-m", "--migrate", "Migrate configuration file to new format." do
      @migrate = true
    end

    opts.on "-r", "--re-encrypt [PATTERN]",
            'ReEncrypt all files matching the pattern. Default:  "**/*.{yml,rb}"' do |pattern|
      @re_encrypt = pattern || "**/*.{yml,rb}"
    end

    opts.on "-n", "--new-password [SIZE]",
            "Generate a new random password using only characters that are URL-safe base64. Default size is 22." do |size|
      @random_password = (size || 22).to_i
    end

    opts.on "-g", "--generate", "Generate a new configuration file and encryption keys for every environment." do |config|
      @generate = config
    end

    opts.on "-s", "--keystore heroku|environment|file|aws|gcp",
            "Which keystore to use during generation or re-encryption." do |keystore|
      @keystore = (keystore || "file").downcase.to_sym
    end

    opts.on "-B", "--regions [us-east-1,us-east-2,us-west-1,us-west-2]",
            "AWS KMS Regions to encrypt data key with." do |regions|
      @regions = regions.to_s.split(",").collect(&:strip) if regions
    end

    opts.on "-K", "--key-path KEY_PATH",
            "Output path in which to write generated key files. Default: ~/.symmetric-encryption" do |path|
      @key_path = path
    end

    opts.on "-a", "--app-name NAME",
            "Application name to use when generating a new configuration. Default: symmetric-encryption" do |name|
      @app_name = name
    end

    opts.on "-S", "--environments ENVIRONMENTS",
            "Comma separated list of environments for which to generate the config file. Default: development,test,release,production" do |environments|
      @environments = environments.split(",").collect(&:strip).collect(&:to_sym)
    end

    opts.on "-C", "--cipher-name NAME",
            "Name of the cipher to use when generating a new config file, or when rotating keys. Default: aes-256-cbc" do |name|
      @cipher_name = name
    end

    opts.on "-R", "--rotate-keys",
            "Generates a new encryption key version, encryption key files, and updates the configuration file." do
      @rotate_keys = true
    end

    opts.on "-U", "--rotate-kek",
            "Replace the existing key encrypting keys only, the data encryption key is not changed, and updates the configuration file." do
      @rotate_kek = true
    end

    opts.on "-D", "--rolling-deploy",
            "During key rotation, support a rolling deploy by placing the new key second in the list so that it is not activated yet." do
      @rolling_deploy = true
    end

    opts.on "-A", "--activate-key", "Activates the key by moving the key with the highest version to the top." do
      @activate_key = true
    end

    opts.on "-X", "--cleanup-keys",
            "Removes all encryption keys, except the one with the highest version from the configuration file." do
      @cleanup_keys = true
    end

    opts.on "-V", "--key-version NUMBER",
            "Encryption key version to use when encrypting or re-encrypting. Default: (Current global version)." do |number|
      @version = number.to_i
    end

    opts.on "-L", "--ciphers", "List available OpenSSL ciphers." do
      puts "OpenSSL v#{OpenSSL::VERSION}. Available Ciphers:"
      puts OpenSSL::Cipher.ciphers.join("\n")
      exit
    end

    opts.on "-v", "--version", "Display Symmetric Encryption version." do
      @show_version = true
    end

    opts.on("-h", "--help", "Prints this help.") do
      puts opts
      exit
    end
  end
end

#run!Object

Raises:

  • (ArgumentError)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/symmetric_encryption/cli.rb', line 36

def run!
  raise(ArgumentError, "Cannot cleanup keys and rotate keys at the same time") if cleanup_keys && rotate_keys

  if show_version
    puts "Symmetric Encryption v#{VERSION}"
    puts "OpenSSL v#{OpenSSL::VERSION}"
    puts "Environment: #{environment}"
  elsif encrypt
    load_config
    prompt ? encrypt_string : encrypt_file(encrypt)
  elsif decrypt
    load_config
    prompt ? decrypt_string : decrypt_file(decrypt)
  elsif random_password
    load_config
    gen_random_password(random_password)
  elsif migrate
    run_migrate
  elsif re_encrypt
    load_config
    SymmetricEncryption::Utils::ReEncryptFiles.new(version: version).process_directory(re_encrypt)
  elsif activate_key
    run_activate_key
  elsif rotate_kek
    run_rotate_kek
  elsif rotate_keys
    run_rotate_keys
  elsif cleanup_keys
    run_cleanup_keys
  elsif generate
    generate_new_config
  else
    puts parser
  end
end