devise_hacker_tracker 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c3765dd410d14455610636c11ef582d94d791d3a
4
+ data.tar.gz: 6ff4ef457e13ba10ee0bcf0cde49c498aebfd2a6
5
+ SHA512:
6
+ metadata.gz: da982f88ac91828f8d8c487d810abd50d26db81d200fb42b305eaa03d74f094e34aa86e726f3d40e95fe155645fae83967683df85b3005b6e260b947fb902fac
7
+ data.tar.gz: d90cbd8a8c44fd19a4755955ae828f15d9304cb041046b5f77293d8c18f17dca467b6c1321355a5958480bbc7ac23c32a5311bd6cc600238f03f35a2c36a8861
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.4
5
+ cache:
6
+ - apt
7
+ - bundler
8
+ # With this, feature branches will only be built when a Pull Request is sent
9
+ branches:
10
+ only:
11
+ - master
12
+ - develop
13
+ - /^release\/.*$/
14
+ - /^hotfix\/.*$/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in devise_hacker_tracker.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Abletech
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # DeviseHackerTracker
2
+ Track failed attempts to sign in through devise.
3
+
4
+ This can allow for increased security measures, such as locking sign in after multiple failed attempts on different accounts from a single IP address.
5
+
6
+ ## Requirements
7
+
8
+ - Devise: follow the setup from their page [here](https://github.com/plataformatec/devise#getting-started)
9
+
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'devise_hacker_tracker', :git => 'https://github.com/AbleTech/devise_hacker_tracker.git', branch: 'develop'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ ## Usage
24
+
25
+ To setup the gem and generate the relevant config additions and migrations, run:
26
+ ```bash
27
+ $ rails generate devise_hacker_tracker sign_in_failures
28
+ ```
29
+ - To change the name of the database table storing the failed sign in attempts, replace `sign_in_failures` with your preferred name
30
+ - To use uuid as the index for the `sign_in_failures` table, add the flag `--enable-uuid`
31
+
32
+
33
+ The generator will create the following new files
34
+ - db/migrate/devise_create_sign_in_failures.rb
35
+ - config/locales/devise_hacker_tracker.en.yml
36
+
37
+ and also add some configuration options to config/initializers/devise.rb.
38
+
39
+ Create the new `sign_in_failures` database table by running:
40
+ ```bash
41
+ $ rake db:migrate
42
+ ```
43
+
44
+ You can then prevent a user from signing in, if they have made too many attempts at different accounts, by adding the following code to your Devise sessions controller (you may need to create this controller if you haven't already. Follow the [devise explanation here](https://github.com/plataformatec/devise#configuring-controllers)). You can change the flash message and redirection path as appropriate for you application.
45
+
46
+ ```ruby
47
+ class SessionsController < Devise::SessionsController
48
+
49
+ def create
50
+ if HackerTracker.hacker?(request.remote_ip)
51
+ set_flash_message :alert, :ip_blocked
52
+ redirect_to new_user_session_path
53
+ else
54
+ super
55
+ end
56
+ end
57
+
58
+ end
59
+ ```
60
+
61
+ ## Contributing
62
+
63
+ Bug reports and pull requests are welcome on GitHub at https://github.com/AbleTech/devise_hacker_tracker.
64
+
65
+ ## License
66
+
67
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
68
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "devise_hacker_tracker"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,4 @@
1
+ en:
2
+ devise:
3
+ sessions:
4
+ ip_blocked: "Sorry, your IP address has been temporarily blocked from signing in."
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'devise_hacker_tracker/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "devise_hacker_tracker"
8
+ spec.version = DeviseHackerTracker::VERSION
9
+ spec.authors = ["Dawn Richardson"]
10
+ spec.email = ["dawn.richardson@abletech.co.nz"]
11
+
12
+ spec.summary = %q{Track failed attempts to sign in through devise}
13
+ spec.description = %q{Track failed attempts to sign in through devise to allow for increased security measures, such as locking sign in after failed attempts on several accounts from a single IP address.}
14
+ spec.homepage = "https://github.com/AbleTech/devise_hacker_tracker"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.10"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec", "~> 3.3"
26
+ spec.add_development_dependency "sqlite3", "~> 1.3"
27
+ spec.add_development_dependency "factory_girl", "~> 4.5"
28
+ spec.add_development_dependency 'database_cleaner', "~> 1.4"
29
+ spec.add_development_dependency 'byebug', "~> 5"
30
+ spec.add_runtime_dependency 'devise', '>= 3.4.1'
31
+ spec.add_runtime_dependency 'rails', '~> 4.2.0'
32
+ end
@@ -0,0 +1,15 @@
1
+ require 'warden'
2
+
3
+ Warden::Manager.before_failure do |env, options|
4
+ if options.try(:[], :action) == "unauthenticated" && options.has_key?(:recall)
5
+ request = ActionDispatch::Request.new(env)
6
+
7
+ attributes = { ip_address: request.remote_ip, user_agent: request.user_agent }
8
+ authentication_values = request.params.try(:[], options.try(:[], :scope))
9
+
10
+ Devise.authentication_keys.each do |key|
11
+ attributes = attributes.merge(key => authentication_values.try(:[], key))
12
+ end
13
+ SignInFailure.create!(attributes)
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ require 'devise_hacker_tracker/models/sign_in_failure'
2
+
3
+ module HackerTracker
4
+
5
+ def self.hacker?(ip_address)
6
+ SignInFailure.clear_outdated!
7
+
8
+ failures = SignInFailure.recent.where(ip_address: ip_address)
9
+ too_many_attempts?(failures) && too_many_accounts_tried?(failures)
10
+ end
11
+
12
+ private
13
+
14
+ def self.too_many_attempts?(failures)
15
+ failures.size >= Devise.maximum_attempts_per_ip
16
+ end
17
+
18
+ def self.too_many_accounts_tried?(failures)
19
+ failures.distinct.count(*Devise.authentication_keys) >= Devise.maximum_accounts_attempted
20
+ end
21
+
22
+ end
@@ -0,0 +1,14 @@
1
+ require 'active_record'
2
+
3
+ class SignInFailure < ActiveRecord::Base
4
+ def self.table_name
5
+ Devise.sign_in_failures_table_name
6
+ end
7
+
8
+ scope :recent, -> { where("created_at > '#{Devise.ip_block_time.ago.utc}'") }
9
+ scope :outdated, -> { where("created_at <= '#{Devise.ip_block_time.ago.utc}'") }
10
+
11
+ def self.clear_outdated!
12
+ outdated.destroy_all
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module DeviseHackerTracker
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,20 @@
1
+ require 'devise'
2
+
3
+ module Devise
4
+ mattr_accessor :ip_block_time
5
+ @@ip_block_time = 5.minutes
6
+
7
+ mattr_accessor :maximum_attempts_per_ip
8
+ @@maximum_attempts_per_ip = 5
9
+
10
+ mattr_accessor :maximum_accounts_attempted
11
+ @@maximum_accounts_attempted = 3
12
+
13
+ mattr_accessor :sign_in_failures_table_name
14
+ @@sign_in_failures_table_name = 'sign_in_failures'
15
+
16
+ end
17
+
18
+ require "devise_hacker_tracker/version"
19
+ require 'devise_hacker_tracker/hooks/hacker_tracker'
20
+ require 'devise_hacker_tracker/models/hacker_tracker'
@@ -0,0 +1,47 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ class DeviseHackerTrackerGenerator < ActiveRecord::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+
6
+ desc "Generates a model and migration with the given NAME to store failed sign in attempts and adds to the devise configuration."
7
+
8
+ class_option :uuid, desc: "Enable uuid as the index for NAME table", type: :boolean, default: false
9
+
10
+ def setup_hacker_tracker_configuration
11
+ devise_initializer_path = "config/initializers/devise.rb"
12
+ if File.exist?(devise_initializer_path)
13
+ old_content = File.read(devise_initializer_path)
14
+
15
+ if old_content.match(Regexp.new(/^\s# ==> Configuration for :hacker_tracker\n/))
16
+ false
17
+ else
18
+ inject_into_file(devise_initializer_path, :before => " # ==> Configuration for :confirmable\n") do
19
+ " # ==> Configuration for :hacker_tracker
20
+ # Amount of time an IP address stays blocked for
21
+ # config.ip_block_time = 5.minutes
22
+ #
23
+ # Total number of failed sign in attempts allowed per IP address before being blocked
24
+ # config.maximum_attempts_per_ip = #{Devise.maximum_attempts_per_ip}
25
+ #
26
+ # Total number accounts a single IP address is allowed to attempt before being blocked
27
+ # config.maximum_accounts_attempted = #{Devise.maximum_accounts_attempted}
28
+ #
29
+ # The name of the table storing the failed sign in attempts
30
+ config.sign_in_failures_table_name = '#{table_name}'
31
+
32
+ "
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def setup_hacker_tracker_locales
39
+ copy_file "../../../config/locales/en.yml", "config/locales/devise_hacker_tracker.en.yml"
40
+ end
41
+
42
+ def create_hacker_tracker_migration
43
+ @uuid_enabled = options.uuid
44
+ migration_template "migration.rb", "db/migrate/devise_create_#{table_name}.rb"
45
+ end
46
+
47
+ end
@@ -0,0 +1,11 @@
1
+ class DeviseCreate<%= table_name.camelcase %> < ActiveRecord::Migration
2
+ def change
3
+ create_table(:<%= table_name %><%= ", id: :uuid" if @uuid_enabled %>) do |t|
4
+ <% Devise.authentication_keys.each { |key| %><%= "\n t.string :#{key}" %><% } %>
5
+ t.string :ip_address
6
+ t.string :user_agent
7
+
8
+ t.timestamps null: false
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,190 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: devise_hacker_tracker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dawn Richardson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-07-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: factory_girl
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '4.5'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '4.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: database_cleaner
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.4'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: byebug
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '5'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '5'
111
+ - !ruby/object:Gem::Dependency
112
+ name: devise
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 3.4.1
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 3.4.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 4.2.0
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 4.2.0
139
+ description: Track failed attempts to sign in through devise to allow for increased
140
+ security measures, such as locking sign in after failed attempts on several accounts
141
+ from a single IP address.
142
+ email:
143
+ - dawn.richardson@abletech.co.nz
144
+ executables: []
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - ".gitignore"
149
+ - ".rspec"
150
+ - ".travis.yml"
151
+ - Gemfile
152
+ - LICENSE.txt
153
+ - README.md
154
+ - Rakefile
155
+ - bin/console
156
+ - bin/setup
157
+ - config/locales/en.yml
158
+ - devise_hacker_tracker.gemspec
159
+ - lib/devise_hacker_tracker.rb
160
+ - lib/devise_hacker_tracker/hooks/hacker_tracker.rb
161
+ - lib/devise_hacker_tracker/models/hacker_tracker.rb
162
+ - lib/devise_hacker_tracker/models/sign_in_failure.rb
163
+ - lib/devise_hacker_tracker/version.rb
164
+ - lib/generators/devise_hacker_tracker_generator.rb
165
+ - lib/generators/templates/migration.rb
166
+ homepage: https://github.com/AbleTech/devise_hacker_tracker
167
+ licenses:
168
+ - MIT
169
+ metadata: {}
170
+ post_install_message:
171
+ rdoc_options: []
172
+ require_paths:
173
+ - lib
174
+ required_ruby_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ required_rubygems_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ requirements: []
185
+ rubyforge_project:
186
+ rubygems_version: 2.4.5
187
+ signing_key:
188
+ specification_version: 4
189
+ summary: Track failed attempts to sign in through devise
190
+ test_files: []