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)


101
102
103
# File 'lib/vault/encrypted_model.rb', line 101

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.



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

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



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
94
95
96
# File 'lib/vault/encrypted_model.rb', line 50

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



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

def vault_lazy_decrypt
  @vault_lazy_decrypt ||= false
end

#vault_lazy_decrypt!Object



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

def vault_lazy_decrypt!
  @vault_lazy_decrypt = true
end

#vault_single_decryptObject



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

def vault_single_decrypt
  @vault_single_decrypt ||= false
end

#vault_single_decrypt!Object



156
157
158
# File 'lib/vault/encrypted_model.rb', line 156

def vault_single_decrypt!
  @vault_single_decrypt = true
end