sudo 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2053fedb37f34b870e40e278da1d10d1319eb7ca312ecb0095df168d32b99c2e
4
+ data.tar.gz: 8b50e8441761ef16a2abe245d7d9e0b1904a82eddb8fe5984b710025fd0f7d23
5
+ SHA512:
6
+ metadata.gz: 415df83c7088c488e652b34dabb82b74eaccc01b8344b6728af9e416128337d82198dc1241f1a2c27a48f4c7e4ab3fba4cc46b4e4df21c53a26fbadc08d219e6
7
+ data.tar.gz: 538abc4e634d6201d21ff2fda5cc34f694367201e9991643094462573f246d34897fb928a078dd6247ee7426c501f25dc321fde464e4e5058cc39e8689ef8239
@@ -0,0 +1,16 @@
1
+ # Sudo
2
+
3
+ ## 0.2.0 _(November 05, 2018)_
4
+ - Modernized
5
+ - Tests
6
+ - Works on ruby 2.3 - 2.5
7
+ - More robust dependency loading
8
+
9
+ ## 0.0.3 _(October 25, 2010)_
10
+ -
11
+
12
+ ## 0.0.2 _(October 22, 2010)_
13
+ -
14
+
15
+ ## 0.0.1 _(October 22, 2010)_
16
+ -
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2010, 2011, 2012, 2013 Guido De Rosa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,104 @@
1
+ [![Version ](https://img.shields.io/gem/v/sudo.svg?maxAge=2592000)](https://rubygems.org/gems/sudo)
2
+ [![Build Status](https://travis-ci.com/gderosa/rubysu.svg?branch=master)](https://travis-ci.com/gderosa/rubysu)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/3fdebfb836bebb531fb3/maintainability)](https://codeclimate.com/github/gderosa/rubysu/maintainability)
4
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/3fdebfb836bebb531fb3/test_coverage)](https://codeclimate.com/github/gderosa/rubysu/test_coverage)
5
+
6
+ # Ruby Sudo
7
+
8
+ Give Ruby objects superuser privileges.
9
+
10
+ Based on [dRuby](http://ruby-doc.org/stdlib-2.5.3/libdoc/drb/rdoc/DRb.html) and [sudo](http://www.sudo.ws/).
11
+
12
+ Only tested with [MRI](http://en.wikipedia.org/wiki/Ruby_MRI). (2.3, 2.4 and 2.5)
13
+
14
+ ## Usage
15
+
16
+ Your user must be allowed, in `/etc/sudoers`, to run `ruby` and `kill`
17
+ commands as root.
18
+
19
+ A password may be required from the console, depending on the
20
+ `NOPASSWD` options in `/etc/sudoers`.
21
+
22
+ Spawns a sudo-ed Ruby process running a
23
+ [DRb](http://ruby-doc.org/stdlib-2.5.3/libdoc/drb/rdoc/DRb.html) server. Communication is
24
+ done via a Unix socket (and, of course, permissions are set to `0600`).
25
+
26
+ No long-running daemons involved, everything is created on demand.
27
+
28
+ Access control is entirely delegated to `sudo`.
29
+
30
+ ### Application Code
31
+
32
+ Let's start with a trivial example:
33
+
34
+ ```ruby
35
+ require 'my_gem/my_class'
36
+ require 'sudo'
37
+
38
+ obj = MyGem::MyClass.new
39
+
40
+ # Now, create a Sudo::Wrapper object:
41
+ sudo = Sudo::Wrapper.new
42
+
43
+ # 'mygem/myclass' will be automatically required in the
44
+ # sudo DRb server
45
+
46
+ # Start the sudo-ed Ruby process:
47
+ sudo.start!
48
+ sudo[obj].my_instance_method
49
+ sudo[MyClass].my_class_method
50
+
51
+ # Call stop! when finished, otherwise, that will be done
52
+ # when the `sudo` object gets garbage-collected.
53
+ sudo.stop!
54
+ ```
55
+
56
+ A convienient utility for working with sudo is to use the `run` method and pass it a block.
57
+ Run will automatically start and stop the ruby sudo process around the block.
58
+
59
+ ```ruby
60
+ require 'fileutils'
61
+ require 'sudo'
62
+
63
+ Sudo::Wrapper.run do |sudo|
64
+ sudo[FileUtils].mkdir_p '/ONLY/ROOT/CAN/DO/THAT'
65
+ end
66
+ # Sockets and processes are closed automatically when the block exits
67
+ ```
68
+
69
+ Both `Sudo::Wrapper.run` and `Sudo::Wrapper.new` take the same named arguments: `ruby_opts` (default: `''` ) and `load_gems` (default: `true`).
70
+
71
+ If you'd like to pass options to the sudo-spawned ruby process, pass them as a string to `ruby_opts`.
72
+
73
+ If you'd like to prevent the loading of `gems` currently loaded from the calling program, pass `false` to `load_gems`. This will give your sudo process a unmodifed environment. The only things required via the sudo process are `'drb/drb'`, `'fileutils'`, and of course `'sudo'`.
74
+
75
+ ## Todo
76
+
77
+ `sudo` has a `-A` option to accept password via an external program (maybe
78
+ graphical): support this feature.
79
+
80
+ ## Credits
81
+
82
+ ### Author
83
+
84
+ Guido De Rosa ([@gderosa](http://github.com/gderosa/)).
85
+
86
+ Originally sponsored by [@vemarsas](https://github.com/vemarsas).
87
+
88
+ ### Contributors
89
+
90
+ Dale ([@voltechs](https://github.com/voltechs))
91
+
92
+ Robert M. Koch ([@threadmetal](https://github.com/threadmetal))
93
+
94
+ ### Other aknowledgements
95
+ Thanks to Tony Arcieri and Brian Candler for suggestions on
96
+ [ruby-talk](http://www.ruby-forum.com/topic/262655).
97
+
98
+ ## Contributing
99
+
100
+ 1. Fork it ( https://github.com/gderosa/rubysu/fork )
101
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
102
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
103
+ 4. Push to the branch (`git push origin my-new-feature`)
104
+ 5. Create a new Pull Request
@@ -1,11 +1,18 @@
1
+ require 'pathname'
2
+
1
3
  module Sudo
2
4
 
3
- VERSION = '0.1.1'
4
- ROOTDIR = File.expand_path File.join File.dirname(__FILE__), '../..'
5
- LIBDIR = File.join ROOTDIR, 'lib'
6
- SERVER_SCRIPT = File.join ROOTDIR, 'libexec/server.rb'
7
- SUDO_CMD = ENV['rvm_path'] ? 'rvmsudo' : 'sudo'
5
+ VERSION = '0.2.0'
6
+
7
+ def self.root
8
+ @root ||= Pathname.new(File.expand_path('../../', __dir__))
9
+ end
10
+
11
+ LIBDIR = root.join('lib')
12
+ SERVER_SCRIPT = root.join('libexec/server.rb')
13
+ SUDO_CMD = `which sudo`.chomp
14
+ RUBY_CMD = `which ruby`.chomp
8
15
 
9
- class RuntimeError < RuntimeError; end
16
+ RuntimeError = Class.new(RuntimeError)
10
17
 
11
18
  end
@@ -1,4 +1,3 @@
1
- require 'sudo/support/object'
2
1
 
3
2
  module Sudo
4
3
 
@@ -7,15 +6,28 @@ module Sudo
7
6
  @object = object
8
7
  @proxy = proxy
9
8
  end
10
- def method_missing(method=:self, *args, &blk)
9
+ def method_missing(method=:itself, *args, &blk)
11
10
  @proxy.proxy @object, method, *args, &blk
12
11
  end
13
12
  end
14
13
 
15
14
  class Proxy
16
- def proxy(object, method=:self, *args, &blk)
15
+ def proxy(object, method=:itself, *args, &blk)
17
16
  object.send method, *args, &blk
18
17
  end
18
+
19
+ def loaded_specs
20
+ # Something's weird with this method when called outside
21
+ Gem.loaded_specs.to_a.to_h
22
+ end
23
+
24
+ def load_path
25
+ $LOAD_PATH
26
+ end
27
+
28
+ def add_load_path(path)
29
+ $LOAD_PATH << path
30
+ end
19
31
  end
20
32
 
21
33
  end
@@ -1,20 +1,12 @@
1
- module Kernel
2
- def wait_for(conf)
3
- start = Time.now
4
- defaults = {
5
- :timeout => nil,
6
- :step => 0.125
7
- }
8
- conf = defaults.update conf
9
- condition = false
10
- loop do
11
- condition = yield
1
+ require 'timeout'
12
2
 
13
- break if condition
14
- break if conf[:timeout] and Time.now - start > conf[:timeout]
15
-
16
- sleep conf[:step]
3
+ module Kernel
4
+ def wait_for(timeout: nil, step: 0.125)
5
+ Timeout::timeout(timeout) do
6
+ condition = false
7
+ sleep(step) until (condition = yield) and return condition
17
8
  end
18
- condition
19
- end
9
+ rescue Timeout::Error
10
+ return false
11
+ end
20
12
  end
@@ -3,12 +3,10 @@ module Process
3
3
  # Thanks to:
4
4
  # http://stackoverflow.com/questions/141162/how-can-i-determine-if-a-different-process-id-is-running-using-java-or-jruby-on-l
5
5
  def exists?(pid)
6
- begin
7
- Process.getpgid( pid )
8
- true
9
- rescue Errno::ESRCH
10
- false
11
- end
6
+ Process.getpgid( pid )
7
+ true
8
+ rescue Errno::ESRCH
9
+ false
12
10
  end
13
11
  end
14
12
  end
@@ -4,31 +4,29 @@ require 'sudo/constants'
4
4
  module Sudo
5
5
  module System
6
6
 
7
- class ProcessStillExists < RuntimeError; end
8
- class FileStillExists < RuntimeError; end
7
+ ProcessStillExists = Class.new(RuntimeError)
8
+ FileStillExists = Class.new(RuntimeError)
9
9
 
10
10
  class << self
11
11
 
12
12
  def kill(pid)
13
13
  if pid and Process.exists? pid
14
- system "sudo kill #{pid}" or
15
- system "sudo kill -9 #{pid}" or
16
- raise ProcessStillExists,
17
- "Couldn't kill sudo process (PID=#{pid})"
14
+ system "sudo kill #{pid}" or
15
+ system "sudo kill -9 #{pid}" or
16
+ raise ProcessStillExists, "Couldn't kill sudo process (PID=#{pid})"
18
17
  end
19
18
  end
20
19
 
21
20
  def unlink(file)
22
21
  if file and File.exists? file
23
- system "sudo rm -f #{file}" or
24
- raise FileStillExists,
25
- "Couldn't delete #{file}"
22
+ system("sudo rm -f #{file}") or
23
+ raise(FileStillExists, "Couldn't delete #{file}")
26
24
  end
27
25
  end
28
26
 
29
27
  # just to check if we can sudo; and we'll receive a sudo token
30
28
  def check
31
- raise SudoFailed unless system "sudo ruby -e ''"
29
+ raise SudoFailed unless system "#{SUDO_CMD} -E #{RUBY_CMD} -e ''"
32
30
  end
33
31
 
34
32
  end
@@ -6,17 +6,18 @@ require 'sudo/system'
6
6
  require 'sudo/proxy'
7
7
 
8
8
  module Sudo
9
+
9
10
  class Wrapper
10
11
 
11
- class RuntimeError < RuntimeError; end
12
- class NotRunning < RuntimeError; end
13
- class SudoFailed < RuntimeError; end
14
- class SudoProcessExists < RuntimeError; end
15
- class SudoProcessAlreadyExists < SudoProcessExists; end
16
- class NoValidSocket < RuntimeError; end
17
- class SocketNotFound < NoValidSocket; end
18
- class NoValidSudoPid < RuntimeError; end
19
- class SudoProcessNotFound < NoValidSudoPid; end
12
+ RuntimeError = Class.new(RuntimeError)
13
+ NotRunning = Class.new(RuntimeError)
14
+ SudoFailed = Class.new(RuntimeError)
15
+ SudoProcessExists = Class.new(RuntimeError)
16
+ SudoProcessAlreadyExists = Class.new(SudoProcessExists)
17
+ NoValidSocket = Class.new(RuntimeError)
18
+ SocketNotFound = Class.new(NoValidSocket)
19
+ NoValidSudoPid = Class.new(RuntimeError)
20
+ SudoProcessNotFound = Class.new(NoValidSudoPid)
20
21
 
21
22
  class << self
22
23
 
@@ -24,11 +25,13 @@ module Sudo
24
25
  # cleanup when the block exits.
25
26
  #
26
27
  # ruby_opts:: is passed to Sudo::Wrapper::new .
27
- def run(ruby_opts = '') # :yields: sudo
28
- sudo = new(ruby_opts).start!
29
- retval = yield sudo
28
+ def run(ruby_opts: '', load_gems: true) # :yields: sudo
29
+ sudo = new(ruby_opts: ruby_opts, load_gems: load_gems).start!
30
+ yield sudo
31
+ rescue Exception => e # Bubble all exceptions...
32
+ raise e
33
+ ensure # and ensure sudo stops
30
34
  sudo.stop!
31
- retval
32
35
  end
33
36
 
34
37
  # Do the actual resources clean-up.
@@ -45,13 +48,12 @@ module Sudo
45
48
  # +ruby_opts+ are the command line options to the sudo ruby interpreter;
46
49
  # usually you don't need to specify stuff like "-rmygem/mylib", libraries
47
50
  # will be sorta "inherited".
48
- def initialize(ruby_opts='')
51
+ def initialize(ruby_opts: '', load_gems: true)
49
52
  @proxy = nil
50
53
  @socket = "/tmp/rubysu-#{Process.pid}-#{object_id}"
51
54
  @sudo_pid = nil
52
55
  @ruby_opts = ruby_opts
53
- @loaded_features = []
54
- # @load_path = [] # currentl unused
56
+ @load_gems = load_gems == true
55
57
  end
56
58
 
57
59
  def server_uri; "drbunix:#{@socket}"; end
@@ -61,39 +63,23 @@ module Sudo
61
63
  Sudo::System.check
62
64
 
63
65
  @sudo_pid = spawn(
64
- "#{SUDO_CMD} ruby -I#{LIBDIR} #{@ruby_opts} #{SERVER_SCRIPT} #{@socket} #{Process.uid}"
66
+ "#{SUDO_CMD} -E #{RUBY_CMD} -I#{LIBDIR} #{@ruby_opts} #{SERVER_SCRIPT} #{@socket} #{Process.uid}"
65
67
  )
66
68
  Process.detach(@sudo_pid) if @sudo_pid # avoid zombies
67
- ObjectSpace.define_finalizer self, Finalizer.new(
68
- :pid => @sudo_pid, :socket => @socket
69
- )
69
+ finalizer = Finalizer.new(pid: @sudo_pid, socket: @socket)
70
+ ObjectSpace.define_finalizer(self, finalizer)
70
71
 
71
- if wait_for(:timeout => 1){File.exists? @socket}
72
+ if wait_for(timeout: 1){File.exists? @socket}
72
73
  @proxy = DRbObject.new_with_uri(server_uri)
73
74
  else
74
75
  raise RuntimeError, "Couldn't create DRb socket #{@socket}"
75
76
  end
76
77
 
77
- #set_load_path # apparently, we don't need this
78
-
79
- load_features
78
+ load!
80
79
 
81
80
  self
82
81
  end
83
82
 
84
- # Load needed libraries in the DRb server. Usually you don't need
85
- # to call this directly.
86
- def load_features
87
- unless $LOADED_FEATURES == @loaded_features
88
- new_features = $LOADED_FEATURES - @loaded_features
89
- new_features.each do |feature|
90
- @proxy.proxy Kernel, :require, feature
91
- @loaded_features << feature
92
- end
93
- #@loaded_features += new_features
94
- end
95
- end
96
-
97
83
  def running?
98
84
  true if (
99
85
  @sudo_pid and Process.exists? @sudo_pid and
@@ -106,14 +92,14 @@ module Sudo
106
92
  # ruby process and the Unix-domain socket used to communicate
107
93
  # to it via ::DRb.
108
94
  def stop!
109
- self.class.cleanup!(:pid => @sudo_pid, :socket => @socket)
95
+ self.class.cleanup!(pid: @sudo_pid, socket: @socket)
110
96
  @proxy = nil
111
97
  end
112
98
 
113
99
  # Gives a copy of +object+ with root privileges.
114
100
  def [](object)
115
101
  if running?
116
- load_features
102
+ load!
117
103
  MethodProxy.new object, @proxy
118
104
  else
119
105
  raise NotRunning
@@ -133,5 +119,44 @@ module Sudo
133
119
  end
134
120
  end
135
121
 
122
+ protected
123
+
124
+ def load!
125
+ load_gems if load_gems?
126
+ end
127
+
128
+ def load_gems?
129
+ @load_gems == true
130
+ end
131
+
132
+ def prospective_gems
133
+ (Gem.loaded_specs.keys - @proxy.loaded_specs.keys)
134
+ end
135
+
136
+ # Load needed libraries in the DRb server. Usually you don't need
137
+ def load_gems
138
+ load_paths
139
+ prospective_gems.each do |prospect|
140
+ gem_name = prospect.dup
141
+ begin
142
+ loaded = @proxy.proxy(Kernel, :require, gem_name)
143
+ # puts "Loading Gem: #{gem_name} => #{loaded}"
144
+ rescue LoadError, NameError => e
145
+ old_gem_name = gem_name.dup
146
+ gem_name.gsub!('-', '/')
147
+ retry if old_gem_name != gem_name
148
+ end
149
+ end
150
+ end
151
+
152
+ def load_paths
153
+ host_paths = $LOAD_PATH
154
+ proxy_paths = @proxy.load_path
155
+ diff_paths = host_paths - proxy_paths
156
+ diff_paths.each do |path|
157
+ @proxy.add_load_path(path)
158
+ end
159
+ end
160
+
136
161
  end
137
162
  end
metadata CHANGED
@@ -1,70 +1,114 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sudo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Guido De Rosa
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-01-06 00:00:00.000000000 Z
13
- dependencies: []
14
- description: ! 'Give Ruby objects superuser privileges.
15
-
16
-
11
+ date: 2018-11-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry-byebug
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: |
70
+ Give Ruby objects superuser privileges.
17
71
  Based on dRuby and sudo (the Unix program).
18
-
19
- '
20
- email: guido.derosa@vemarsas.it
72
+ email:
73
+ - guidoderosa@gmail.com
21
74
  executables: []
22
75
  extensions: []
23
- extra_rdoc_files:
24
- - README.rdoc
76
+ extra_rdoc_files: []
25
77
  files:
26
- - examples/block.rb
27
- - examples/dsl.rb
28
- - examples/new.rb
29
- - examples/writable_root.rb
30
- - examples/lib/writable_root.rb
31
- - libexec/server.rb
78
+ - CHANGELOG.md
79
+ - LICENSE
80
+ - README.md
81
+ - lib/sudo.rb
32
82
  - lib/sudo/constants.rb
33
- - lib/sudo/dsl.rb
34
83
  - lib/sudo/proxy.rb
35
- - lib/sudo.rb
36
84
  - lib/sudo/support/kernel.rb
37
- - lib/sudo/support/object.rb
38
85
  - lib/sudo/support/process.rb
39
86
  - lib/sudo/system.rb
40
87
  - lib/sudo/wrapper.rb
41
- - MANIFEST
42
- - README.rdoc
43
- homepage: http://github.com/gderosa/rubysu
44
- licenses: []
88
+ - libexec/server.rb
89
+ homepage: https://github.com/gderosa/rubysu
90
+ licenses:
91
+ - MIT
92
+ metadata:
93
+ allowed_push_host: https://rubygems.org
45
94
  post_install_message:
46
- rdoc_options:
47
- - --charset=UTF-8
48
- - --main
49
- - README.rdoc
95
+ rdoc_options: []
50
96
  require_paths:
51
97
  - lib
52
98
  required_ruby_version: !ruby/object:Gem::Requirement
53
- none: false
54
99
  requirements:
55
- - - ! '>='
100
+ - - ">="
56
101
  - !ruby/object:Gem::Version
57
- version: '0'
102
+ version: '2.3'
58
103
  required_rubygems_version: !ruby/object:Gem::Requirement
59
- none: false
60
104
  requirements:
61
- - - ! '>='
105
+ - - ">="
62
106
  - !ruby/object:Gem::Version
63
107
  version: '0'
64
108
  requirements: []
65
109
  rubyforge_project:
66
- rubygems_version: 1.8.11
110
+ rubygems_version: 2.7.3
67
111
  signing_key:
68
- specification_version: 3
112
+ specification_version: 4
69
113
  summary: Give Ruby objects superuser privileges
70
114
  test_files: []
data/MANIFEST DELETED
@@ -1,17 +0,0 @@
1
- examples/block.rb
2
- examples/dsl.rb
3
- examples/new.rb
4
- examples/writable_root.rb
5
- examples/lib/writable_root.rb
6
- libexec/server.rb
7
- lib/sudo/constants.rb
8
- lib/sudo/dsl.rb
9
- lib/sudo/proxy.rb
10
- lib/sudo.rb
11
- lib/sudo/support/kernel.rb
12
- lib/sudo/support/object.rb
13
- lib/sudo/support/process.rb
14
- lib/sudo/system.rb
15
- lib/sudo/wrapper.rb
16
- MANIFEST
17
- README.rdoc
@@ -1,119 +0,0 @@
1
- = Ruby \Sudo
2
-
3
- Give Ruby objects superuser privileges.
4
-
5
- Based on dRuby[http://ruby-doc.org/ruby-1.9/classes/DRb.html] and
6
- sudo[http://www.sudo.ws/].
7
-
8
- Only tested with {MRI 1.9}[http://en.wikipedia.org/wiki/Ruby_MRI] .
9
-
10
- == REQUIREMENTS
11
-
12
- Your user must be allowed, in +/etc/sudoers+, to run +ruby+ and +kill+
13
- commands as root.
14
-
15
- A password will be required from the console, or not, depending on
16
- the +NOPASSWD+ options in +/etc/sudoers+.
17
-
18
- == USAGE
19
-
20
- Let's start with a trivial example:
21
-
22
- require 'mygem/myclass'
23
- require 'sudo'
24
-
25
- obj = MyGem::MyClass.new
26
-
27
-
28
- Now, create a Sudo::Wrapper object:
29
-
30
- sudo = Sudo::Wrapper.new
31
-
32
-
33
- Start the sudo-ed Ruby process:
34
-
35
- # 'mygem/myclass' will be automatically required in the
36
- # sudo DRb server
37
-
38
- sudo.start!
39
-
40
-
41
- Use it!
42
-
43
- sudo[obj].my_instance_method
44
- sudo[MyClass].my_class_method
45
-
46
-
47
- When you've done, +stop!+ it. Otherwise, that will be done (only) when
48
- the +sudo+ object gets garbage-collected.
49
-
50
- sudo.stop!
51
-
52
- === With a block
53
-
54
- Use Sudo::Wrapper::run in this case.
55
-
56
- require 'fileutils'
57
- require 'sudo'
58
-
59
- Sudo::Wrapper.run do |sudo|
60
- sudo[FileUtils].mkdir_p '/ONLY/ROOT/CAN/DO/THAT'
61
- end
62
- # Sockets and processes are closed automatically when the block exits
63
-
64
- == PRINCIPLES OF OPERATION
65
-
66
- Spawns a sudo-ed Ruby process running a
67
- DRb[http://ruby-doc.org/ruby-1.9/classes/DRb.html] server. Communication is
68
- done via a Unix socket (and, of course, permissions are set to +0600+).
69
-
70
- No long-running daemons involved, everything is created on demand.
71
-
72
- Access control is entirely delegated to +sudo+.
73
-
74
- == TODO
75
-
76
- +sudo+ has a +-A+ option to accept password via an external program
77
- (maybe graphical): support this feature.
78
-
79
- == CREDITS
80
-
81
- === AUTHOR
82
-
83
- {Guido De Rosa}[http://github.com/gderosa/].
84
-
85
- Sponsored by {VEMAR s.a.s.}[http://www.vemarsas.it/]
86
-
87
- === CONTRIBUTORS
88
-
89
- {Robert M. Koch}[http://github.com/threadmetal/].
90
-
91
- === THANKS
92
-
93
- Thanks to Tony Arcieri and Brian Candler for suggestions on
94
- ruby-talk[http://www.ruby-forum.com/topic/262655].
95
-
96
- === COPYRIGHT
97
-
98
- (The MIT License)
99
-
100
- Copyright (c) 2010, 2011, 2012, 2013 Guido De Rosa
101
-
102
- Permission is hereby granted, free of charge, to any person obtaining
103
- a copy of this software and associated documentation files (the
104
- 'Software'), to deal in the Software without restriction, including
105
- without limitation the rights to use, copy, modify, merge, publish,
106
- distribute, sublicense, and/or sell copies of the Software, and to
107
- permit persons to whom the Software is furnished to do so, subject to
108
- the following conditions:
109
-
110
- The above copyright notice and this permission notice shall be
111
- included in all copies or substantial portions of the Software.
112
-
113
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
114
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
115
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
116
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
117
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
118
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
119
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,18 +0,0 @@
1
- require 'fileutils'
2
- require 'sudo'
3
-
4
- Sudo::Wrapper.run do |su|
5
-
6
- su[File].open '/TEST', 'w' do |f|
7
- f.puts "Hello from UID=#{su[Process].uid}!"
8
- end
9
-
10
- su[FileUtils].cp '/etc/shadow', '/etc/shadow2'
11
-
12
- end
13
-
14
-
15
-
16
-
17
-
18
-
@@ -1,14 +0,0 @@
1
- =begin
2
- require 'sudo/dsl'
3
-
4
- include Sudo::DSL
5
-
6
- sudo_start "-rfileutils"
7
-
8
- puts sudo(File).read '/etc/shadow'
9
-
10
- sudo(FileUtils).mkdir_p '/TEST_DIR/SUB_DIR'
11
-
12
- #sudo_stop # automatic clenup, when out of scope, if not explicit
13
-
14
- =end
@@ -1,7 +0,0 @@
1
- class WritableRoot
2
- def check
3
- puts "As uid = #{Process.uid}, writable root = #{File.writable? '/'} (object_id=#{object_id})"
4
- end
5
- end
6
-
7
-
@@ -1,28 +0,0 @@
1
- require 'fileutils'
2
- autoload :IPAddr, 'ipaddr'
3
- require 'sudo'
4
-
5
- # Requires and autoloads are inherited by the sudo process.
6
-
7
- su = Sudo::Wrapper.new
8
-
9
- su.start!
10
-
11
- su[File].open '/TEST', 'w' do |f|
12
- f.puts "Hello from UID=#{su[Process].uid}!"
13
- f.puts "#{su[IPAddr].new}"
14
- end
15
-
16
- su[FileUtils].cp '/etc/shadow', '/etc/shadow2'
17
-
18
- # If you don't call stop! explicitly, the corresponding process and file
19
- # cleanup will be done when su gets garbage-collected.
20
- #
21
- su.stop!
22
-
23
-
24
-
25
-
26
-
27
-
28
-
@@ -1,52 +0,0 @@
1
- require 'sudo'
2
-
3
-
4
- t0 = Time.now
5
- su = Sudo::Wrapper.new.start!
6
- t1 = Time.now
7
-
8
- writable_root = su[File].writable? '/'
9
- t2 = Time.now
10
- writable_root_by_normal_user = File.writable? '/'
11
-
12
- puts
13
- puts "writable_root = #{writable_root}"
14
- puts "writable_root_by_normal_user = #{writable_root_by_normal_user}"
15
- puts "Starting Sudo::Wrapper object took #{t1-t0} seconds"
16
- puts "Using it, as in su[File].writable? '/', took #{t2-t1} seconds"
17
-
18
- puts
19
- puts "Now trying on an instance of WritableRoot custom class:"
20
-
21
- $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/lib"
22
- require 'writable_root'
23
-
24
- wr1 = WritableRoot.new
25
- wr2 = WritableRoot.new
26
-
27
- wr1.check
28
- su[wr2].check
29
-
30
- puts
31
- puts "Hit ENTER to stop the Sudo::Wrapper object"
32
- puts "(in the meantime, you can look at the ruby sudo-ed process with ps)"
33
- gets
34
-
35
- # Optional (it will be stopped automatically as soon as 'su' object gets out of scope).
36
- su.stop!
37
-
38
- puts "Now trying with a block (Sudo::Wrapper.run):"
39
- writable_root = Sudo::Wrapper.run do |sudo|
40
- print "As uid=#{ sudo[Process].uid }, "
41
- sudo[File].writable? '/'
42
- end
43
- puts "writable_root = #{writable_root.inspect}"
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
@@ -1,27 +0,0 @@
1
- =begin
2
- DEPRECATED
3
-
4
- It's not clear what the scope of __default_sudo_wrapper should be:
5
- local, instance, class? global? and what about thread-safety?
6
-
7
- =end
8
-
9
- =begin
10
- require 'sudo/wrapper'
11
-
12
- module Sudo
13
-
14
- module DSL
15
- def sudo_start(*args, &blk)
16
- @__default_sudo_wrapper = Sudo::Wrapper.new(*args, &blk).start!
17
- end
18
- def sudo_stop
19
- @__default_sudo_wrapper.stop!
20
- end
21
- def sudo(object)
22
- @__default_sudo_wrapper[object]
23
- end
24
- end
25
-
26
- end
27
- =end
@@ -1,5 +0,0 @@
1
- class Object
2
- def self
3
- self
4
- end
5
- end