right_link 5.9.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.
Files changed (199) hide show
  1. data/actors/agent_manager.rb +88 -0
  2. data/actors/instance_scheduler.rb +321 -0
  3. data/actors/instance_services.rb +64 -0
  4. data/actors/instance_setup.rb +567 -0
  5. data/bin/cloud +25 -0
  6. data/bin/cook_runner +44 -0
  7. data/bin/deploy +120 -0
  8. data/bin/enroll +385 -0
  9. data/bin/rad +32 -0
  10. data/bin/rchk +29 -0
  11. data/bin/rnac +39 -0
  12. data/bin/rs_connect +33 -0
  13. data/bin/rs_log_level +31 -0
  14. data/bin/rs_ohai +28 -0
  15. data/bin/rs_reenroll +31 -0
  16. data/bin/rs_run_recipe +34 -0
  17. data/bin/rs_run_right_script +34 -0
  18. data/bin/rs_shutdown +33 -0
  19. data/bin/rs_tag +33 -0
  20. data/bin/rs_thunk +33 -0
  21. data/bin/rstat +31 -0
  22. data/bin/system +16 -0
  23. data/ext/Rakefile +18 -0
  24. data/init/config.yml +5 -0
  25. data/init/init.rb +79 -0
  26. data/lib/chef/ohai_setup.rb +51 -0
  27. data/lib/chef/plugins/cloud.rb +91 -0
  28. data/lib/chef/plugins/cloudstack.rb +23 -0
  29. data/lib/chef/plugins/ec2.rb +23 -0
  30. data/lib/chef/plugins/linux/block_device2.rb +24 -0
  31. data/lib/chef/plugins/rackspace.rb +23 -0
  32. data/lib/chef/plugins/rightscale.rb +125 -0
  33. data/lib/chef/plugins/windows/network.rb +114 -0
  34. data/lib/chef/plugins.rb +74 -0
  35. data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
  36. data/lib/chef/providers/dns_resource.rb +100 -0
  37. data/lib/chef/providers/executable_schedule_provider.rb +70 -0
  38. data/lib/chef/providers/executable_schedule_resource.rb +144 -0
  39. data/lib/chef/providers/remote_recipe_provider.rb +86 -0
  40. data/lib/chef/providers/remote_recipe_resource.rb +101 -0
  41. data/lib/chef/providers/right_link_tag_provider.rb +73 -0
  42. data/lib/chef/providers/right_link_tag_resource.rb +59 -0
  43. data/lib/chef/providers/right_script_provider.rb +190 -0
  44. data/lib/chef/providers/right_script_resource.rb +113 -0
  45. data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
  46. data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
  47. data/lib/chef/providers/server_collection_provider.rb +66 -0
  48. data/lib/chef/providers/server_collection_resource.rb +93 -0
  49. data/lib/chef/providers/windows/powershell_provider.rb +151 -0
  50. data/lib/chef/providers/windows/powershell_resource.rb +111 -0
  51. data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
  52. data/lib/chef/right_providers.rb +55 -0
  53. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
  54. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
  55. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
  56. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
  57. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
  58. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
  59. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
  60. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
  61. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
  62. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
  63. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
  64. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
  65. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
  66. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
  67. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
  68. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
  69. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
  70. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
  71. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
  72. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
  73. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
  74. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  75. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
  76. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
  77. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
  78. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
  79. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
  80. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
  81. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
  82. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
  83. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
  84. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
  85. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
  86. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
  87. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
  88. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
  89. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
  90. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
  91. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
  92. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
  93. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  94. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
  95. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
  96. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
  97. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
  98. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
  99. data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
  100. data/lib/chef/windows/chef_node_server.rb +463 -0
  101. data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
  102. data/lib/chef/windows/pipe_server.rb +283 -0
  103. data/lib/chef/windows/powershell_host.rb +285 -0
  104. data/lib/chef/windows/powershell_pipe_server.rb +136 -0
  105. data/lib/chef/windows/powershell_provider_base.rb +92 -0
  106. data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
  107. data/lib/clouds/cloud.rb +557 -0
  108. data/lib/clouds/cloud_factory.rb +250 -0
  109. data/lib/clouds/cloud_utilities.rb +244 -0
  110. data/lib/clouds/clouds/azure.rb +106 -0
  111. data/lib/clouds/clouds/cloudstack.rb +114 -0
  112. data/lib/clouds/clouds/ec2.rb +113 -0
  113. data/lib/clouds/clouds/eucalyptus.rb +46 -0
  114. data/lib/clouds/clouds/google.rb +102 -0
  115. data/lib/clouds/clouds/none.rb +76 -0
  116. data/lib/clouds/clouds/openstack.rb +30 -0
  117. data/lib/clouds/clouds/rackspace-ng.rb +54 -0
  118. data/lib/clouds/clouds/rackspace.rb +78 -0
  119. data/lib/clouds/clouds/softlayer.rb +91 -0
  120. data/lib/clouds/metadata_formatter.rb +108 -0
  121. data/lib/clouds/metadata_provider.rb +128 -0
  122. data/lib/clouds/metadata_source.rb +87 -0
  123. data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
  124. data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
  125. data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
  126. data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
  127. data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
  128. data/lib/clouds/metadata_tree_climber.rb +144 -0
  129. data/lib/clouds/metadata_writer.rb +155 -0
  130. data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
  131. data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
  132. data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
  133. data/lib/clouds/register_clouds.rb +34 -0
  134. data/lib/clouds.rb +32 -0
  135. data/lib/gem_dependencies.rb +83 -0
  136. data/lib/git_hooks/commit-msg.rb +7 -0
  137. data/lib/instance/agent_config.rb +168 -0
  138. data/lib/instance/agent_watcher.rb +233 -0
  139. data/lib/instance/audit_cook_stub.rb +104 -0
  140. data/lib/instance/audit_proxy.rb +247 -0
  141. data/lib/instance/bundle_queue.rb +104 -0
  142. data/lib/instance/cook/agent_connection.rb +109 -0
  143. data/lib/instance/cook/audit_logger.rb +165 -0
  144. data/lib/instance/cook/audit_stub.rb +142 -0
  145. data/lib/instance/cook/ca-bundle.crt +2794 -0
  146. data/lib/instance/cook/chef_state.rb +211 -0
  147. data/lib/instance/cook/cook.rb +306 -0
  148. data/lib/instance/cook/cook_state.rb +298 -0
  149. data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
  150. data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
  151. data/lib/instance/cook/executable_sequence.rb +765 -0
  152. data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
  153. data/lib/instance/cook/repose_downloader.rb +349 -0
  154. data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
  155. data/lib/instance/cook.rb +41 -0
  156. data/lib/instance/downloader.rb +208 -0
  157. data/lib/instance/duplicable.rb +67 -0
  158. data/lib/instance/exceptions.rb +49 -0
  159. data/lib/instance/executable_sequence_proxy.rb +278 -0
  160. data/lib/instance/instance_commands.rb +577 -0
  161. data/lib/instance/instance_state.rb +633 -0
  162. data/lib/instance/json_utilities.rb +102 -0
  163. data/lib/instance/login_manager.rb +533 -0
  164. data/lib/instance/login_user_manager.rb +522 -0
  165. data/lib/instance/message_encoder.rb +118 -0
  166. data/lib/instance/multi_thread_bundle_queue.rb +232 -0
  167. data/lib/instance/operation_context.rb +60 -0
  168. data/lib/instance/options_bag.rb +65 -0
  169. data/lib/instance/payload_formatter.rb +46 -0
  170. data/lib/instance/policy.rb +53 -0
  171. data/lib/instance/policy_audit.rb +100 -0
  172. data/lib/instance/policy_manager.rb +146 -0
  173. data/lib/instance/reenroll_manager.rb +104 -0
  174. data/lib/instance/right_scripts_cookbook.rb +181 -0
  175. data/lib/instance/shutdown_request.rb +221 -0
  176. data/lib/instance/single_thread_bundle_queue.rb +189 -0
  177. data/lib/instance/volume_management.rb +450 -0
  178. data/lib/instance.rb +50 -0
  179. data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
  180. data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
  181. data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
  182. data/lib/repo_conf_generators/rightscale_key.pub +17 -0
  183. data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
  184. data/lib/repo_conf_generators.rb +30 -0
  185. data/lib/run_shell.rb +28 -0
  186. data/scripts/agent_checker.rb +571 -0
  187. data/scripts/agent_controller.rb +247 -0
  188. data/scripts/agent_deployer.rb +148 -0
  189. data/scripts/bundle_runner.rb +336 -0
  190. data/scripts/cloud_controller.rb +176 -0
  191. data/scripts/log_level_manager.rb +142 -0
  192. data/scripts/ohai_runner.rb +33 -0
  193. data/scripts/reenroller.rb +193 -0
  194. data/scripts/server_importer.rb +293 -0
  195. data/scripts/shutdown_client.rb +183 -0
  196. data/scripts/system_configurator.rb +367 -0
  197. data/scripts/tagger.rb +381 -0
  198. data/scripts/thunker.rb +356 -0
  199. metadata +418 -0
@@ -0,0 +1,356 @@
1
+ # === Synopsis:
2
+ # RightScale Thunker (rs_thunk) - (c) 2011 RightScale Inc
3
+ #
4
+ # Thunker allows you to manage custom SSH logins for non root users. It uses the rightscale
5
+ # user and group RightScale to give privileges for authorization, managing the instance
6
+ # under individual users' profiles. It also downloads profile tarballs containing e.g.
7
+ # bash config.
8
+ #
9
+ ## === Usage
10
+ # rs_thunk --username USERNAME --email EMAIL [--profile DATA] [--force]
11
+ #
12
+ # === Options:
13
+ # --uuid, -i UUID Integer UUID for this user, obtained from RightScale
14
+ # --username, -u USERNAME Local Unix account name for this user
15
+ # --email, -e EMAIL Create audit entry saying "EMAIL logged in as USERNAME"
16
+ # --profile, -p DATA Extra profile data (e.g. a URL to download)
17
+ # --superuser, -s Create account with superuser privilege
18
+ # --force, -f If profile option was specified - rewrite existing files
19
+ # --help: Display help
20
+ # --version: Display version information
21
+ #
22
+ # === Examples:
23
+ # Authorize as 'alice' with UUID 12345 and email address alice@example.com:
24
+ # rs_thunk -i 12345 -u alice -e alice@example.com
25
+ #
26
+ require 'rubygems'
27
+ require 'trollop'
28
+ require 'shellwords'
29
+ require 'right_agent'
30
+ require 'right_agent/scripts/usage'
31
+ require 'right_agent/scripts/common_parser'
32
+ require 'right_agent/core_payload_types'
33
+ require 'right_support/net'
34
+
35
+ basedir = File.expand_path('../..', __FILE__)
36
+ require File.join(basedir, 'lib', 'instance')
37
+
38
+ module RightScale
39
+
40
+ class Thunker
41
+ SCP_COMMAND = %r{^[A-Za-z0-9_/]*scp}
42
+ SFTP_COMMAND = %r{^[A-Za-z0-9_/]*sftp-server}
43
+ AUDIT_REQUEST_TIMEOUT = 15 # best-effort auditing, but try not to block user
44
+ MOTD = '/etc/motd'
45
+
46
+ # Manage individual user SSH logins
47
+ #
48
+ # === Parameters
49
+ # options(Hash):: Hash of options as defined in +parse_args+
50
+ #
51
+ # === Return
52
+ # true:: Always return true
53
+ def run(options)
54
+ @log_sink = StringIO.new
55
+ @log = Logger.new(@log_sink)
56
+ RightScale::Log.force_logger(@log)
57
+
58
+ username = options.delete(:username)
59
+ email = options.delete(:email)
60
+ uuid = options.delete(:uuid)
61
+ superuser = options.delete(:superuser)
62
+ profile = options.delete(:profile)
63
+ force = options.delete(:force)
64
+
65
+ fail(1) if missing_argument(username, "USERNAME") || missing_argument(email, "EMAIL") || missing_argument(uuid, "UUID")
66
+
67
+ # Fetch some information about the client's intentions and origin
68
+ orig = ENV['SSH2_ORIGINAL_COMMAND'] || ENV['SSH_ORIGINAL_COMMAND']
69
+ client_ip = ENV['SSH_CLIENT'].split(/\s+/).first if ENV.has_key?('SSH_CLIENT')
70
+
71
+
72
+ if orig =~ SCP_COMMAND
73
+ access = :scp
74
+ elsif orig =~ SFTP_COMMAND
75
+ access = :sftp
76
+ elsif (orig != nil) && (!orig.empty?)
77
+ access = :command
78
+ else
79
+ access = :shell
80
+ end
81
+
82
+ # Create user just-in-time; idempotent if user already exists
83
+ # Note that username == chosen here, they just get used in two different contexts
84
+ username = LoginUserManager.create_user(username, uuid, superuser ? true : false) do |chosen|
85
+ if :shell == access
86
+ puts "Creating your user profile (#{chosen}) on this machine."
87
+ end
88
+ end
89
+
90
+ create_audit_entry(email, username, access, orig, client_ip)
91
+ chown_tty(username)
92
+ create_profile(access, username, profile, force) if profile
93
+
94
+ # Note that when execing sudo we use the N-argument form of Kernel.exec,
95
+ # which does not invoke a shell, but rather directly invokes the command specified
96
+ # by argv[0] and uses argv[1..N] as the command line. This protects us against shell
97
+ # escape characters and other badness.
98
+ #
99
+ # Unfortunately, this means that file globs and other 'useful' shell escape characters
100
+ # do not get parsed.
101
+ #
102
+ # As a workaround, for non-interactive access types, we tell sudo to invoke a shell and
103
+ # use the shell's '-c' argument to specify the command to run. We also use the -H
104
+ # argument to sudo, which forces it to set HOME to the user's homedir. We attempt to
105
+ # set some other environment variables to make the user feel more at home, but we
106
+ # are at the mercy of sudo.
107
+ #
108
+ # For interactive logins, we don't need to perform any trickiness since our goal is
109
+ # simply to get the user into a shell, with no command line args to parse.
110
+ case access
111
+ when :scp, :sftp, :command
112
+ LoginUserManager.simulate_login(username)
113
+ Kernel.exec('sudo', '-H', '-u', username, '/bin/sh', '-c', "cd $HOME ; #{orig}")
114
+ when :shell
115
+ display_motd
116
+ Kernel.exec('sudo', '-i', '-u', username)
117
+ end
118
+ rescue SystemExit => e
119
+ raise e
120
+ rescue Exception => e
121
+ fail(e)
122
+ end
123
+
124
+ # Create options hash from command line arguments
125
+ #
126
+ # === Return
127
+ # options(Hash):: Hash of options as defined by the command line
128
+ def parse_args
129
+ parser = Trollop::Parser.new do
130
+ opt :username, "", :type => :string
131
+ opt :email, "", :type => :string
132
+ opt :uuid, "", :type => :string, :short => "-i"
133
+ opt :superuser
134
+ opt :profile, "", :type => :string
135
+ opt :force
136
+ version ""
137
+ end
138
+
139
+ begin
140
+ parser.parse
141
+ rescue Trollop::VersionNeeded
142
+ puts version
143
+ succeed
144
+ rescue Trollop::HelpNeeded
145
+ puts Usage.scan(__FILE__)
146
+ succeed
147
+ rescue Trollop::CommandlineError => e
148
+ STDERR.puts e.message + "\nUse rs_thunk --help for additional information"
149
+ fail(1)
150
+ rescue SystemExit => e
151
+ raise e
152
+ end
153
+ end
154
+
155
+ protected
156
+
157
+ # Checks if argument is missing; shows error message
158
+ #
159
+ # === Parameters
160
+ # parameter(String):: parameter
161
+ # name(String):: parameter's name
162
+ #
163
+ # == Return
164
+ # missing(Boolean):: true if parameter is missing
165
+ def missing_argument(parameter, name)
166
+ unless parameter
167
+ STDERR.puts "Missing argument #{name}, rs_thunk --help for additional information"
168
+ return true
169
+ end
170
+
171
+ return false
172
+ end
173
+
174
+ # Exit with success.
175
+ #
176
+ # === Return
177
+ # R.I.P. does not return
178
+ def succeed
179
+ exit(0)
180
+ end
181
+
182
+ # Print error on console and exit abnormally
183
+ #
184
+ # === Parameters
185
+ # msg(String):: Error message, default to nil (no message printed)
186
+ # print_usage(Boolean):: Whether script usage should be printed, default to false
187
+ #
188
+ # === Return
189
+ # R.I.P. does not return
190
+ def fail(reason=nil, options={})
191
+ case reason
192
+ when Errno::EACCES
193
+ STDERR.puts reason.message
194
+ STDERR.puts "Try elevating privilege (sudo/runas) before invoking this command."
195
+ code = 2
196
+ when Exception
197
+ STDOUT.puts "Unexpected #{reason.class.name}: #{reason.message}"
198
+ STDOUT.puts "We apologize for the inconvenience. You may try connecting as root"
199
+ STDOUT.puts "to work around this problem, if you have sufficient privilege."
200
+ STDERR.puts
201
+ STDERR.puts("Debugging information:")
202
+ STDERR.puts(@log_sink.string)
203
+ code = 50
204
+ when String
205
+ STDOUT.puts reason
206
+ code = 50
207
+ when Integer
208
+ code = reason
209
+ else
210
+ code = 50
211
+ end
212
+
213
+ puts Usage.scan(__FILE__) if options[:print_usage]
214
+ exit(code)
215
+ end
216
+
217
+ # Create an audit entry to record this user's access. The entry is created
218
+ # asynchronously and this method never raises exceptions even if the
219
+ # request fails or times out. Thus, this is "best-effort" auditing and
220
+ # should not be relied upon!
221
+ #
222
+ # === Parameters
223
+ # email(String):: the user's email address
224
+ # username(String):: the user's email address
225
+ # access(Symbol):: mode of access; one of :scp, :sftp, :command or :shell
226
+ # command(String):: exact command that is being executed via SSH
227
+ # client_ip(String):: origin IP address
228
+ #
229
+ # === Return
230
+ # Returns true on success, false otherwise
231
+ def create_audit_entry(email, username, access, command, client_ip=nil)
232
+ config_options = AgentConfig.agent_options('instance')
233
+ listen_port = config_options[:listen_port]
234
+ raise ArgumentError.new('Could not retrieve agent listen port') unless listen_port
235
+ client = CommandClient.new(listen_port, config_options[:cookie])
236
+
237
+ begin
238
+ hostname = `hostname`.strip
239
+ rescue Exception => e
240
+ hostname = 'localhost'
241
+ end
242
+
243
+ case access
244
+ when :scp then
245
+ summary = 'SSH file copy'
246
+ detail = "User copied files copied (scp) to/from host."
247
+ when :sftp then
248
+ summary = 'SSH interactive file transfer'
249
+ detail = "User initiated an SFTP session."
250
+ when :command
251
+ summary = 'SSH command'
252
+ detail = "User invoked an interactive program."
253
+ when :shell
254
+ summary = 'SSH interactive login'
255
+ detail = "User connected and invoked a login shell."
256
+ end
257
+
258
+ detail += "\nLogin: #{username}@#{hostname}" if username
259
+ detail += "\nClient IP: #{client_ip}" if client_ip
260
+ detail += "\nCommand: #{command}" if command
261
+
262
+ log_detail = detail.gsub("\n", '; ')
263
+ Log.info("#{summary} - #{log_detail}")
264
+
265
+ options = {
266
+ :name => 'audit_create_entry',
267
+ :user_email => email,
268
+ :summary => summary,
269
+ :detail => detail,
270
+ :category => RightScale::EventCategories::CATEGORY_SECURITY
271
+ }
272
+ client.send_command(options, false, AUDIT_REQUEST_TIMEOUT)
273
+
274
+ true
275
+ rescue Exception => e
276
+ Log.error("#{e.class.name}:#{e.message}")
277
+ Log.error(e.backtrace.join("\n"))
278
+ false
279
+ end
280
+
281
+ # Download an archive from given path; extracts files and moves
282
+ # them to username's home directory.
283
+ #
284
+ # === Parameters
285
+ # username(String):: account's username
286
+ # custom_data(String):: custom data, e.g. personal tarball URL
287
+ # force(Boolean):: rewrite existing files if true; otherwise skip them
288
+ #
289
+ # === Return
290
+ # extracted(Boolean):: true if profile downloaded and copied; false
291
+ # if profile has been created earlier or error occured
292
+ def create_profile(access, username, custom_data, force = false)
293
+ home_dir = Etc.getpwnam(username).dir
294
+
295
+ LoginUserManager.setup_profile(username, home_dir, custom_data, force) do |msg|
296
+ puts msg if [:command, :shell].include?(access)
297
+ end
298
+ end
299
+
300
+ # Display the Message of the Day if it exists.
301
+ def display_motd
302
+ if File.exist?(MOTD)
303
+ puts File.read(MOTD)
304
+ end
305
+ rescue Exception => e
306
+ # no-op.
307
+ end
308
+
309
+ # Ensure the user's PTY/TTY will be owned by him once we thunk through to his account.
310
+ # This helps apps like screen/tmux work better.
311
+ def chown_tty(username)
312
+ tty = `tty 2> /dev/null`.chomp
313
+ @log.error("'tty' command failed") unless $?.success?
314
+
315
+ if File.exists?(tty)
316
+ %x(sudo chown #{Shellwords.escape(username)} #{Shellwords.escape(tty)})
317
+ raise RuntimeError, "Failed to change ownership of #{tty}" unless $?.success?
318
+ else
319
+ @log.error("'tty' command did not give a reasonable answer: #{tty}")
320
+ end
321
+ end
322
+
323
+ # Version information
324
+ #
325
+ # === Return
326
+ # (String):: Version information
327
+ def version
328
+ gemspec = eval(File.read(File.join(File.dirname(__FILE__), '..', 'right_link.gemspec')))
329
+ "rs_thunk #{gemspec.version} - RightLink's thunker (c) 2011 RightScale"
330
+ end
331
+
332
+ end # Thunker
333
+
334
+ end # RightScale
335
+
336
+ #
337
+ # Copyright (c) 2011 RightScale Inc
338
+ #
339
+ # Permission is hereby granted, free of charge, to any person obtaining
340
+ # a copy of this software and associated documentation files (the
341
+ # "Software"), to deal in the Software without restriction, including
342
+ # without limitation the rights to use, copy, modify, merge, publish,
343
+ # distribute, sublicense, and/or sell copies of the Software, and to
344
+ # permit persons to whom the Software is furnished to do so, subject to
345
+ # the following conditions:
346
+ #
347
+ # The above copyright notice and this permission notice shall be
348
+ # included in all copies or substantial portions of the Software.
349
+ #
350
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
351
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
352
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
353
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
354
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
355
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
356
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.