rahasia 0.0.2

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.
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rahasia
4
+ module Adapter
5
+ # Adapter lockbox
6
+ class Lockbox
7
+ def self.encrypt(key:, value:)
8
+ lockbox = ::Lockbox.new(key: key)
9
+ string = lockbox.encrypt(value)
10
+ Base64.strict_encode64(string)
11
+ end
12
+
13
+ def self.decrypt(key:, value:)
14
+ lockbox = ::Lockbox.new(key: key)
15
+ chipertext = Base64.decode64(value)
16
+ lockbox.decrypt(chipertext)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # You may need to set the following environment variable:
4
+
5
+ # $ export VAULT_ADDR='http://127.0.0.1:8200'
6
+
7
+ # The unseal key and root token are displayed below in case you want to
8
+ # seal/unseal the Vault or re-authenticate.
9
+
10
+ # Unseal Key: Rq8uhQeS7BgyMd/T3AeDA9wWGk9XHIlejTgZCSu8ug8=
11
+ # Root Token: s.TaWtwLTczBiwd0w36fMkrO8i
12
+
13
+ module Rahasia
14
+ module Adapter
15
+ # Adapter vault
16
+ class Vault
17
+ def self.encrypt(key:, value:)
18
+ unless ::Vault::Transit.sys.mounts.key? :transit
19
+ ::Vault::Transit.sys.mount('transit', :transit)
20
+ end
21
+ ::Vault::Transit.logical.write("transit/keys/#{key}")
22
+ ::Vault::Transit.enabled = true
23
+ ::Vault::Transit.encrypt(key, value)
24
+ end
25
+
26
+ def self.decrypt(key:, value:)
27
+ unless ::Vault::Transit.sys.mounts.key? :transit
28
+ ::Vault::Transit.sys.mount('transit', :transit)
29
+ end
30
+ ::Vault::Transit.logical.write("transit/keys/#{key}")
31
+ ::Vault::Transit.enabled = true
32
+ ::Vault::Transit.decrypt(key, value)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/base'
4
+
5
+ #
6
+ # Generate file init/rahasia.rb
7
+ #
8
+ module Rahasia
9
+ module Generators
10
+ # Extend Rails Base Generator
11
+ class InstallGenerator < Rails::Generators::Base
12
+ source_root File.join(__dir__, '../templates')
13
+
14
+ def copy_initializer
15
+ template 'rahasia.rb', 'config/initializers/rahasia.rb'
16
+ end
17
+
18
+ def show_readme
19
+ readme 'README' if behavior == :invoke
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/rails/model/model_generator'
5
+ require 'rails/generators/active_record/migration/migration_generator'
6
+
7
+ #
8
+ # Generate Encrypt Column using Rahasia generator
9
+ #
10
+ module Rahasia
11
+ module Generators
12
+ # Extend Rails Model Generator
13
+ class MigrationGenerator < Rails::Generators::ModelGenerator
14
+ include ActiveRecord::Generators::Migration
15
+
16
+ source_root File.join(__dir__, '../templates')
17
+
18
+ def copy_migration
19
+ suffix = attributes_names.join('_').first(13).to_s.presence || 'encrypt'
20
+ migration_template \
21
+ 'migration.rb.tt',
22
+ "db/migrate/rahasia_#{table_name}#{suffix}.rb",
23
+ migration_version: migration_version
24
+ end
25
+
26
+ def migration_version
27
+ return if ActiveRecord::VERSION::MAJOR == 4
28
+
29
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,18 @@
1
+ ===============================================================================
2
+
3
+ Depending on your application's configuration some manual setup may be required:
4
+
5
+ 1. Ensure you have defined initializer/rahasia.rb. Here
6
+ is an example of adapter appropriate for a development environment
7
+ in config/environments/development.rb:
8
+
9
+ config.master_key = 'masterkey' # SecureRandom.hex(32)
10
+ config.adapter = 'lockbox' # available ['vault','lockbox']
11
+ config.vault = {host: 'http://localhost', token: 'token'}
12
+ config.vault_app = 'qontak'
13
+
14
+ * Required for all applications. *
15
+
16
+
17
+
18
+ ===============================================================================
@@ -0,0 +1,6 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version %>
2
+ def change<% attributes_names.each do |t| %>
3
+ add_column :<%=table_name%>, :<%= t %>, :string
4
+ add_column :<%=table_name%>, :<%= t %>_encrypted, :text<% end %>
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rahasia.setup do |config|
4
+ config.master_key = 'please-change-me-at-config-initializers-rahasia' # SecureRandom.hex(32)
5
+ config.adapter = 'lockbox' # available ['vault','lockbox']
6
+ config.vault_app = 'qontak'
7
+ config.vault = {address: 'http://localhost', ssl_verify: false, token: 'token'}
8
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ require 'lockbox'
6
+ require 'vault'
7
+ require 'vault/transit'
8
+ require 'adapter/lockbox'
9
+ require 'adapter/vault'
10
+ require 'rahasia/version'
11
+ require 'rahasia/model'
12
+
13
+ if defined?(ActiveSupport)
14
+ ActiveSupport.on_load(:active_record) do
15
+ extend Rahasia::Model
16
+ end
17
+ end
18
+
19
+ require 'generators/rahasia/migration_generator' if defined?(ActiveRecord)
20
+
21
+ # Wrapper for encrypt and keep our credentials secret
22
+ module Rahasia
23
+ def self.setup
24
+ yield self
25
+ end
26
+
27
+ # Masterkey
28
+ mattr_accessor :master_key
29
+ def self.master_key=(master_key)
30
+ @master_key = master_key
31
+ end
32
+
33
+ def self.master_key
34
+ @master_key ||
35
+ '0000000000000000000000000000000000000000000000000000000000000000'
36
+ end
37
+
38
+ # Rahasia key
39
+ mattr_accessor :rahasia_key
40
+ def self.rahasia_key=(key)
41
+ @rahasia_key = key
42
+ end
43
+
44
+ def self.rahasia_key
45
+ @rahasia_key =
46
+ if Rahasia.adapter == 'vault'
47
+ Rahasia.vault_app
48
+ else
49
+ Rahasia.master_key
50
+ end
51
+ end
52
+
53
+ # Adapter
54
+ mattr_accessor :adapter
55
+ def self.adapter=(adapter)
56
+ @adapter = adapter
57
+ @encryptor =
58
+ if adapter == 'vault'
59
+ Adapter::Vault
60
+ else
61
+ Adapter::Lockbox
62
+ end
63
+ adapter
64
+ end
65
+
66
+ def self.adapter
67
+ @adapter || null_adapter
68
+ end
69
+
70
+ # Encryptor
71
+ mattr_accessor :encryptor
72
+ def self.encryptor=(encryptor)
73
+ @encryptor = encryptor
74
+ end
75
+
76
+ def self.encryptor
77
+ @encryptor || null_encryptor
78
+ end
79
+
80
+ # Vault Setting
81
+ mattr_accessor :vault
82
+ def self.vault=(vault)
83
+ @vault = vault
84
+ end
85
+
86
+ def self.vault
87
+ @vault
88
+ end
89
+
90
+ # VaultApp Name KV Setting
91
+ mattr_accessor :vault_app
92
+ def self.vault_app=(vault_app)
93
+ @vault_app = vault_app
94
+ end
95
+
96
+ def self.vault_app
97
+ @vault_app
98
+ end
99
+
100
+ def self.null_adapter
101
+ 'lockbox'
102
+ end
103
+
104
+ def self.null_encryptor
105
+ Adapter::Lockbox
106
+ end
107
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rahasia
4
+ # Model for ActiveRecord extension
5
+ # https://github.com/ankane/lockbox/blob/80adc597b27172b5e420471db5888b8f962ad829/lib/lockbox/model.rb
6
+ module Model
7
+ def enrcypt_column(*attributes, **options)
8
+ unless [nil, :string].include?(options[:type])
9
+ raise ArgumentError, "UnknownType #{options[:type]}."
10
+ end
11
+
12
+ activerecord = defined?(ActiveRecord::Base) && self < ActiveRecord::Base
13
+ if options[:type] && !activerecord
14
+ raise ArgumentError, 'Type not supported yet with Mongoid'
15
+ end
16
+
17
+ define_attributes(attributes)
18
+ end
19
+
20
+ def default_string
21
+ "--encrypted:#{SecureRandom.hex(16)}---"
22
+ end
23
+
24
+ def define_attributes(attributes)
25
+ attributes.each do |name|
26
+ encrypted_attribute = "#{name}_encrypted"
27
+ decrypt_method_name = "decrypt_#{encrypted_attribute}"
28
+
29
+ define_decrypt_method_name(decrypt_method_name)
30
+ define_decrypt(name, encrypted_attribute, decrypt_method_name)
31
+ define_setter(name)
32
+ end
33
+ end
34
+
35
+ # ------------------------------------
36
+ # available column refresh_token, name
37
+ # ------------------------------------
38
+ # Credential < ActiveRecord
39
+ # enrcypt_column :refresh_token
40
+ # end
41
+ #
42
+ # available method
43
+ # # decrypt_refresh_token_encrypted
44
+ # # refresh_token_chipertext?
45
+ # # refresh_token
46
+ # # refresh_token=(string)
47
+ # # refresh_token_encrypted
48
+ #
49
+ # refresh_token_encrypted
50
+ # token_encrypted
51
+ #
52
+ def define_decrypt_method_name(decrypt_method_name)
53
+ define_singleton_method decrypt_method_name do |encrypted, **_opts|
54
+ Rahasia.encryptor.decrypt(
55
+ key: Rahasia.rahasia_key,
56
+ value: encrypted
57
+ )
58
+ end
59
+ end
60
+
61
+ # refresh_token
62
+ # token
63
+ def define_decrypt(name, encrypted_attribute, decrypt_method_name)
64
+ define_method(name) do
65
+ message = super()
66
+ if self.class.not_encrypted?(message)
67
+ ciphertext = send(encrypted_attribute)
68
+ message =
69
+ self.class.send(decrypt_method_name, ciphertext, context: self)
70
+ end
71
+ message
72
+ end
73
+ end
74
+
75
+ # refresh_token=(string)
76
+ # # refresh_token_encrypted
77
+ def define_setter(name)
78
+ define_method("#{name}=") do |val|
79
+ begin
80
+ val = val.presence || ''
81
+ str = Rahasia.encryptor.encrypt(key: Rahasia.rahasia_key, value: val)
82
+ send("#{name}_encrypted=", str)
83
+ super(self.class.default_string)
84
+ rescue ArgumentError => e
85
+ puts e
86
+ end
87
+ end
88
+ end
89
+
90
+ def not_encrypted?(message)
91
+ return false if message.nil?
92
+
93
+ message.match(/--encrypted:/) ? true : false
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rahasia
4
+ VERSION = '0.0.2'
5
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rahasia/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'rahasia'
9
+ spec.version = Rahasia::VERSION
10
+ spec.authors = ['burhanudin hakim']
11
+ spec.email = ['udnpico@gmail.com']
12
+
13
+ spec.summary = 'Wrapper encryption gem'
14
+ spec.description = 'Wrapper encryption gem'
15
+ spec.homepage = 'https://github.com/qontak-dev/rahasia'
16
+ spec.license = 'MIT'
17
+
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
20
+ else
21
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
22
+ 'public gem pushes.'
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(test|spec|features)/})
27
+ end
28
+ spec.bindir = 'exe'
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ['lib']
31
+
32
+ spec.required_ruby_version = '>= 2.3.8'
33
+ spec.add_dependency 'activesupport'
34
+ spec.add_dependency 'lockbox', '~> 0.3.1'
35
+ spec.add_dependency 'vault', '~> 0.13.0'
36
+ spec.add_dependency 'vault-transit'
37
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rahasia
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - burhanudin hakim
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-02-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: lockbox
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: vault
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.13.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.13.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: vault-transit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Wrapper encryption gem
70
+ email:
71
+ - udnpico@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".hound.yml"
78
+ - ".rspec"
79
+ - ".rubocop.yml"
80
+ - ".travis.yml"
81
+ - CODE_OF_CONDUCT.md
82
+ - Gemfile
83
+ - Gemfile.lock
84
+ - LICENSE.txt
85
+ - README.md
86
+ - Rakefile
87
+ - bin/console
88
+ - bin/setup
89
+ - config.ru
90
+ - gemfiles/.bundle/config
91
+ - gemfiles/rails_4.gemfile
92
+ - gemfiles/rails_4.gemfile.lock
93
+ - gemfiles/rails_5.gemfile
94
+ - gemfiles/rails_5.gemfile.lock
95
+ - gemfiles/rails_6.gemfile
96
+ - gemfiles/rails_6.gemfile.lock
97
+ - lib/adapter/lockbox.rb
98
+ - lib/adapter/vault.rb
99
+ - lib/generators/rahasia/install_generator.rb
100
+ - lib/generators/rahasia/migration_generator.rb
101
+ - lib/generators/templates/README
102
+ - lib/generators/templates/migration.rb.tt
103
+ - lib/generators/templates/rahasia.rb.tt
104
+ - lib/rahasia.rb
105
+ - lib/rahasia/model.rb
106
+ - lib/rahasia/version.rb
107
+ - rahasia.gemspec
108
+ homepage: https://github.com/qontak-dev/rahasia
109
+ licenses:
110
+ - MIT
111
+ metadata:
112
+ allowed_push_host: https://rubygems.org
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: 2.3.8
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.7.7
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Wrapper encryption gem
133
+ test_files: []