Module: Vault::EncryptedModel::ClassMethods

Defined in:
lib/vault/encrypted_model.rb

Instance Method Summary collapse

Instance Method Details

#__vault_attributesHash

The list of Vault attributes.

Returns:

  • (Hash)


98
99
100
# File 'lib/vault/encrypted_model.rb', line 98

def __vault_attributes
  @vault_attributes ||= {}
end

#_vault_validate_options!(options) ⇒ Object

Validate that Vault options are all a-okay! This method will raise exceptions if something does not make sense.



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
# File 'lib/vault/encrypted_model.rb', line 104

def _vault_validate_options!(options)
  if options[:serializer]
    if options[:encode] || options[:decode]
      raise Vault::Rails::ValidationFailedError, "Cannot use a " \
        "custom encoder/decoder if a `:serializer' is specified!"
    end

    if options[:transform_secret]
      raise Vault::Rails::ValidationFailedError, "Cannot use the " \
        "transform secrets engine with a specified `:serializer'!"
    end
  end

  if options[:encode] && !options[:decode]
    raise Vault::Rails::ValidationFailedError, "Cannot specify " \
      "`:encode' without specifying `:decode' as well!"
  end

  if options[:decode] && !options[:encode]
    raise Vault::Rails::ValidationFailedError, "Cannot specify " \
      "`:decode' without specifying `:encode' as well!"
  end

  if context = options[:context]
    if context.is_a?(Proc) && context.arity != 1
      raise Vault::Rails::ValidationFailedError, "Proc passed to " \
        "`:context' must take 1 argument!"
    end
  end
  if transform_opts = options[:transform_secret]
    if !transform_opts[:transformation]
      raise Vault::Rails::VaildationFailedError, "Transform Secrets " \
        "requires a transformation name!"
    end
  end
end

#vault_attribute(attribute, options = {}) ⇒ Object

Creates an attribute that is read and written using Vault.

Examples:


class Person < ActiveRecord::Base
  include Vault::EncryptedModel
  vault_attribute :ssn
end

person = Person.new
person.ssn = "123-45-6789"
person.save
person.encrypted_ssn #=> "vault:v0:6hdPkhvyL6..."

Parameters:

  • column (Symbol)

    the column that is encrypted

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :encrypted_column (Symbol)

    the name of the encrypted column (default: #{column}_encrypted)

  • :path (String)

    the path to the transit backend (default: transit)

  • :key (String)

    the name of the encryption key (default: #{app}_#{table}_#{column})

  • :context (String, Symbol, Proc)

    either a string context, or a symbol or proc used to generate a context for key generation

  • :default (Object)

    a default value for this attribute to be set to if the underlying value is nil

  • :serializer (Symbol, Class)

    the name of the serializer to use (or a class)

  • :encode (Proc)

    a proc to encode the value with

  • :decode (Proc)

    a proc to decode the value with

  • :transform_secret (Hash)

    a hash providing details about the transformation to use, this includes the name, and the role to use



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/vault/encrypted_model.rb', line 47

def vault_attribute(attribute, options = {})
  # Sanity check options!
  _vault_validate_options!(options)

  parsed_opts = if options[:transform_secret]
                  parse_transform_secret_attributes(attribute, options)
                else
                  parse_transit_attributes(attribute, options)
                end
  parsed_opts[:encrypted_column] = options[:encrypted_column] || "#{attribute}_encrypted"

  # Make a note of this attribute so we can use it in the future (maybe).
  __vault_attributes[attribute.to_sym] = parsed_opts

  self.attribute attribute.to_s, ActiveRecord::Type::Value.new,
    default: nil

  # Getter
  define_method("#{attribute}") do
    self.__vault_load_attributes!(attribute) unless @__vault_loaded
    super()
  end

  # Setter
  define_method("#{attribute}=") do |value|
    self.__vault_load_attributes!(attribute) unless @__vault_loaded

    # We always set it as changed without comparing with the current value
    # because we allow our held values to be mutated, so we need to assume
    # that if you call attr=, you want it sent back regardless.

    attribute_will_change!("#{attribute}")
    instance_variable_set("@#{attribute}", value)
    super(value)

    # Return the value to be consistent with other AR methods.
    value
  end

  # Checker
  define_method("#{attribute}?") do
    self.__vault_load_attributes!(attribute) unless @__vault_loaded
    instance_variable_get("@#{attribute}").present?
  end

  self
end

#vault_lazy_decryptObject



141
142
143
# File 'lib/vault/encrypted_model.rb', line 141

def vault_lazy_decrypt
  @vault_lazy_decrypt ||= false
end

#vault_lazy_decrypt!Object



145
146
147
# File 'lib/vault/encrypted_model.rb', line 145

def vault_lazy_decrypt!
  @vault_lazy_decrypt = true
end

#vault_single_decryptObject



149
150
151
# File 'lib/vault/encrypted_model.rb', line 149

def vault_single_decrypt
  @vault_single_decrypt ||= false
end

#vault_single_decrypt!Object



153
154
155
# File 'lib/vault/encrypted_model.rb', line 153

def vault_single_decrypt!
  @vault_single_decrypt = true
end