whimsy-asf 0.0.24 → 0.0.25

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.
data/asf.version CHANGED
@@ -1 +1 @@
1
- 0.0.24
1
+ 0.0.25
@@ -2,38 +2,22 @@ require 'wunderbar'
2
2
  require 'ldap'
3
3
 
4
4
  module ASF
5
-
6
5
  # determine whether or not the LDAP API can be used
7
6
  def self.init_ldap
8
7
  @ldap = nil
9
8
 
10
- config = ASF::Config.get(:ldap)
9
+ host = ASF::LDAP.host
11
10
 
12
- unless config
13
- conf = '/etc/ldap/ldap.conf'
14
- if File.exist? conf
15
- config = File.read(conf)[/^uri\s+(ldaps?:\/\/\S+?:\d+)/i, 1]
16
- end
17
- end
18
-
19
- unless config
20
- # https://www.pingmybox.com/dashboard?location=304
21
- config = %w(ldaps://ldap1-us-west.apache.org:636
22
- ldaps://ldap1-eu-central.apache.org:636
23
- ldaps://ldap2-us-west.apache.org:636
24
- ldaps://ldap1-us-east.apache.org:636).sample
25
- end
26
-
27
- Wunderbar.info "Connecting to LDAP server: #{config}"
11
+ Wunderbar.info "Connecting to LDAP server: #{host}"
28
12
 
29
13
  begin
30
- uri = URI.parse(config)
14
+ uri = URI.parse(host)
31
15
  if uri.scheme == 'ldaps'
32
- @ldap = LDAP::SSLConn.new(uri.host, uri.port)
16
+ @ldap = ::LDAP::SSLConn.new(uri.host, uri.port)
33
17
  else
34
- @ldap = LDAP::Conn.new(uri.host, uri.port)
18
+ @ldap = ::LDAP::Conn.new(uri.host, uri.port)
35
19
  end
36
- rescue LDAP::ResultError=>re
20
+ rescue ::LDAP::ResultError=>re
37
21
  Wunderbar.error "Error binding to LDAP server: message: ["+ re.message + "]"
38
22
  end
39
23
  end
@@ -47,7 +31,7 @@ module ASF
47
31
  "#{[attrs].flatten.join(' ')}"
48
32
 
49
33
  begin
50
- result = @ldap.search2(base, LDAP::LDAP_SCOPE_ONELEVEL, filter, attrs)
34
+ result = @ldap.search2(base, ::LDAP::LDAP_SCOPE_ONELEVEL, filter, attrs)
51
35
  rescue
52
36
  result = []
53
37
  end
@@ -176,6 +160,10 @@ module ASF
176
160
  ASF::Member.status[name] or ASF.members.include? self
177
161
  end
178
162
 
163
+ def asf_committer?
164
+ ASF::Group.new('committers').include? self
165
+ end
166
+
179
167
  def banned?
180
168
  not attrs['loginShell'] or attrs['loginShell'].include? "/usr/bin/false"
181
169
  end
@@ -212,6 +200,15 @@ module ASF
212
200
  ASF.search_one(base, filter, 'cn').flatten.map {|cn| find(cn)}
213
201
  end
214
202
 
203
+ def include?(person)
204
+ filter = "(&(cn=#{name})(memberUid=#{person.name}))"
205
+ if ASF.search_one(base, filter, 'cn').empty?
206
+ return false
207
+ else
208
+ return true
209
+ end
210
+ end
211
+
215
212
  def members
216
213
  ASF.search_one(base, "cn=#{name}", 'memberUid').flatten.
217
214
  map {|uid| Person.find(uid)}
@@ -243,4 +240,57 @@ module ASF
243
240
  map {|uid| Person.find uid[/uid=(.*?),/,1]}
244
241
  end
245
242
  end
243
+
244
+ module LDAP
245
+ # select LDAP host
246
+ def self.host
247
+ # try whimsy config
248
+ host = ASF::Config.get(:ldap)
249
+
250
+ # check system configuration
251
+ unless host
252
+ conf = '/etc/ldap/ldap.conf'
253
+ if File.exist? conf
254
+ host = File.read(conf)[/^uri\s+(ldaps?:\/\/\S+?:\d+)/i, 1]
255
+ end
256
+ end
257
+
258
+ # if all else fails, pick one at random
259
+ unless host
260
+ # https://www.pingmybox.com/dashboard?location=304
261
+ host = %w(ldaps://ldap1-us-west.apache.org:636
262
+ ldaps://ldap1-eu-central.apache.org:636
263
+ ldaps://ldap2-us-west.apache.org:636
264
+ ldaps://ldap1-us-east.apache.org:636).sample
265
+ end
266
+
267
+ host
268
+ end
269
+
270
+ # query and extract cert from openssl output
271
+ def self.cert
272
+ host = LDAP.host[%r{//(.*?)(/|$)}, 1]
273
+ query = "openssl s_client -connect #{host} -showcerts"
274
+ output = `#{query} < /dev/null 2> /dev/null`
275
+ output[/^-+BEGIN.*?\n-+END[^\n]+\n/m]
276
+ end
277
+
278
+ # update /etc/ldap.conf. Usage:
279
+ # sudo ruby -r whimsy/asf -e "ASF::LDAP.configure"
280
+ def self.configure
281
+ if not File.exist? "/etc/ldap/asf-ldap-client.pem"
282
+ File.write "/etc/ldap/asf-ldap-client.pem", self.cert
283
+ end
284
+
285
+ ldap_conf = '/etc/ldap/ldap.conf'
286
+ content = File.read(ldap_conf)
287
+ unless content.include? 'asf-ldap-client.pem'
288
+ content.gsub!(/^TLS_CACERT/, '# TLS_CACERT')
289
+ content += "TLS_CACERT /etc/ldap/asf-ldap-client.pem\n"
290
+ content += "uri #{LDAP.host}\n"
291
+ content += "base dc=apache,dc=org\n"
292
+ File.write(ldap_conf, content)
293
+ end
294
+ end
295
+ end
246
296
  end
@@ -17,7 +17,7 @@ module ASF
17
17
  }
18
18
 
19
19
  # decode HTTP authorization, when present
20
- def self.decode(env, user)
20
+ def self.decode(env)
21
21
  class << env; attr_accessor :user, :password; end
22
22
 
23
23
  if env['HTTP_AUTHORIZATION']
@@ -25,25 +25,25 @@ module ASF
25
25
  env.user, env.password = Base64.decode64(env['HTTP_AUTHORIZATION'][
26
26
  /^Basic ([A-Za-z0-9+\/=]+)$/,1]).split(':',2)
27
27
  else
28
- env.user = user
28
+ env.user = env['REMOTE_USER'] ||= ENV['USER'] || Etc.getpwuid.name
29
29
  end
30
+
31
+ ASF::Person.new(env.user)
30
32
  end
31
33
 
32
34
  # Simply 'use' the following class in config.ru to limit access
33
35
  # to the application to ASF committers
34
36
  class Committers < Rack::Auth::Basic
35
37
  def initialize(app)
36
- super(app, "ASF Members and Officers", &proc {})
38
+ super(app, "ASF Committers", &proc {})
37
39
  end
38
40
 
39
41
  def call(env)
40
42
  authorized = ( ENV['RACK_ENV'] == 'test' )
41
43
 
42
- user = env['REMOTE_USER'] ||= ENV['USER'] || Etc.getpwuid.name
43
- authorized ||= ASF::Person.new(user)
44
+ authorized ||= ASF::Auth.decode(env).asf_committer?
44
45
 
45
46
  if authorized
46
- ASF::Auth.decode(env, user)
47
47
  @app.call(env)
48
48
  else
49
49
  unauthorized
@@ -61,21 +61,19 @@ module ASF
61
61
  def call(env)
62
62
  authorized = ( ENV['RACK_ENV'] == 'test' )
63
63
 
64
- user = env['REMOTE_USER'] ||= ENV['USER'] || Etc.getpwuid.name
65
- person = ASF::Person.new(user)
64
+ person = ASF::Auth.decode(env)
66
65
 
67
- authorized ||= DIRECTORS[user]
66
+ authorized ||= DIRECTORS[env.user]
68
67
  authorized ||= person.asf_member?
69
68
  authorized ||= ASF.pmc_chairs.include? person
70
69
 
71
70
  if not authorized
72
71
  accounting = ASF::Authorization.new('pit').
73
72
  find {|group, list| group=='accounting'}
74
- authorized = (accounting and accounting.last.include? user)
73
+ authorized = (accounting and accounting.last.include? env.user)
75
74
  end
76
75
 
77
76
  if authorized
78
- ASF::Auth.decode(env, user)
79
77
  @app.call(env)
80
78
  else
81
79
  unauthorized
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: whimsy-asf
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.24
5
+ version: 0.0.25
6
6
  platform: ruby
7
7
  authors:
8
8
  - Sam Ruby