watch_list 0.1.1 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e97e426ed3f34dafac855f270c178ef6219fdd3
4
- data.tar.gz: f17a5fda4613c6aefc8387d92ab2ef7be2ab039d
3
+ metadata.gz: 0393f96cfe27b0285bfd762bdac9b0f167973a24
4
+ data.tar.gz: 2d8f67229c357f3c392939a2202b4b8173366780
5
5
  SHA512:
6
- metadata.gz: 088cececf8fa874b876d782cc67e63f103e3af88cdea917fc1502c6bc506b325ca39092ae8a368106a56035fd09aba17eb57a17129d6c1d4e9d1be67c4e5c95a
7
- data.tar.gz: 19ab595278b1f340d95c3ef410ccaa828442ba26ec1b0b85ba74ebb5267cd31aef70345fdb891a88d4a0c5a542201e5a5350e670b43f241a7e779f3291c56b7e
6
+ metadata.gz: 765504cd0da9408bd4739c5016309da7429208c5144c08f5cb5082091aec74540ce6dee9200e223d63d9d845b4265aad07f9e364eb1c613301c84af93d272f42
7
+ data.tar.gz: 2d08916d8521a9ef1b65e7ce4a64fa3ea6a1236392f4466155547f05662ddebc0f5b06d03af07ecf4cea9b9d28c557ebd59472a2ef827209a504893fcade3baf
data/README.md CHANGED
@@ -26,6 +26,8 @@ Or install it yourself as:
26
26
  ## Usage
27
27
 
28
28
  ```sh
29
+ export WATCH_LIST_API_KEY=u956-afus321g565fghr519
30
+
29
31
  watch_list -e -o Robotfile
30
32
  vi Robotfile
31
33
  watch_list -a --dry-run
@@ -97,3 +99,25 @@ alert_contact do
97
99
  value "alice@example.com"
98
100
  end
99
101
  ```
102
+
103
+ ## Encryption
104
+
105
+ ```sh
106
+ git config watch-list.pass "**secret password**"
107
+ git config watch-list.salt "nU0+G1icf70="
108
+ # openssl rand -base64 8
109
+ ```
110
+
111
+ ```ruby
112
+ monitor "http monitor" do
113
+ target "http://example.com"
114
+ interval 5
115
+ paused false
116
+ alert_contact :email, "alice@example.com"
117
+
118
+ type :http do
119
+ httpusername "username"
120
+ httppassword :secure=>"A4wjNcr8xl71wVXqsIYuYQ=="
121
+ end
122
+ end
123
+ ```
@@ -28,6 +28,6 @@ class WatchList::DSL::Context::AlertContact
28
28
 
29
29
  def value(value)
30
30
  raise %!AlertContact: "value" is invalid: #{value.inspect}! if value.nil?
31
- @result[:Value] = value.to_s
31
+ @result[:Value] = WatchList::Secure.decrypt_if_possible(value).to_s
32
32
  end
33
33
  end
@@ -2,12 +2,12 @@ class WatchList::DSL::Context::Monitor
2
2
  class HTTP < Type
3
3
  def httpusername(value)
4
4
  raise %!Monitor `#{@monitor_name}`: "httpusername" is invalid: #{value.inspect}! if value.nil?
5
- @result[:HTTPUsername] = value.to_s
5
+ @result[:HTTPUsername] = WatchList::Secure.decrypt_if_possible(value).to_s
6
6
  end
7
7
 
8
8
  def httppassword(value)
9
9
  raise %!Monitor `#{@monitor_name}`: "httppassword" is invalid: #{value.inspect}! if value.nil?
10
- @result[:HTTPPassword] = value.to_s
10
+ @result[:HTTPPassword] = WatchList::Secure.decrypt_if_possible(value).to_s
11
11
  end
12
12
  end
13
13
  end
@@ -24,7 +24,7 @@ class WatchList::DSL::Context::Monitor
24
24
 
25
25
  def keywordvalue(value)
26
26
  raise %!Monitor `#{@monitor_name}`: "keywordvalue" is invalid: #{value.inspect}! if value.nil?
27
- @result[:KeywordValue] = value.to_s
27
+ @result[:KeywordValue] = WatchList::Secure.decrypt_if_possible(value).to_s
28
28
  end
29
29
  end
30
30
  end
@@ -23,7 +23,7 @@ class WatchList::DSL::Context::Monitor
23
23
 
24
24
  def target(value)
25
25
  raise %!Monitor `#{@name}`: "target" is invalid: #{value.inspect}! if value.nil?
26
- @result[:URL] = value.to_s
26
+ @result[:URL] = WatchList::Secure.decrypt_if_possible(value).to_s
27
27
  end
28
28
 
29
29
  def interval(value)
@@ -77,6 +77,9 @@ class WatchList::DSL::Converter
77
77
  if WatchList::Monitor.const_defined?(key)
78
78
  const = WatchList::Monitor.const_get(key)
79
79
  buf << " #{key.to_s.downcase} " + const.key(value).to_sym.inspect
80
+ elsif key == :HTTPPassword and WatchList::Secure.git_encryptable?
81
+ value = WatchList::Secure.git_encrypt(value).inspect.sub(/\A\{/, '').sub(/\}\z/, '')
82
+ buf << " #{key.to_s.downcase} #{value}"
80
83
  else
81
84
  buf << " #{key.to_s.downcase} #{value.inspect}"
82
85
  end
@@ -0,0 +1,69 @@
1
+ class WatchList::Secure
2
+ CIPHER_NAME = 'AES-256-CBC'
3
+
4
+ class << self
5
+ def git_encrypt(data)
6
+ pass, salt = get_pass_salt_from_git(:validate => true)
7
+ {:secure => encrypt(pass, salt, data)}
8
+ end
9
+
10
+ def git_decrypt(data)
11
+ pass, salt = get_pass_salt_from_git(:validate => true)
12
+ decrypt(pass, salt, data.fetch(:secure))
13
+ end
14
+
15
+ def encrypt(pass, salt, data)
16
+ cipher = OpenSSL::Cipher.new(CIPHER_NAME)
17
+ cipher.encrypt
18
+ set_key_iv(pass, salt, cipher)
19
+ encrypted = cipher.update(data) + cipher.final
20
+ Base64.strict_encode64(encrypted)
21
+ end
22
+
23
+ def decrypt(pass, salt, encrypted)
24
+ encrypted = Base64.strict_decode64(encrypted)
25
+ cipher = OpenSSL::Cipher.new(CIPHER_NAME)
26
+ cipher.decrypt
27
+ set_key_iv(pass, salt, cipher)
28
+ cipher.update(encrypted) + cipher.final
29
+ end
30
+
31
+ def set_key_iv(pass, salt, cipher)
32
+ salt = Base64.strict_decode64(salt)
33
+ key_iv = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, 2000, cipher.key_len + cipher.iv_len)
34
+ key = key_iv[0, cipher.key_len]
35
+ iv = key_iv[cipher.key_len, cipher.iv_len]
36
+ cipher.key = key
37
+ cipher.iv = iv
38
+ end
39
+
40
+ def get_pass_salt_from_git(options = {})
41
+ pass = `git config watch-list.pass`.strip
42
+ salt = `git config watch-list.salt`.strip
43
+
44
+ if options[:validate]
45
+ raise 'cannot get "watch-list.pass" from git config' if pass.empty?
46
+ raise 'cannot get "watch-list.salt" from git config' if salt.empty?
47
+ end
48
+
49
+ [pass, salt]
50
+ end
51
+
52
+ def git_encryptable?
53
+ pass, salt = get_pass_salt_from_git
54
+ not pass.empty? and not salt.empty?
55
+ end
56
+
57
+ def encrypted_value?(value)
58
+ value.kind_of?(Hash) and value.has_key?(:secure)
59
+ end
60
+
61
+ def decrypt_if_possible(value)
62
+ if git_encryptable? and encrypted_value?(value)
63
+ git_decrypt(value)
64
+ else
65
+ value
66
+ end
67
+ end
68
+ end # of class methods
69
+ end
@@ -1,3 +1,3 @@
1
1
  module WatchList
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
data/lib/watch_list.rb CHANGED
@@ -1,4 +1,6 @@
1
+ require 'base64'
1
2
  require 'logger'
3
+ require 'openssl'
2
4
  require 'singleton'
3
5
  require 'tempfile'
4
6
  require 'term/ansicolor'
@@ -9,6 +11,7 @@ module WatchList; end
9
11
  require 'watch_list/utils'
10
12
  require 'watch_list/constants'
11
13
  require 'watch_list/logger'
14
+ require 'watch_list/secure'
12
15
 
13
16
  require 'watch_list/client'
14
17
  require 'watch_list/driver'
@@ -0,0 +1,149 @@
1
+ describe 'export' do
2
+ it do
3
+ watch_list do
4
+ <<-RUBY
5
+ alert_contact do
6
+ type :email
7
+ value "#{WATCH_LIST_TEST_EMAIL}"
8
+ end
9
+
10
+ alert_contact do
11
+ type :email
12
+ value "#{WATCH_LIST_TEST_EMAIL2}"
13
+ end
14
+ RUBY
15
+ end
16
+
17
+ wait_until {|h| h[:alert_contacts].length > 1 }
18
+
19
+ expect(watch_list_client.export).to eq <<-RUBY.strip
20
+ alert_contact do
21
+ type :email
22
+ value "#{WATCH_LIST_TEST_EMAIL}"
23
+ end
24
+
25
+ alert_contact do
26
+ type :email
27
+ value "#{WATCH_LIST_TEST_EMAIL2}"
28
+ end
29
+ RUBY
30
+
31
+ watch_list do
32
+ <<-RUBY
33
+ monitor "http monitor" do
34
+ target "http://example.com"
35
+ interval 5
36
+ paused false
37
+ alert_contact :email, "#{WATCH_LIST_TEST_EMAIL}"
38
+ alert_contact :email, "#{WATCH_LIST_TEST_EMAIL2}"
39
+ type :http
40
+ end
41
+
42
+ alert_contact do
43
+ type :email
44
+ value "#{WATCH_LIST_TEST_EMAIL}"
45
+ end
46
+
47
+ alert_contact do
48
+ type :email
49
+ value "#{WATCH_LIST_TEST_EMAIL2}"
50
+ end
51
+ RUBY
52
+ end
53
+
54
+ wait_until {|h| h[:monitors].length > 0 }
55
+
56
+ expect(watch_list_client.export).to eq <<-RUBY.strip
57
+ monitor "http monitor" do
58
+ target "http://example.com"
59
+ interval 5
60
+ paused false
61
+ alert_contact :email, "#{WATCH_LIST_TEST_EMAIL}"
62
+ alert_contact :email, "#{WATCH_LIST_TEST_EMAIL2}"
63
+
64
+ type :http
65
+ end
66
+
67
+ alert_contact do
68
+ type :email
69
+ value "#{WATCH_LIST_TEST_EMAIL}"
70
+ end
71
+
72
+ alert_contact do
73
+ type :email
74
+ value "#{WATCH_LIST_TEST_EMAIL2}"
75
+ end
76
+ RUBY
77
+ end
78
+
79
+ context 'when with encrypt' do
80
+ let(:pass) { '**secret password**' }
81
+ let(:salt) { 'nU0+G1icf70=' }
82
+ let(:encrypted_password) { 'A4wjNcr8xl71wVXqsIYuYQ==' }
83
+
84
+ let(:dsl_with_secure) do
85
+ <<-RUBY
86
+ monitor "http monitor" do
87
+ target "http://example.com"
88
+ interval 5
89
+ paused false
90
+ alert_contact :email, "#{WATCH_LIST_TEST_EMAIL}"
91
+
92
+ type :http do
93
+ httpusername "username"
94
+ httppassword :secure=>"#{encrypted_password}"
95
+ end
96
+ end
97
+
98
+ alert_contact do
99
+ type :email
100
+ value "sugawara.genki@gmail.com"
101
+ end
102
+ RUBY
103
+ end
104
+
105
+ before do
106
+ system(%!git config watch-list.pass "#{pass}"!)
107
+ system(%!git config watch-list.salt "#{salt}"!)
108
+ end
109
+
110
+ after do
111
+ system('git config --remove-section watch-list')
112
+ end
113
+
114
+ it do
115
+ watch_list do
116
+ <<-RUBY
117
+ monitor "http monitor" do
118
+ target "http://example.com"
119
+ interval 5
120
+ paused false
121
+ alert_contact :email, "#{WATCH_LIST_TEST_EMAIL}"
122
+
123
+ type :http do
124
+ httpusername "username"
125
+ httppassword "password"
126
+ end
127
+ end
128
+
129
+ alert_contact do
130
+ type :email
131
+ value "#{WATCH_LIST_TEST_EMAIL}"
132
+ end
133
+ RUBY
134
+ end
135
+
136
+ wait_until {|h| h[:monitors].length > 0 }
137
+
138
+ expect(watch_list_client.export).to eq dsl_with_secure.strip
139
+ end
140
+
141
+ it do
142
+ watch_list { dsl_with_secure }
143
+
144
+ wait_until {|h| h[:monitors].length > 0 }
145
+
146
+ expect(watch_list_client.export).to eq dsl_with_secure.strip
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,81 @@
1
+ describe WatchList::Secure do
2
+ let(:data) { '*secret data*' }
3
+ let(:pass) { '**secret password**' }
4
+ let(:salt) { 'nU0+G1icf70=' }
5
+ let(:encrypted_data) { 'S2aPj2Ajk11sowGJnV+00Q==' }
6
+
7
+ describe '#git_encrypt' do
8
+ before do
9
+ system(%!git config watch-list.pass "#{pass}"!)
10
+ system(%!git config watch-list.salt "#{salt}"!)
11
+ end
12
+
13
+ it do
14
+ expect(described_class.git_encrypt(data)).to eq(secure: encrypted_data)
15
+ end
16
+
17
+ after do
18
+ system('git config --remove-section watch-list')
19
+ end
20
+ end
21
+
22
+ describe '#git_decrypt' do
23
+ before do
24
+ system(%!git config watch-list.pass "#{pass}"!)
25
+ system(%!git config watch-list.salt "#{salt}"!)
26
+ end
27
+
28
+ it do
29
+ expect(described_class.git_decrypt(secure: encrypted_data)).to eq data
30
+ end
31
+
32
+ after do
33
+ system('git config --remove-section watch-list')
34
+ end
35
+ end
36
+
37
+ describe '#encrypt' do
38
+ it do
39
+ expect(described_class.encrypt(pass, salt, data)).to eq encrypted_data
40
+ end
41
+ end
42
+
43
+ describe '#decrypt' do
44
+ it do
45
+ expect(described_class.decrypt(pass, salt, encrypted_data)).to eq data
46
+ end
47
+ end
48
+
49
+ describe '#git_encryptable?' do
50
+ context 'when config is set' do
51
+ before do
52
+ system(%!git config watch-list.pass "#{pass}"!)
53
+ system(%!git config watch-list.salt "#{salt}"!)
54
+ end
55
+
56
+ it do
57
+ expect(described_class.git_encryptable?).to be_truthy
58
+ end
59
+
60
+ after do
61
+ system('git config --remove-section watch-list')
62
+ end
63
+ end
64
+
65
+ context 'when config is not set' do
66
+ it do
67
+ expect(described_class.git_encryptable?).to be_falsey
68
+ end
69
+ end
70
+ end
71
+
72
+ describe '#encrypted_value?' do
73
+ it do
74
+ expect(described_class.encrypted_value?(secure: nil)).to be_truthy
75
+ end
76
+
77
+ it do
78
+ expect(described_class.encrypted_value?(nil)).to be_falsey
79
+ end
80
+ end
81
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: watch_list
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Genki Sugawara
@@ -114,11 +114,14 @@ files:
114
114
  - lib/watch_list/exporter.rb
115
115
  - lib/watch_list/ext/string_ext.rb
116
116
  - lib/watch_list/logger.rb
117
+ - lib/watch_list/secure.rb
117
118
  - lib/watch_list/utils.rb
118
119
  - lib/watch_list/version.rb
119
120
  - spec/alert_contact_spec.rb
121
+ - spec/exporter_spec.rb
120
122
  - spec/monitor_spec.rb
121
123
  - spec/paused_spec.rb
124
+ - spec/secure_spec.rb
122
125
  - spec/spec_helper.rb
123
126
  - spec/status_spec.rb
124
127
  - watch_list.gemspec
@@ -148,7 +151,9 @@ specification_version: 4
148
151
  summary: watch_list is a tool to manage Uptime Robot.
149
152
  test_files:
150
153
  - spec/alert_contact_spec.rb
154
+ - spec/exporter_spec.rb
151
155
  - spec/monitor_spec.rb
152
156
  - spec/paused_spec.rb
157
+ - spec/secure_spec.rb
153
158
  - spec/spec_helper.rb
154
159
  - spec/status_spec.rb