watch_list 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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