CloudyScripts 0.0.8 → 0.0.9

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.
@@ -1,191 +1,195 @@
1
- require "help/script_execution_state"
2
- require "scripts/ec2/ec2_script"
3
- require "help/remote_command_handler"
4
- require "help/dm_crypt_helper"
5
- require "AWS"
6
-
7
- # Script to Encrypt an EC2 Storage (aka Elastic Block Storage)
8
- #
9
- class DmEncrypt < Ec2Script
10
- # dependencies: tools that need to be installed to make things work
11
- TOOLS = ["cryptsetup","lvm"]
12
-
13
- # Input parameters
14
- # * aws_access_key => the Amazon AWS Access Key (see Your Account -> Security Credentials)
15
- # * aws_secret_key => the Amazon AWS Secret Key
16
- # * ip_address => IP Address of the machine to connect to
17
- # * ssh_key_file => Path of the keyfile used to connect to the machine (optional, otherwise: ssh_key_data)
18
- # * ssh_key_data => Key information (optional, otherwise: ssh_key_file)
19
- # * device => Path of the device to encrypt
20
- # * device_name => Name of the Device to encrypt
21
- # * storage_path => Path on which the encrypted device is mounted
22
- # * paraphrase => paraphrase used for encryption
23
- # * remote_command_handler => object that allows to connect via ssh and execute commands (optional)
24
- # * ec2_api_handler => object that allows to access the EC2 API (optional)
25
- # * ec2_api_server => server to connect to (option, default is us-east-1.ec2.amazonaws.com)
26
- #
27
-
28
- def initialize(input_params)
29
- super(input_params)
30
- end
31
-
32
- # Executes the script.
33
- def start_script
34
- begin
35
- # optional parameters and initialization
36
- if @input_params[:ec2_api_server] == nil
37
- @input_params[:ec2_api_server] = "us-east-1.ec2.amazonaws.com"
38
- end
39
- if @input_params[:remote_command_handler] == nil
40
- @input_params[:remote_command_handler] = RemoteCommandHandler.new
41
- end
42
- if @input_params[:ec2_api_handler] == nil
43
- @input_params[:ec2_api_handler] = AWS::EC2::Base.new(:access_key_id => @input_params[:aws_access_key],
44
- :secret_access_key => @input_params[:aws_secret_key], :server => @input_params[:ec2_api_server])
45
- end
46
- # start state machine
47
- current_state = DmEncryptState.load_state(@input_params)
48
- @state_change_listeners.each() {|listener|
49
- current_state.register_state_change_listener(listener)
50
- }
51
- end_state = current_state.start_state_machine()
52
- if end_state.failed?
53
- @result[:failed] = true
54
- @result[:failure_reason] = current_state.end_state.failure_reason
55
- @result[:end_state] = current_state.end_state
56
- else
57
- @result[:failed] = false
58
- end
59
- rescue Exception => e
60
- @logger.warn "exception during encryption: #{e}"
61
- @logger.info e.backtrace.join("\n")
62
- err = e.to_s
63
- err += " (in #{current_state.end_state.to_s})" unless current_state == nil
64
- @result[:failed] = true
65
- @result[:failure_reason] = err
66
- @result[:end_state] = current_state.end_state unless current_state == nil
67
- ensure
68
- begin
69
- @input_params[:remote_command_handler].disconnect
70
- rescue Exception => e2
71
- end
72
- end
73
-
74
- #
75
- @result[:done] = true
76
- end
77
-
78
- # Returns a hash with the following information:
79
- # :done => if execution is done
80
- #
81
- def get_execution_result
82
- @result
83
- end
84
-
85
- private
86
-
87
- # Here begins the state machine implementation
88
- class DmEncryptState < ScriptExecutionState
89
-
90
- def self.load_state(context)
91
- InitialState.new(context)
92
- end
93
- end
94
-
95
- # Starting state. Tries to connect via ssh.
96
- class InitialState < DmEncryptState
97
- def enter
98
- connect()
99
- end
100
-
101
- private
102
-
103
- def connect()
104
- @logger.debug "InitialState.connect"
105
- if @context[:ssh_key_file] != nil
106
- @context[:remote_command_handler].connect_with_keyfile(@context[:ip_address], @context[:ssh_key_file])
107
- elsif @context[:ssh_key_data] != nil
108
- @context[:remote_command_handler].connect(@context[:ip_address], "root", @context[:ssh_key_data])
109
- else
110
- raise Exception.new("no key information specified")
111
- end
112
- @context[:result][:os] = @context[:remote_command_handler].retrieve_os()
113
- ConnectedState.new(@context)
114
- end
115
- end
116
-
117
- # Connected via SSH. Tries to install dm-encrypt.#TODO: depends on OS
118
- class ConnectedState < DmEncryptState
119
- def enter
120
- install_tools()
121
- end
122
-
123
- private
124
- def install_tools
125
- @logger.debug "ConnectedState.install_tools"
126
- if !tools_installed?
127
- TOOLS.each() {|tool|
128
- @context[:remote_command_handler].install(tool)
129
- }
130
- end
131
- if tools_installed?
132
- @logger.debug "system says that tools are installed"
133
- ToolInstalledState.new(@context)
134
- else
135
- FailedState.new(@context, "Installation of Tools failed", ConnectedState.new(@context))
136
- end
137
- end
138
-
139
- def tools_installed?
140
- TOOLS.each() {|tool|
141
- if !@context[:remote_command_handler].tools_installed?(tool)
142
- return false
143
- end
144
- }
145
- true
146
- end
147
- end
148
-
149
- # Connected and Tools installed. Start encryption.
150
- class ToolInstalledState < DmEncryptState
151
- def enter
152
- create_encrypted_volume()
153
- end
154
-
155
- private
156
- def create_encrypted_volume
157
- @logger.debug "ToolInstalledState.create_encrypted_volume"
158
- @context[:remote_command_handler].encrypt_storage(@context[:device_name],
159
- @context[:paraphrase], @context[:device], @context[:storage_path])
160
- MountedAndActivatedState.new(@context)
161
- end
162
-
163
- def calc_device_name
164
- dev = @context[:device_name].gsub(/[-]/,"--")
165
- "/dev/mapper/vg--#{dev}-lv--#{dev}"
166
- end
167
-
168
- end
169
-
170
- # The encrypted storages is mounted and activated. Cleanup and done.
171
- class MountedAndActivatedState < DmEncryptState
172
- def enter
173
- cleanup()
174
- end
175
-
176
- private
177
- def cleanup()
178
- @logger.debug "MountedAndActivatedState.cleanup"
179
- @context[:remote_command_handler].disconnect()
180
- DoneState.new(@context)
181
- end
182
-
183
- end
184
-
185
- class DoneState < DmEncryptState
186
- def done?
187
- true
188
- end
189
- end
190
-
1
+ require "help/script_execution_state"
2
+ require "scripts/ec2/ec2_script"
3
+ require "help/remote_command_handler"
4
+ require "help/dm_crypt_helper"
5
+ require "AWS"
6
+
7
+ # Script to Encrypt an EC2 Storage (aka Elastic Block Storage)
8
+ #
9
+ class DmEncrypt < Ec2Script
10
+ # dependencies: tools that need to be installed to make things work
11
+ TOOLS = ["cryptsetup"]
12
+ # the parameters for which
13
+ CHECK = ["cryptsetup"]
14
+
15
+ # Input parameters
16
+ # * aws_access_key => the Amazon AWS Access Key (see Your Account -> Security Credentials)
17
+ # * aws_secret_key => the Amazon AWS Secret Key
18
+ # * ip_address => IP Address of the machine to connect to
19
+ # * ssh_key_file => Path of the keyfile used to connect to the machine (optional, otherwise: ssh_key_data)
20
+ # * ssh_key_data => Key information (optional, otherwise: ssh_key_file)
21
+ # * device => Path of the device to encrypt
22
+ # * device_name => Name of the Device to encrypt
23
+ # * storage_path => Path on which the encrypted device is mounted
24
+ # * paraphrase => paraphrase used for encryption
25
+ # * remote_command_handler => object that allows to connect via ssh and execute commands (optional)
26
+ # * ec2_api_handler => object that allows to access the EC2 API (optional)
27
+ # * ec2_api_server => server to connect to (option, default is us-east-1.ec2.amazonaws.com)
28
+ #
29
+
30
+ def initialize(input_params)
31
+ super(input_params)
32
+ end
33
+
34
+ # Executes the script.
35
+ def start_script
36
+ begin
37
+ # optional parameters and initialization
38
+ if @input_params[:ec2_api_server] == nil
39
+ @input_params[:ec2_api_server] = "us-east-1.ec2.amazonaws.com"
40
+ end
41
+ if @input_params[:remote_command_handler] == nil
42
+ @input_params[:remote_command_handler] = RemoteCommandHandler.new
43
+ end
44
+ if @input_params[:ec2_api_handler] == nil
45
+ @input_params[:ec2_api_handler] = AWS::EC2::Base.new(:access_key_id => @input_params[:aws_access_key],
46
+ :secret_access_key => @input_params[:aws_secret_key], :server => @input_params[:ec2_api_server])
47
+ end
48
+ # start state machine
49
+ current_state = DmEncryptState.load_state(@input_params)
50
+ @state_change_listeners.each() {|listener|
51
+ current_state.register_state_change_listener(listener)
52
+ }
53
+ end_state = current_state.start_state_machine()
54
+ if end_state.failed?
55
+ @result[:failed] = true
56
+ @result[:failure_reason] = current_state.end_state.failure_reason
57
+ @result[:end_state] = current_state.end_state
58
+ else
59
+ @result[:failed] = false
60
+ end
61
+ rescue Exception => e
62
+ @logger.warn "exception during encryption: #{e}"
63
+ @logger.info e.backtrace.join("\n")
64
+ err = e.to_s
65
+ err += " (in #{current_state.end_state.to_s})" unless current_state == nil
66
+ @result[:failed] = true
67
+ @result[:failure_reason] = err
68
+ @result[:end_state] = current_state.end_state unless current_state == nil
69
+ ensure
70
+ begin
71
+ @input_params[:remote_command_handler].disconnect
72
+ rescue Exception => e2
73
+ end
74
+ end
75
+ #
76
+ @result[:done] = true
77
+ end
78
+
79
+ # Returns a hash with the following information:
80
+ # :done => if execution is done
81
+ #
82
+ def get_execution_result
83
+ @result
84
+ end
85
+
86
+ private
87
+
88
+ # Here begins the state machine implementation
89
+ class DmEncryptState < ScriptExecutionState
90
+
91
+ def self.load_state(context)
92
+ InitialState.new(context)
93
+ end
94
+ end
95
+
96
+ # Starting state. Tries to connect via ssh.
97
+ class InitialState < DmEncryptState
98
+ def enter
99
+ connect()
100
+ end
101
+
102
+ private
103
+
104
+ def connect()
105
+ @logger.debug "InitialState.connect"
106
+ if @context[:ssh_key_file] != nil
107
+ @context[:remote_command_handler].connect_with_keyfile(@context[:ip_address], @context[:ssh_key_file])
108
+ elsif @context[:ssh_key_data] != nil
109
+ @context[:remote_command_handler].connect(@context[:ip_address], "root", @context[:ssh_key_data])
110
+ else
111
+ raise Exception.new("no key information specified")
112
+ end
113
+ @context[:result][:os] = @context[:remote_command_handler].retrieve_os()
114
+ ConnectedState.new(@context)
115
+ end
116
+ end
117
+
118
+ # Connected via SSH. Tries to install dm-encrypt.#TODO: depends on OS
119
+ class ConnectedState < DmEncryptState
120
+ def enter
121
+ install_tools()
122
+ end
123
+
124
+ private
125
+ def install_tools
126
+ @logger.debug "ConnectedState.install_tools"
127
+ if !tools_installed?
128
+ TOOLS.each() {|tool|
129
+ @context[:remote_command_handler].install(tool)
130
+ }
131
+ end
132
+ if !@context[:remote_command_handler].remote_execute("modprobe dm_crypt")
133
+ raise Exception.new("dm-crypt module missing")
134
+ end
135
+ if tools_installed?
136
+ @logger.debug "system says that tools are installed"
137
+ ToolInstalledState.new(@context)
138
+ else
139
+ FailedState.new(@context, "Installation of Tools failed", ConnectedState.new(@context))
140
+ end
141
+ end
142
+
143
+ def tools_installed?
144
+ CHECK.each() {|tool|
145
+ if !@context[:remote_command_handler].tools_installed?(tool)
146
+ return false
147
+ end
148
+ }
149
+ true
150
+ end
151
+ end
152
+
153
+ # Connected and Tools installed. Start encryption.
154
+ class ToolInstalledState < DmEncryptState
155
+ def enter
156
+ create_encrypted_volume()
157
+ end
158
+
159
+ private
160
+ def create_encrypted_volume
161
+ @logger.debug "ToolInstalledState.create_encrypted_volume"
162
+ @context[:remote_command_handler].encrypt_storage(@context[:device_name],
163
+ @context[:paraphrase], @context[:device], @context[:storage_path])
164
+ MountedAndActivatedState.new(@context)
165
+ end
166
+
167
+ def calc_device_name
168
+ dev = @context[:device_name].gsub(/[-]/,"--")
169
+ "/dev/mapper/vg--#{dev}-lv--#{dev}"
170
+ end
171
+
172
+ end
173
+
174
+ # The encrypted storages is mounted and activated. Cleanup and done.
175
+ class MountedAndActivatedState < DmEncryptState
176
+ def enter
177
+ cleanup()
178
+ end
179
+
180
+ private
181
+ def cleanup()
182
+ @logger.debug "MountedAndActivatedState.cleanup"
183
+ @context[:remote_command_handler].disconnect()
184
+ DoneState.new(@context)
185
+ end
186
+
187
+ end
188
+
189
+ class DoneState < DmEncryptState
190
+ def done?
191
+ true
192
+ end
193
+ end
194
+
191
195
  end
@@ -1,41 +1,41 @@
1
- # Base class for any script on EC2.
2
- class Ec2Script
3
- # Initialization. Common Input parameters:
4
- # * aws_access_key => the Amazon AWS Access Key (see Your Account -> Security Credentials)
5
- # * aws_secret_key => the Amazon AWS Secret Key
6
- # * ec2_api_server => the API Server to connect to (optional, default is us-east-1 (=> <ec2_api_server>.ec2.amazonaws.com)
7
- # * logger => allows to pass a ruby logger object used for logging (optional, default is a stdout logger with level WARN)
8
- # Scripts may add specific key/value pairs.
9
- def initialize(input_params)
10
- @input_params = input_params
11
- @state_change_listeners = []
12
- if input_params[:logger] == nil
13
- @logger = Logger.new(STDOUT)
14
- @logger .level = Logger::WARN
15
- input_params[:logger] = @logger
16
- end
17
- @result = {:done => false}
18
- @input_params[:result] = @result
19
- end
20
-
21
- def register_state_change_listener(listener)
22
- @state_change_listeners << listener
23
- end
24
-
25
- def start_script
26
- raise Exception.new("must be implemented")
27
- end
28
-
29
- # Return a hash of results. Common values are:
30
- # * :done => is true when the script has terminated, otherwise false
31
- # * :failed => is false when the script succeeded
32
- # * :failure_reason => returns a failure reason (string)
33
- # * :end_state => returns the state, in which the script terminated (#Help::ScriptExecutionState)
34
- # Scripts may add specific key/value pairs.
35
- # *
36
- def get_execution_result
37
- raise Exception.new("must be implemented")
38
- end
39
-
40
- end
41
-
1
+ # Base class for any script on EC2.
2
+ class Ec2Script
3
+ # Initialization. Common Input parameters:
4
+ # * aws_access_key => the Amazon AWS Access Key (see Your Account -> Security Credentials)
5
+ # * aws_secret_key => the Amazon AWS Secret Key
6
+ # * ec2_api_server => the API Server to connect to (optional, default is us-east-1 (=> <ec2_api_server>.ec2.amazonaws.com)
7
+ # * logger => allows to pass a ruby logger object used for logging (optional, default is a stdout logger with level WARN)
8
+ # Scripts may add specific key/value pairs.
9
+ def initialize(input_params)
10
+ @input_params = input_params
11
+ @state_change_listeners = []
12
+ if input_params[:logger] == nil
13
+ @logger = Logger.new(STDOUT)
14
+ @logger .level = Logger::WARN
15
+ input_params[:logger] = @logger
16
+ end
17
+ @result = {:done => false, :failed => false}
18
+ @input_params[:result] = @result
19
+ end
20
+
21
+ def register_state_change_listener(listener)
22
+ @state_change_listeners << listener
23
+ end
24
+
25
+ def start_script
26
+ raise Exception.new("must be implemented")
27
+ end
28
+
29
+ # Return a hash of results. Common values are:
30
+ # * :done => is true when the script has terminated, otherwise false
31
+ # * :failed => is false when the script succeeded
32
+ # * :failure_reason => returns a failure reason (string)
33
+ # * :end_state => returns the state, in which the script terminated (#Help::ScriptExecutionState)
34
+ # Scripts may add specific key/value pairs.
35
+ # *
36
+ def get_execution_result
37
+ raise Exception.new("must be implemented")
38
+ end
39
+
40
+ end
41
+