pechkin 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pechkin.rb +20 -6
- data/lib/pechkin/app.rb +8 -3
- data/lib/pechkin/auth.rb +57 -0
- data/lib/pechkin/cli.rb +31 -7
- data/lib/pechkin/message_template.rb +3 -20
- data/lib/pechkin/prometheus_utils.rb +12 -0
- data/lib/pechkin/version.rb +1 -1
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59912e94ce5225522475cb9f77b3bbb83c398a5dada6b1f937c02c0a886e2e8f
|
4
|
+
data.tar.gz: dcf67693f3ecaa7de96ef00ee3e4bfc0347d6ee45f546a3c8e7ae9e5d39b34b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d071d69449005cf0dfae928a148391ea1247876bcc06cd52c588ca84d5210e37a66a0838e10511ed0a6554b1ecf6904961467e6d1fef916676a4296f34687367
|
7
|
+
data.tar.gz: d59c5fcbf1c97be064075bf012ca0d760d65edd911bd4cd551efcc64468292ed213423fcfb893823aa57191b38433bb803a09158cd3da2da18558f8a7bd5d795
|
data/lib/pechkin.rb
CHANGED
@@ -3,6 +3,8 @@ require 'rack'
|
|
3
3
|
require 'logger'
|
4
4
|
require 'prometheus/middleware/collector'
|
5
5
|
require 'prometheus/middleware/exporter'
|
6
|
+
require 'htauth'
|
7
|
+
require 'base64'
|
6
8
|
|
7
9
|
require_relative 'pechkin/cli'
|
8
10
|
require_relative 'pechkin/exceptions'
|
@@ -14,6 +16,8 @@ require_relative 'pechkin/connector_telegram'
|
|
14
16
|
require_relative 'pechkin/channel'
|
15
17
|
require_relative 'pechkin/configuration'
|
16
18
|
require_relative 'pechkin/substitute'
|
19
|
+
require_relative 'pechkin/prometheus_utils'
|
20
|
+
require_relative 'pechkin/auth'
|
17
21
|
require_relative 'pechkin/app'
|
18
22
|
|
19
23
|
module Pechkin # :nodoc:
|
@@ -33,20 +37,24 @@ module Pechkin # :nodoc:
|
|
33
37
|
|
34
38
|
def initialize(options)
|
35
39
|
@options = options
|
36
|
-
@configuration = Configuration.load_from_directory(options.config_file)
|
37
|
-
@handler = Handler.new(@configuration.channels)
|
38
40
|
end
|
39
41
|
|
40
42
|
def run
|
43
|
+
if options.add_auth
|
44
|
+
add_auth
|
45
|
+
exit 0
|
46
|
+
end
|
47
|
+
|
48
|
+
@configuration = Configuration.load_from_directory(options.config_file)
|
49
|
+
@handler = Handler.new(@configuration.channels)
|
41
50
|
configuration.list if options.list?
|
42
|
-
|
51
|
+
return if options.check?
|
43
52
|
|
44
53
|
if options.send_data
|
45
54
|
send_data
|
46
|
-
|
55
|
+
else
|
56
|
+
run_server
|
47
57
|
end
|
48
|
-
|
49
|
-
run_server
|
50
58
|
end
|
51
59
|
|
52
60
|
def run_server
|
@@ -79,5 +87,11 @@ module Pechkin # :nodoc:
|
|
79
87
|
[m[1], m[2]]
|
80
88
|
end
|
81
89
|
end
|
90
|
+
|
91
|
+
def add_auth
|
92
|
+
user, password = options.add_auth.split(':')
|
93
|
+
Pechkin::Auth::Manager.new(options.htpasswd).add(user, password)
|
94
|
+
puts IO.read(options.htpasswd)
|
95
|
+
end
|
82
96
|
end
|
83
97
|
end
|
data/lib/pechkin/app.rb
CHANGED
@@ -5,14 +5,19 @@ module Pechkin
|
|
5
5
|
def build(handler, options)
|
6
6
|
app = App.new
|
7
7
|
app.handler = handler
|
8
|
-
|
8
|
+
prometheus = Pechkin::PrometheusUtils.registry
|
9
9
|
logger = create_logger(options.log_dir)
|
10
10
|
|
11
11
|
Rack::Builder.app do
|
12
12
|
use Rack::CommonLogger, logger
|
13
13
|
use Rack::Deflater
|
14
|
-
use Prometheus::Middleware::Collector
|
15
|
-
|
14
|
+
use Prometheus::Middleware::Collector, registry: prometheus
|
15
|
+
# Add Auth check if found htpasswd file or it was excplicitly provided
|
16
|
+
# See CLI class for configuration details
|
17
|
+
if options.htpasswd
|
18
|
+
use Pechkin::Auth::Middleware, auth_file: options.htpasswd
|
19
|
+
end
|
20
|
+
use Prometheus::Middleware::Exporter, registry: prometheus
|
16
21
|
|
17
22
|
run app
|
18
23
|
end
|
data/lib/pechkin/auth.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Pechkin
|
2
|
+
module Auth
|
3
|
+
# Utility class for altering htpasswd files
|
4
|
+
class Manager
|
5
|
+
attr_reader :htpasswd
|
6
|
+
def initialize(htpasswd)
|
7
|
+
@htpasswd = htpasswd
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(user, password)
|
11
|
+
m = File.exist?(htpasswd) ? HTAuth::File::ALTER : HTAuth::File::CREATE
|
12
|
+
HTAuth::PasswdFile.open(htpasswd, m) do |f|
|
13
|
+
f.add_or_update(user, password, 'md5')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Auth middleware to check if provided auth can be found in .htpasswd file
|
19
|
+
class Middleware
|
20
|
+
attr_reader :htpasswd
|
21
|
+
|
22
|
+
def initialize(app, auth_file:)
|
23
|
+
@htpasswd = HTAuth::PasswdFile.open(auth_file) if File.exist?(auth_file)
|
24
|
+
@app = app
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(env)
|
28
|
+
if authorized?(env)
|
29
|
+
@app.call(env)
|
30
|
+
else
|
31
|
+
body = { status: 'error', reason: 'unathorized' }.to_json
|
32
|
+
['401', { 'Content-Type' => 'application/json' }, [body]]
|
33
|
+
end
|
34
|
+
rescue StandardError => e
|
35
|
+
puts e.backtrace.reverse.join('\n\t')
|
36
|
+
body = { status: 'error', reason: e.message }.to_json
|
37
|
+
['503', { 'Content-Type' => 'application/json' }, [body]]
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def authorized?(env)
|
43
|
+
return true unless htpasswd
|
44
|
+
|
45
|
+
auth = env['HTTP_AUTHORIZATION'] || ''
|
46
|
+
auth.match(/^Basic (.+)$/) do |m|
|
47
|
+
check_auth(*Base64.decode64(m[1]).split(':'))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def check_auth(user, password)
|
52
|
+
e = htpasswd.fetch(user)
|
53
|
+
e && e.authenticated?(password)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/pechkin/cli.rb
CHANGED
@@ -43,7 +43,7 @@ module Pechkin
|
|
43
43
|
exit 2
|
44
44
|
else
|
45
45
|
parser.parse(args)
|
46
|
-
values
|
46
|
+
new.post_init(values)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -89,6 +89,9 @@ module Pechkin
|
|
89
89
|
|
90
90
|
# Command Line Parser Builder
|
91
91
|
class CLI
|
92
|
+
# Default file name for htpasswd file with auth credentials
|
93
|
+
PECHKIN_HTPASSWD_FILE = 'pechkin.htpasswd'.freeze
|
94
|
+
|
92
95
|
extend CLIHelper
|
93
96
|
|
94
97
|
separator 'Run options'
|
@@ -104,28 +107,49 @@ module Pechkin
|
|
104
107
|
|
105
108
|
opt :log_dir, names: ['--log-dir [DIR]'],
|
106
109
|
desc: 'Path to log directory. Output will be writen to' \
|
107
|
-
'pechkin.log file. If not specified will write to' \
|
110
|
+
'pechkin.log file. If not specified will write to ' \
|
108
111
|
'STDOUT'
|
112
|
+
opt :htpasswd, names: ['--auth-file FILE'],
|
113
|
+
desc: 'Path to .htpasswd file. By default ' \
|
114
|
+
'`pechkin.htpasswd` file will be looked up in ' \
|
115
|
+
'configuration directory and if found then ' \
|
116
|
+
'authorization will be enabled implicitly. ' \
|
117
|
+
'Providing this option enables htpasswd based ' \
|
118
|
+
'authorization explicitly. When making requests use ' \
|
119
|
+
'Basic auth to authorize.'
|
109
120
|
|
110
121
|
separator 'Utils for configuration maintenance'
|
111
|
-
|
112
122
|
opt :list?, names: ['-l', '--[no-]list'],
|
113
123
|
desc: 'List all endpoints'
|
114
124
|
|
115
125
|
opt :check?, names: ['-k', '--[no-]check'],
|
116
126
|
desc: 'Load configuration and exit'
|
117
127
|
opt :send_data, names: ['-s', '--send ENDPOINT'],
|
118
|
-
desc: 'Send data to specified ENDPOINT and exit.
|
119
|
-
'--data to be set.'
|
128
|
+
desc: 'Send data to specified ENDPOINT and exit. ' \
|
129
|
+
'Requires --data to be set.'
|
120
130
|
opt :preview, names: ['--preview'],
|
121
131
|
desc: 'Print rendering result to STDOUT and exit. ' \
|
122
|
-
'Use with send'
|
132
|
+
'Use with --send'
|
123
133
|
opt :data, names: ['--data DATA'],
|
124
134
|
desc: 'Data to send with --send flag. Json string or @filename.'
|
125
135
|
|
126
|
-
separator '
|
136
|
+
separator 'Auth utils'
|
137
|
+
opt :add_auth, names: ['--add-auth USER:PASSWORD'],
|
138
|
+
desc: 'Add auth entry to .htpasswd file. By default ' \
|
139
|
+
'pechkin.htpasswd from configuration directory ' \
|
140
|
+
'will be used. Use --auth-file to specify other ' \
|
141
|
+
'file to update. If file does not exist it will be ' \
|
142
|
+
'created.'
|
127
143
|
|
144
|
+
separator 'Debug options'
|
128
145
|
opt :debug?, names: ['--[no-]debug'],
|
129
146
|
desc: 'Print debug information and stack trace on errors'
|
147
|
+
|
148
|
+
def post_init(values)
|
149
|
+
default_htpasswd = File.join(values.config_file, PECHKIN_HTPASSWD_FILE)
|
150
|
+
values.htpasswd ||= default_htpasswd
|
151
|
+
|
152
|
+
values
|
153
|
+
end
|
130
154
|
end
|
131
155
|
end
|
@@ -8,31 +8,14 @@ module Pechkin
|
|
8
8
|
|
9
9
|
# Message template to render final message.
|
10
10
|
class MessageTemplate
|
11
|
-
|
12
|
-
|
13
|
-
# Need to compare two versions, one is 2.6.0 - which supports keyword
|
14
|
-
# arguments in ERB#initialize. Everything below that should use legacy
|
15
|
-
# arguments
|
16
|
-
rb_v260 = [2, 6, 0]
|
17
|
-
rb_current = ruby_version.split('.').map(&:to_i)
|
18
|
-
|
19
|
-
rb_v260.zip(rb_current).each do |x, y|
|
20
|
-
x ||= 0
|
21
|
-
y ||= 0
|
22
|
-
return false if y < x
|
23
|
-
end
|
24
|
-
|
25
|
-
true
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
RUBY_V260 = MessageTemplate.ruby_v260_or_later?
|
11
|
+
ERB_INITIALIZE_KEYWORD_ARGUMENTS = ERB.instance_method(:initialize)
|
12
|
+
.parameters.assoc(:key)
|
30
13
|
|
31
14
|
def initialize(erb)
|
32
15
|
# ERB#initialize has different signature starting from Ruby 2.6.*
|
33
16
|
# See link:
|
34
17
|
# https://github.com/ruby/ruby/blob/2311087/NEWS#stdlib-updates-outstanding-ones-only
|
35
|
-
if MessageTemplate::
|
18
|
+
if MessageTemplate::ERB_INITIALIZE_KEYWORD_ARGUMENTS # Ruby 2.6+
|
36
19
|
@erb_template = ERB.new(erb, trim_mode: '-')
|
37
20
|
else
|
38
21
|
safe_level = nil
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Pechkin
|
2
|
+
module PrometheusUtils # :nodoc:
|
3
|
+
class << self
|
4
|
+
def registry
|
5
|
+
registry = ::Prometheus::Client.registry
|
6
|
+
registry.gauge(:pechkin_start_time_seconds,
|
7
|
+
docstring: 'Startup timestamp').set(Time.now.to_i)
|
8
|
+
registry
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/pechkin/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pechkin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ilya Arkhanhelsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-12-
|
11
|
+
date: 2019-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grape
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: htauth
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.0.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: prometheus-client
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,14 +58,14 @@ dependencies:
|
|
44
58
|
requirements:
|
45
59
|
- - '='
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: 2.0.
|
61
|
+
version: 2.0.8
|
48
62
|
type: :runtime
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - '='
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: 2.0.
|
68
|
+
version: 2.0.8
|
55
69
|
description:
|
56
70
|
email: ilya.arkhanhelsky at gmail.com
|
57
71
|
executables:
|
@@ -62,6 +76,7 @@ files:
|
|
62
76
|
- bin/pechkin
|
63
77
|
- lib/pechkin.rb
|
64
78
|
- lib/pechkin/app.rb
|
79
|
+
- lib/pechkin/auth.rb
|
65
80
|
- lib/pechkin/channel.rb
|
66
81
|
- lib/pechkin/cli.rb
|
67
82
|
- lib/pechkin/configuration.rb
|
@@ -76,6 +91,7 @@ files:
|
|
76
91
|
- lib/pechkin/exceptions.rb
|
77
92
|
- lib/pechkin/handler.rb
|
78
93
|
- lib/pechkin/message_template.rb
|
94
|
+
- lib/pechkin/prometheus_utils.rb
|
79
95
|
- lib/pechkin/substitute.rb
|
80
96
|
- lib/pechkin/version.rb
|
81
97
|
homepage: https://github.com/iarkhanhelsky/pechkin
|