sudo 0.1.1 → 0.3.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8533dcc019e5bf40c31a3a2f0d00fb1ed7799710fbd623e1f35bdc7b3854f8ad
4
+ data.tar.gz: d21c8cc10c30840bdcd0d6a9c86816ea8123897305c5e4b41b6503301c39e8f6
5
+ SHA512:
6
+ metadata.gz: 53a797c78535d39c6fd4c123726345cc6ad4a73617f8e835437ab49c86168dbfd83696776ea7c2a1fdb26419e88f9cb6799bf33365447ff42c2a023015c0fc48
7
+ data.tar.gz: e81deabf36e8a0a4a4bad76e8d94560c0518e25deb8f8dac7184dcbb9befee866f704a2f17716dafc773ad0427329120c7ca88562fb82af21e061234681c5114
data/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Sudo
2
+
3
+ ## 0.3.0 _(July 04, 2023)_
4
+ - Works on ruby 3.2
5
+
6
+ ## 0.2.0 _(November 05, 2018)_
7
+ - Modernized
8
+ - Tests
9
+ - Works on ruby 2.3 - 2.5
10
+ - More robust dependency loading
11
+
12
+ ## 0.0.3 _(October 25, 2010)_
13
+ -
14
+
15
+ ## 0.0.2 _(October 22, 2010)_
16
+ -
17
+
18
+ ## 0.0.1 _(October 22, 2010)_
19
+ -
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2010-2023 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.
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ [![Gem Version](https://badge.fury.io/rb/sudo.svg)](https://badge.fury.io/rb/sudo)[![Build Status](https://travis-ci.com/gderosa/rubysu.svg?branch=master)](https://travis-ci.com/gderosa/rubysu)
2
+ [![Maintainability](https://api.codeclimate.com/v1/badges/3fdebfb836bebb531fb3/maintainability)](https://codeclimate.com/github/gderosa/rubysu/maintainability)
3
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/3fdebfb836bebb531fb3/test_coverage)](https://codeclimate.com/github/gderosa/rubysu/test_coverage)
4
+
5
+ # Ruby Sudo
6
+
7
+ Give Ruby objects superuser privileges.
8
+
9
+ Based on [dRuby](http://ruby-doc.org/stdlib-2.5.3/libdoc/drb/rdoc/DRb.html) and [sudo](http://www.sudo.ws/).
10
+
11
+ Only tested with [MRI](http://en.wikipedia.org/wiki/Ruby_MRI).
12
+
13
+ ## Usage
14
+
15
+ Your user must be allowed, in `/etc/sudoers`, to run `ruby` and `kill`
16
+ commands as root.
17
+
18
+ A password may be required from the console, depending on the
19
+ `NOPASSWD` options in `/etc/sudoers`.
20
+
21
+ Spawns a sudo-ed Ruby process running a
22
+ [DRb](http://ruby-doc.org/stdlib-2.5.3/libdoc/drb/rdoc/DRb.html) server. Communication is
23
+ done via a Unix socket (and, of course, permissions are set to `0600`).
24
+
25
+ No long-running daemons involved, everything is created on demand.
26
+
27
+ Access control is entirely delegated to `sudo`.
28
+
29
+ ### Application Code
30
+
31
+ Let's start with a trivial example:
32
+
33
+ ```ruby
34
+ require 'my_gem/my_class'
35
+ require 'sudo'
36
+
37
+ obj = MyGem::MyClass.new
38
+
39
+ # Now, create a Sudo::Wrapper object:
40
+ sudo = Sudo::Wrapper.new
41
+
42
+ # 'mygem/myclass' will be automatically required in the
43
+ # sudo DRb server
44
+
45
+ # Start the sudo-ed Ruby process:
46
+ sudo.start!
47
+ sudo[obj].my_instance_method
48
+ sudo[MyClass].my_class_method
49
+
50
+ # Call stop! when finished, otherwise, that will be done
51
+ # when the `sudo` object gets garbage-collected.
52
+ sudo.stop!
53
+ ```
54
+
55
+ A convienient utility for working with sudo is to use the `run` method and pass it a block.
56
+ Run will automatically start and stop the ruby sudo process around the block.
57
+
58
+ ```ruby
59
+ require 'fileutils'
60
+ require 'sudo'
61
+
62
+ Sudo::Wrapper.run do |sudo|
63
+ sudo[FileUtils].mkdir_p '/ONLY/ROOT/CAN/DO/THAT'
64
+ end
65
+ # Sockets and processes are closed automatically when the block exits
66
+ ```
67
+
68
+ Both `Sudo::Wrapper.run` and `Sudo::Wrapper.new` take the same named arguments: `ruby_opts` (default: `''` ) and `load_gems` (default: `true`).
69
+
70
+ If you'd like to pass options to the sudo-spawned ruby process, pass them as a string to `ruby_opts`.
71
+
72
+ 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'`.
73
+
74
+ ## Todo
75
+
76
+ `sudo` has a `-A` option to accept password via an external program (maybe
77
+ graphical): support this feature.
78
+
79
+ ## Credits
80
+
81
+ ### Author and Copyright
82
+
83
+ Guido De Rosa ([@gderosa](http://github.com/gderosa/)).
84
+
85
+ See LICENSE.
86
+
87
+ ### Contributors
88
+
89
+ Dale Stevens ([@voltechs](https://github.com/voltechs))
90
+
91
+ Robert M. Koch ([@threadmetal](https://github.com/threadmetal))
92
+
93
+ Wolfgang Teuber ([@wteuber](https://github.com/wteuber))
94
+
95
+ ### Other aknowledgements
96
+ Thanks to Tony Arcieri and Brian Candler for suggestions on
97
+ [ruby-talk](http://www.ruby-forum.com/topic/262655).
98
+
99
+ Initially developed by G. D. while working at [@vemarsas](https://github.com/vemarsas).
100
+
101
+ ## Contributing
102
+
103
+ 1. Fork it ( https://github.com/gderosa/rubysu/fork )
104
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
105
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
106
+ 4. Push to the branch (`git push origin my-new-feature`)
107
+ 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.3.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
data/lib/sudo/proxy.rb CHANGED
@@ -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
data/lib/sudo/system.rb CHANGED
@@ -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
- if file and File.exists? file
23
- system "sudo rm -f #{file}" or
24
- raise FileStillExists,
25
- "Couldn't delete #{file}"
21
+ if file and File.exist? 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
data/lib/sudo/wrapper.rb CHANGED
@@ -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,43 +63,27 @@ 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.exist? @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
100
- @socket and File.exists? @socket and
86
+ @socket and File.exist? @socket and
101
87
  @proxy
102
88
  )
103
89
  end
@@ -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,113 @@
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.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Guido De Rosa
9
- autorequire:
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: 2023-07-10 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: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
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: []
45
- post_install_message:
46
- rdoc_options:
47
- - --charset=UTF-8
48
- - --main
49
- - README.rdoc
88
+ - libexec/server.rb
89
+ homepage: https://github.com/TwilightCoders/rubysu
90
+ licenses:
91
+ - MIT
92
+ metadata:
93
+ allowed_push_host: https://rubygems.org
94
+ post_install_message:
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
- rubyforge_project:
66
- rubygems_version: 1.8.11
67
- signing_key:
68
- specification_version: 3
109
+ rubygems_version: 3.1.6
110
+ signing_key:
111
+ specification_version: 4
69
112
  summary: Give Ruby objects superuser privileges
70
113
  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
data/README.rdoc DELETED
@@ -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.
data/examples/block.rb DELETED
@@ -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
-
data/examples/dsl.rb DELETED
@@ -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
-
data/examples/new.rb DELETED
@@ -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
-
data/lib/sudo/dsl.rb DELETED
@@ -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