Class: ActiveSupport::EncryptedFile

Inherits:
Object
  • Object
show all
Defined in:
lib/active_support/encrypted_file.rb

Direct Known Subclasses

EncryptedConfiguration

Defined Under Namespace

Classes: InvalidKeyLengthError, MissingContentError, MissingKeyError

Constant Summary collapse

CIPHER =
"aes-128-gcm"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content_path:, key_path:, env_key:, raise_if_missing_key:) ⇒ EncryptedFile

Returns a new instance of EncryptedFile.



42
43
44
45
46
# File 'lib/active_support/encrypted_file.rb', line 42

def initialize(content_path:, key_path:, env_key:, raise_if_missing_key:)
  @content_path = Pathname.new(content_path).yield_self { |path| path.symlink? ? path.realpath : path }
  @key_path = Pathname.new(key_path)
  @env_key, @raise_if_missing_key = env_key, raise_if_missing_key
end

Instance Attribute Details

#content_pathObject (readonly)

Returns the value of attribute content_path.



40
41
42
# File 'lib/active_support/encrypted_file.rb', line 40

def content_path
  @content_path
end

#env_keyObject (readonly)

Returns the value of attribute env_key.



40
41
42
# File 'lib/active_support/encrypted_file.rb', line 40

def env_key
  @env_key
end

#key_pathObject (readonly)

Returns the value of attribute key_path.



40
41
42
# File 'lib/active_support/encrypted_file.rb', line 40

def key_path
  @key_path
end

#raise_if_missing_keyObject (readonly)

Returns the value of attribute raise_if_missing_key.



40
41
42
# File 'lib/active_support/encrypted_file.rb', line 40

def raise_if_missing_key
  @raise_if_missing_key
end

Class Method Details

.expected_key_lengthObject

:nodoc:



35
36
37
# File 'lib/active_support/encrypted_file.rb', line 35

def self.expected_key_length # :nodoc:
  @expected_key_length ||= generate_key.length
end

.generate_keyObject



31
32
33
# File 'lib/active_support/encrypted_file.rb', line 31

def self.generate_key
  SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER))
end

Instance Method Details

#change(&block) ⇒ Object



83
84
85
# File 'lib/active_support/encrypted_file.rb', line 83

def change(&block)
  writing read, &block
end

#keyObject

Returns the encryption key, first trying the environment variable specified by env_key, then trying the key file specified by key_path. If raise_if_missing_key is true, raises MissingKeyError if the environment variable is not set and the key file does not exist.



52
53
54
# File 'lib/active_support/encrypted_file.rb', line 52

def key
  read_env_key || read_key_file || handle_missing_key
end

#key?Boolean

Returns truthy if #key is truthy. Returns falsy otherwise. Unlike #key, does not raise MissingKeyError when raise_if_missing_key is true.

Returns:

  • (Boolean)


58
59
60
# File 'lib/active_support/encrypted_file.rb', line 58

def key?
  read_env_key || read_key_file
end

#readObject

Reads the file and returns the decrypted content.

Raises:

  • MissingKeyError if the key is missing and raise_if_missing_key is true.

  • MissingContentError if the encrypted file does not exist or otherwise if the key is missing.

  • ActiveSupport::MessageEncryptor::InvalidMessage if the content cannot be decrypted or verified.



70
71
72
73
74
75
76
# File 'lib/active_support/encrypted_file.rb', line 70

def read
  if !key.nil? && content_path.exist?
    decrypt content_path.binread
  else
    raise MissingContentError, content_path
  end
end

#write(contents) ⇒ Object



78
79
80
81
# File 'lib/active_support/encrypted_file.rb', line 78

def write(contents)
  IO.binwrite "#{content_path}.tmp", encrypt(contents)
  FileUtils.mv "#{content_path}.tmp", content_path
end