vines-agent 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,6 +23,11 @@ module Vines
23
23
  jid = Blather::JID.new(fqdn, domain, 'vines')
24
24
  @stream = Blather::Client.setup(jid, password, host, port, certs)
25
25
 
26
+ @stream.register_handler(:stream_error) do |e|
27
+ log.error(e.message)
28
+ true # prevent EM.stop
29
+ end
30
+
26
31
  @stream.register_handler(:disconnected) do
27
32
  log.info("Stream disconnected, reconnecting . . .")
28
33
  EM::Timer.new(rand(16) + 5) do
@@ -35,6 +40,7 @@ module Vines
35
40
  # prevent handler called twice
36
41
  unless @ready
37
42
  log.info("Connected #{@stream.jid} agent to #{host}:#{port}")
43
+ log.warn("Agent must run as root user to allow user switching") unless root?
38
44
  @ready = true
39
45
  startup
40
46
  end
@@ -270,6 +276,12 @@ module Vines
270
276
  def from_service?(node)
271
277
  @services.include?(node.from.stripped.to_s.downcase)
272
278
  end
279
+
280
+ # Return true if the agent process is owned by root. Switching users with
281
+ # +v user+ is only possible when running as root.
282
+ def root?
283
+ Process.uid == 0
284
+ end
273
285
  end
274
286
  end
275
287
  end
@@ -17,8 +17,8 @@ module Vines
17
17
  # commands.
18
18
  def initialize(jid, permissions)
19
19
  @jid, @permissions = jid, permissions
20
- @user, @commands = allowed_users.first, EM::Queue.new
21
- spawn(@user)
20
+ @user = allowed_users.first if allowed_users.size == 1
21
+ @commands = EM::Queue.new
22
22
  process_command_queue
23
23
  end
24
24
 
@@ -55,7 +55,10 @@ module Vines
55
55
  end
56
56
 
57
57
  def run_in_slave(command)
58
+ return "-> no user selected, run 'v user'" unless @user
58
59
  log.info("Running #{command} as #{@user}")
60
+
61
+ spawn(@user) unless @shell
59
62
  out, err = @shell.execute(command)
60
63
  output = [].tap do |arr|
61
64
  arr << out if out && !out.empty?
@@ -63,16 +66,21 @@ module Vines
63
66
  end.join("\n")
64
67
  output.empty? ? '-> command completed' : output
65
68
  rescue
66
- spawn(@user)
69
+ close
67
70
  '-> restarted shell'
68
71
  end
69
72
 
73
+ def close
74
+ @slave.shutdown(quiet: true) if @slave
75
+ @slave = @shell = nil
76
+ end
77
+
70
78
  # Fork a child process in which to run a shell as this user. Return
71
79
  # the slave and its remote shell proxy. The agent process must be run
72
80
  # as root for the user switch to work.
73
81
  def spawn(user)
74
82
  log.info("Starting shell as #{user}")
75
- @slave.shutdown(quiet: true) if @slave
83
+ close
76
84
  Thread.new do # so em thread won't die on @slave.shutdown
77
85
  slave = Slave.new(psname: "vines-session-#{user}") do
78
86
  uid = Process.euid
@@ -95,7 +103,7 @@ module Vines
95
103
  shell
96
104
  end
97
105
  File.chmod(0700, slave.socket)
98
- @slave, @shell = [slave, slave.object]
106
+ @slave, @shell = slave, slave.object
99
107
  end.join
100
108
  end
101
109
 
@@ -112,21 +120,49 @@ module Vines
112
120
  def run_built_in(command)
113
121
  _, command, *args = command.strip.split(/\s+/)
114
122
  case command
115
- when 'user' then user_command(args)
116
- when 'reset' then reset_command(args)
117
- else '-> not a vines command'
123
+ when 'user' then user_command(args)
124
+ when 'reset' then reset_command(args)
125
+ when 'version' then version_command(args)
126
+ when 'help' then help_command(args)
127
+ else '-> usage: v user|reset|version|help'
118
128
  end
119
129
  end
120
130
 
131
+ def help_command(args)
132
+ [
133
+ "Usage:",
134
+ " v user [name] Display the current user or switch users.",
135
+ " v reset Stops the shell session and starts a new one.",
136
+ " v version Display the agent's version.",
137
+ " v help Provide help on vines commands."
138
+ ].join("\n")
139
+ end
140
+
141
+ def version_command(args)
142
+ return "-> usage: v version" unless args.empty?
143
+ Vines::Agent::VERSION
144
+ end
145
+
121
146
  # Run the +v user+ built-in vines command to list or change the current
122
147
  # unix account executing shell commands.
123
148
  def user_command(args)
124
- return "-> current: #{@user}\n allowed: #{allowed_users.join(', ')}" if args.empty?
125
149
  return "-> usage: v user [name]" if args.size > 1
126
- return "-> user switch not allowed" unless allowed?(args.first)
127
- @user = args.first
128
- spawn(@user)
129
- "-> switched user to #{@user}"
150
+
151
+ if args.empty?
152
+ current = @user || '<none>'
153
+ allowed = allowed_users.empty? ? '<none>' : allowed_users.join(', ')
154
+ return "-> current: #{current}\n allowed: #{allowed}"
155
+ end
156
+
157
+ user = args.first
158
+ if allowed?(user)
159
+ @user = user
160
+ close
161
+ "-> switched user to #{@user}"
162
+ else
163
+ log.warn("#{@jid} denied access to #{user}")
164
+ "-> user switch not allowed"
165
+ end
130
166
  end
131
167
 
132
168
  def reset?(command)
@@ -137,7 +173,7 @@ module Vines
137
173
  def reset_command(args)
138
174
  return "-> usage: v reset" unless args.empty?
139
175
  @commands = EM::Queue.new
140
- spawn(@user)
176
+ close
141
177
  process_command_queue
142
178
  "-> reset shell"
143
179
  end
@@ -145,21 +181,30 @@ module Vines
145
181
  # Return true if the current JID is allowed to run commands as the given
146
182
  # user name on this system.
147
183
  def allowed?(user)
148
- jids = @permissions[user] || []
149
- valid = jids.include?(@jid) && exists?(user)
150
- log.warn("#{@jid} denied access to #{user}") unless valid
151
- valid
184
+ allowed = (@permissions[user] || []).include?(@jid)
185
+ allowed && exists?(user) && (root? || current?(user))
186
+ end
187
+
188
+ # Return true if the agent process is owned by root. Switching users with
189
+ # +v user+ is only possible when running as root.
190
+ def root?
191
+ Process.uid == 0
192
+ end
193
+
194
+ # Return true if the user name is the current agent process owner.
195
+ def current?(user)
196
+ Process.uid == Etc.getpwnam(user).uid
197
+ rescue
198
+ false
152
199
  end
153
200
 
154
201
  def exists?(user)
155
- Etc::getpwnam(user) rescue false
202
+ Etc.getpwnam(user) rescue false
156
203
  end
157
204
 
158
205
  # Return the list of unix user accounts this user is allowed to access.
159
206
  def allowed_users
160
- @permissions.select do |unix, jids|
161
- jids.include?(@jid) && exists?(unix)
162
- end.keys.sort
207
+ @permissions.keys.sort.select {|unix| allowed?(unix) }
163
208
  end
164
209
  end
165
210
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Vines
4
4
  module Agent
5
- VERSION = '0.1.1'
5
+ VERSION = '0.1.2'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vines-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-20 00:00:00.000000000Z
12
+ date: 2011-10-28 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: blather
16
- requirement: &70352868783740 !ruby/object:Gem::Requirement
16
+ requirement: &70257751095360 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.5.8
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70352868783740
24
+ version_requirements: *70257751095360
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: ohai
27
- requirement: &70352868782180 !ruby/object:Gem::Requirement
27
+ requirement: &70257751094400 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.6.8
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70352868782180
35
+ version_requirements: *70257751094400
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: session
38
- requirement: &70352868780480 !ruby/object:Gem::Requirement
38
+ requirement: &70257751093700 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 3.1.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70352868780480
46
+ version_requirements: *70257751093700
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: slave
49
- requirement: &70352868778940 !ruby/object:Gem::Requirement
49
+ requirement: &70257751092940 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.3.0
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70352868778940
57
+ version_requirements: *70257751092940
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: vines
60
- requirement: &70352868777680 !ruby/object:Gem::Requirement
60
+ requirement: &70257751092280 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0.3'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70352868777680
68
+ version_requirements: *70257751092280
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: minitest
71
- requirement: &70352865325120 !ruby/object:Gem::Requirement
71
+ requirement: &70257751091680 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70352865325120
79
+ version_requirements: *70257751091680
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rake
82
- requirement: &70352865324580 !ruby/object:Gem::Requirement
82
+ requirement: &70257751091220 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70352865324580
90
+ version_requirements: *70257751091220
91
91
  description: ! 'Vines Agent executes shell commands sent by users after
92
92
 
93
93
  authorizing them against an access control list, provided by the Vines Services