aws-codedeploy-agent 0.0.1
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.
- data/.gitignore +2 -0
- data/CHANGES.md +3 -0
- data/Gemfile +13 -0
- data/LICENSE +177 -0
- data/NOTICE +2 -0
- data/README.md +16 -0
- data/aws-codedeploy-agent.gemspec +39 -0
- data/bin/codedeploy-agent +78 -0
- data/bin/codedeploy-install +15 -0
- data/bin/codedeploy-uninstall +13 -0
- data/certs/host-agent-deployment-signer-ca-chain.pem +76 -0
- data/conf/codedeployagent.yml +9 -0
- data/init.d/codedeploy-agent +61 -0
- data/lib/core_ext.rb +71 -0
- data/lib/instance_agent.rb +35 -0
- data/lib/instance_agent/agent/base.rb +34 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/ace_info.rb +133 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/acl_info.rb +163 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/application_specification.rb +142 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/context_info.rb +23 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/file_info.rb +23 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/linux_permission_info.rb +121 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/mode_info.rb +66 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/range_info.rb +134 -0
- data/lib/instance_agent/codedeploy_plugin/application_specification/script_info.rb +27 -0
- data/lib/instance_agent/codedeploy_plugin/codedeploy_control.rb +72 -0
- data/lib/instance_agent/codedeploy_plugin/command_executor.rb +357 -0
- data/lib/instance_agent/codedeploy_plugin/command_poller.rb +146 -0
- data/lib/instance_agent/codedeploy_plugin/deployment_specification.rb +150 -0
- data/lib/instance_agent/codedeploy_plugin/hook_executor.rb +206 -0
- data/lib/instance_agent/codedeploy_plugin/install_instruction.rb +374 -0
- data/lib/instance_agent/codedeploy_plugin/installer.rb +143 -0
- data/lib/instance_agent/codedeploy_plugin/request_helper.rb +28 -0
- data/lib/instance_agent/config.rb +43 -0
- data/lib/instance_agent/log.rb +3 -0
- data/lib/instance_agent/platform.rb +17 -0
- data/lib/instance_agent/platform/linux_util.rb +57 -0
- data/lib/instance_agent/runner/child.rb +57 -0
- data/lib/instance_agent/runner/master.rb +103 -0
- data/lib/instance_metadata.rb +47 -0
- data/test/certificate_helper.rb +120 -0
- data/test/helpers/instance_agent_helper.rb +25 -0
- data/test/instance_agent/agent/base_test.rb +49 -0
- data/test/instance_agent/codedeploy_plugin/application_specification_test.rb +1710 -0
- data/test/instance_agent/codedeploy_plugin/codedeploy_control_test.rb +51 -0
- data/test/instance_agent/codedeploy_plugin/command_executor_test.rb +513 -0
- data/test/instance_agent/codedeploy_plugin/command_poller_test.rb +459 -0
- data/test/instance_agent/codedeploy_plugin/deployment_specification_test.rb +335 -0
- data/test/instance_agent/codedeploy_plugin/hook_executor_test.rb +250 -0
- data/test/instance_agent/codedeploy_plugin/install_instruction_test.rb +566 -0
- data/test/instance_agent/codedeploy_plugin/installer_test.rb +519 -0
- data/test/instance_agent/codedeploy_plugin/request_helper_test.rb +37 -0
- data/test/instance_agent/config_test.rb +64 -0
- data/test/instance_agent/runner/child_test.rb +87 -0
- data/test/instance_metadata_test.rb +97 -0
- data/test/test_helper.rb +16 -0
- data/vendor/gems/.codedeploy-commands-1.0.0.created.rid +1 -0
- data/vendor/gems/codedeploy-commands/apis/CodeDeployCommand.api.json +372 -0
- data/vendor/gems/codedeploy-commands/codedeploy-commands-1.0.0.gemspec +28 -0
- data/vendor/gems/codedeploy-commands/lib/aws/codedeploy_commands.rb +18 -0
- data/vendor/gems/codedeploy-commands/lib/aws/plugins/certificate_authority.rb +12 -0
- data/vendor/gems/codedeploy-commands/lib/aws/plugins/deploy_control_endpoint.rb +22 -0
- data/vendor/gems/process_manager/README.md +1 -0
- data/vendor/gems/process_manager/lib/blank.rb +153 -0
- data/vendor/gems/process_manager/lib/core_ext.rb +73 -0
- data/vendor/gems/process_manager/lib/process_manager.rb +49 -0
- data/vendor/gems/process_manager/lib/process_manager/child.rb +119 -0
- data/vendor/gems/process_manager/lib/process_manager/config.rb +112 -0
- data/vendor/gems/process_manager/lib/process_manager/log.rb +107 -0
- data/vendor/gems/process_manager/lib/process_manager/master.rb +322 -0
- data/vendor/gems/process_manager/process_manager-0.0.13.gemspec +42 -0
- data/vendor/specifications/aws-sdk-core-2.0.5.gemspec +39 -0
- data/vendor/specifications/builder-3.2.2.gemspec +29 -0
- data/vendor/specifications/codedeploy-commands-1.0.0.gemspec +28 -0
- data/vendor/specifications/gli-2.5.6.gemspec +51 -0
- data/vendor/specifications/jamespath-0.5.1.gemspec +35 -0
- data/vendor/specifications/little-plugger-1.1.3.gemspec +32 -0
- data/vendor/specifications/logging-1.8.1.gemspec +44 -0
- data/vendor/specifications/multi_json-1.7.7.gemspec +30 -0
- data/vendor/specifications/multi_json-1.8.4.gemspec +30 -0
- data/vendor/specifications/multi_xml-0.5.5.gemspec +30 -0
- data/vendor/specifications/process_manager-0.0.13.gemspec +42 -0
- data/vendor/specifications/simple_pid-0.2.1.gemspec +28 -0
- metadata +377 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'instance_metadata'
|
|
2
|
+
|
|
3
|
+
module InstanceAgent
|
|
4
|
+
module CodeDeployPlugin
|
|
5
|
+
class RequestHelper
|
|
6
|
+
|
|
7
|
+
def initialize(options = {})
|
|
8
|
+
@deploy_control_client = options[:deploy_control_client]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def verify_clients_configuration
|
|
12
|
+
errors = []
|
|
13
|
+
errors << "Invalid aws sdk security configuration" unless valid_aws_sdk_security_config?
|
|
14
|
+
errors << "Invalid server certificate" unless valid_server_certificate?
|
|
15
|
+
errors
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def valid_aws_sdk_security_config?
|
|
19
|
+
@deploy_control_client.ssl_verify_peer
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def valid_server_certificate?
|
|
23
|
+
@deploy_control_client.verify_cert_fields
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'process_manager/config'
|
|
3
|
+
|
|
4
|
+
module InstanceAgent
|
|
5
|
+
class Config < ProcessManager::Config
|
|
6
|
+
def self.init
|
|
7
|
+
@config = Config.new
|
|
8
|
+
ProcessManager::Config.instance_variable_set("@config", @config)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def validate
|
|
12
|
+
errors = super
|
|
13
|
+
validate_children(errors)
|
|
14
|
+
errors
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def initialize
|
|
18
|
+
super
|
|
19
|
+
@config.update({
|
|
20
|
+
:program_name => 'codedeploy-agent',
|
|
21
|
+
:wait_between_spawning_children => 1,
|
|
22
|
+
:log_dir => nil,
|
|
23
|
+
:pid_dir => nil,
|
|
24
|
+
:shared_dir => nil,
|
|
25
|
+
:user => nil,
|
|
26
|
+
:children => 1,
|
|
27
|
+
:http_read_timeout => 80,
|
|
28
|
+
:instance_service_region => nil,
|
|
29
|
+
:instance_service_endpoint => nil,
|
|
30
|
+
:instance_service_port => nil,
|
|
31
|
+
:wait_between_runs => 30,
|
|
32
|
+
:wait_after_error => 30,
|
|
33
|
+
:codedeploy_test_profile => 'prod'
|
|
34
|
+
})
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def validate_children(errors = [])
|
|
38
|
+
errors << 'children can only be set to 1' unless config[:children] == 1
|
|
39
|
+
errors
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module InstanceAgent
|
|
2
|
+
class LinuxUtil
|
|
3
|
+
def self.supported_versions()
|
|
4
|
+
[0.0]
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.supported_oses()
|
|
8
|
+
['linux']
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.prepare_script_command(script, absolute_path)
|
|
12
|
+
script_command = absolute_path
|
|
13
|
+
if(!script.runas.nil?)
|
|
14
|
+
script_command = 'su ' + script.runas + ' -c ' + absolute_path
|
|
15
|
+
end
|
|
16
|
+
script_command
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.script_executable?(path)
|
|
20
|
+
File.executable?(path)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.extract_tar(bundle_file, dst)
|
|
24
|
+
FileUtils.mkdir_p(dst)
|
|
25
|
+
execute_tar_command("/bin/tar -xpsf #{bundle_file} -C #{dst}")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.extract_tgz(bundle_file, dst)
|
|
29
|
+
FileUtils.mkdir_p(dst)
|
|
30
|
+
execute_tar_command("/bin/tar -zxpsf #{bundle_file} -C #{dst}")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
def self.execute_tar_command(cmd)
|
|
35
|
+
log(:debug, "Executing #{cmd}")
|
|
36
|
+
|
|
37
|
+
output = `#{cmd} 2>&1`
|
|
38
|
+
exit_status = $?.exitstatus
|
|
39
|
+
|
|
40
|
+
log(:debug, "Command status: #{$?}")
|
|
41
|
+
log(:debug, "Command output: #{output}")
|
|
42
|
+
|
|
43
|
+
if exit_status != 0
|
|
44
|
+
msg = "Error extracting tar archive: #{exit_status}"
|
|
45
|
+
log(:error, msg)
|
|
46
|
+
raise msg
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
def self.log(severity, message)
|
|
52
|
+
raise ArgumentError, "Unknown severity #{severity.inspect}" unless InstanceAgent::Log::SEVERITIES.include?(severity.to_s)
|
|
53
|
+
InstanceAgent::Log.send(severity.to_sym, "#{self.to_s}: #{message}")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'process_manager/child'
|
|
3
|
+
|
|
4
|
+
module InstanceAgent
|
|
5
|
+
module Runner
|
|
6
|
+
class Child < ProcessManager::Daemon::Child
|
|
7
|
+
AGENTS = {
|
|
8
|
+
0 => InstanceAgent::CodeDeployPlugin::CommandPoller
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
attr_accessor :runner
|
|
12
|
+
|
|
13
|
+
def prepare_run
|
|
14
|
+
validate_index
|
|
15
|
+
with_error_handling do
|
|
16
|
+
@runner = AGENTS[index].runner
|
|
17
|
+
ProcessManager.set_program_name(description)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def run
|
|
22
|
+
with_error_handling do
|
|
23
|
+
runner.run
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def description
|
|
28
|
+
if runner
|
|
29
|
+
"#{runner.description} of master #{master_pid.inspect}"
|
|
30
|
+
else
|
|
31
|
+
'booting child'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def validate_index
|
|
36
|
+
raise ArgumentError, "Invalid index #{index.inspect}: only 0-2 possible" unless AGENTS.keys.include?(index)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def with_error_handling
|
|
40
|
+
yield
|
|
41
|
+
rescue SocketError => e
|
|
42
|
+
ProcessManager::Log.info "#{description}: failed to run as the connection failed! #{e.class} - #{e.message} - #{e.backtrace.join("\n")}"
|
|
43
|
+
sleep ProcessManager::Config.config[:wait_after_connection_problem]
|
|
44
|
+
exit 1
|
|
45
|
+
rescue Exception => e
|
|
46
|
+
if (e.message.to_s.match(/throttle/i) || e.message.to_s.match(/rateexceeded/i) rescue false)
|
|
47
|
+
ProcessManager::Log.error "#{description}: ran into throttling - waiting for #{ProcessManager::Config.config[:wait_after_throttle_error]}s until retrying"
|
|
48
|
+
sleep ProcessManager::Config.config[:wait_after_throttle_error]
|
|
49
|
+
else
|
|
50
|
+
ProcessManager::Log.error "#{description}: error during start or run: #{e.class} - #{e.message} - #{e.backtrace.join("\n")}"
|
|
51
|
+
end
|
|
52
|
+
exit 1
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'process_manager/master'
|
|
3
|
+
require 'instance_agent/codedeploy_plugin/request_helper'
|
|
4
|
+
require 'instance_agent/codedeploy_plugin/codedeploy_control'
|
|
5
|
+
require 'instance_metadata'
|
|
6
|
+
|
|
7
|
+
module InstanceAgent
|
|
8
|
+
module Runner
|
|
9
|
+
class Master < ProcessManager::Daemon::Master
|
|
10
|
+
|
|
11
|
+
ChildTerminationMaxWaitTime = 80
|
|
12
|
+
|
|
13
|
+
def self.description(pid = $$)
|
|
14
|
+
"master #{pid}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.child_class
|
|
18
|
+
::InstanceAgent::Runner::Child
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.pid_description
|
|
22
|
+
ProcessManager::Config.config[:program_name]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def validate_ssl_config
|
|
26
|
+
if !InstanceMetadata.instance_id.blank?
|
|
27
|
+
region = InstanceMetadata.region
|
|
28
|
+
request_helper = InstanceAgent::CodeDeployPlugin::RequestHelper.new(:deploy_control_client => InstanceAgent::CodeDeployPlugin::CodeDeployControl.new(:region => region))
|
|
29
|
+
|
|
30
|
+
if (errors = request_helper.verify_clients_configuration)
|
|
31
|
+
errors.each{|error| ProcessManager::Log.error("Stopping CodeDeploy agent. " + error)}
|
|
32
|
+
end
|
|
33
|
+
self.class.abort unless errors.empty?
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.log_file
|
|
38
|
+
File.join(ProcessManager::Config.config[:log_dir], "#{ProcessManager::Config.config[:program_name]}.log")
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.pid_file
|
|
42
|
+
File.join(ProcessManager::Config.config[:pid_dir], "#{ProcessManager::Config.config[:program_name]}.pid")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def stop
|
|
46
|
+
if (pid = self.class.find_pid)
|
|
47
|
+
puts "Stopping #{description(pid)}"
|
|
48
|
+
ProcessManager::Log.info("Stopping #{description(pid)}")
|
|
49
|
+
begin
|
|
50
|
+
Process.kill('TERM', pid)
|
|
51
|
+
rescue Errno::ESRCH
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
begin
|
|
55
|
+
Timeout.timeout(ChildTerminationMaxWaitTime) do
|
|
56
|
+
loop do
|
|
57
|
+
begin
|
|
58
|
+
Process.kill(0, pid)
|
|
59
|
+
sleep(1)
|
|
60
|
+
rescue Errno::ESRCH
|
|
61
|
+
break
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
rescue Timeout::Error
|
|
66
|
+
puts "Child processes still running. Master going down."
|
|
67
|
+
ProcessManager::Log.warn("Master process (#{pid}) going down before terminating child")
|
|
68
|
+
end
|
|
69
|
+
else
|
|
70
|
+
puts "Nothing running that could be stopped"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def kill_children(sig)
|
|
75
|
+
children.each do |index, child_pid|
|
|
76
|
+
begin
|
|
77
|
+
Process.kill(sig, child_pid)
|
|
78
|
+
rescue Errno::ESRCH
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
begin
|
|
83
|
+
Timeout.timeout(ChildTerminationMaxWaitTime) do
|
|
84
|
+
children.each do |index, child_pid|
|
|
85
|
+
begin
|
|
86
|
+
Process.wait(child_pid)
|
|
87
|
+
rescue Errno::ESRCH
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
rescue Timeout::Error
|
|
92
|
+
children.each do |index, child_pid|
|
|
93
|
+
if ProcessManager.process_running?(child_pid)
|
|
94
|
+
puts "Stopping #{ProcessManager::Config.config[:program_name]} agent(#{pid}) but child(#{child_pid}) still processing."
|
|
95
|
+
ProcessManager::Log.warn("Stopping #{ProcessManager::Config.config[:program_name]} agent(#{pid}) but child(#{child_pid}) is still processing.")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'instance_agent'
|
|
4
|
+
|
|
5
|
+
class InstanceMetadata
|
|
6
|
+
|
|
7
|
+
IP_ADDRESS = '169.254.169.254'
|
|
8
|
+
PORT = 80
|
|
9
|
+
|
|
10
|
+
def self.host_identifier
|
|
11
|
+
doc = JSON.parse(http_get('/latest/dynamic/instance-identity/document').strip)
|
|
12
|
+
"arn:aws:ec2:#{doc['region']}:#{doc['accountId']}:instance/#{doc['instanceId']}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.region
|
|
16
|
+
az = http_get('/latest/meta-data/placement/availability-zone').strip
|
|
17
|
+
raise "Invalid availability zone name: #{az}" unless
|
|
18
|
+
az =~ /[a-z]{2}-[a-z]+-\d+[a-z]/
|
|
19
|
+
az.chop
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.instance_id
|
|
23
|
+
begin
|
|
24
|
+
Net::HTTP.start(IP_ADDRESS, PORT) do |http|
|
|
25
|
+
response = http.get('/latest/meta-data/instance-id')
|
|
26
|
+
if response.code.to_i != 200
|
|
27
|
+
return nil
|
|
28
|
+
end
|
|
29
|
+
return response.body
|
|
30
|
+
end
|
|
31
|
+
rescue
|
|
32
|
+
return nil
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
def self.http_get(path)
|
|
38
|
+
Net::HTTP.start(IP_ADDRESS, PORT) do |http|
|
|
39
|
+
response = http.get(path)
|
|
40
|
+
if response.code.to_i != 200
|
|
41
|
+
InstanceAgent::Log.send(:debug, "HTTP error from metadata service, code #{reponse.code}")
|
|
42
|
+
raise "HTTP error from metadata service, code #{reponse.code}"
|
|
43
|
+
end
|
|
44
|
+
return response.body
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require 'openssl'
|
|
2
|
+
require 'tempfile'
|
|
3
|
+
|
|
4
|
+
class CertificateHelper
|
|
5
|
+
def initialize()
|
|
6
|
+
generate_root()
|
|
7
|
+
generate_intermediate()
|
|
8
|
+
generate_signer()
|
|
9
|
+
|
|
10
|
+
ca_chain_file = generate_ca_chain()
|
|
11
|
+
|
|
12
|
+
ENV['AWS_REGION'] = 'us-east-1'
|
|
13
|
+
InstanceAgent::CodeDeployPlugin::DeploymentSpecification.init_cert_store(ca_chain_file)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def generate_root()
|
|
17
|
+
@root_key = OpenSSL::PKey::RSA.new(1024)
|
|
18
|
+
@root_cert = OpenSSL::X509::Certificate.new
|
|
19
|
+
@root_cert.version = 2
|
|
20
|
+
@root_cert.serial = 1
|
|
21
|
+
@root_cert.subject = OpenSSL::X509::Name.new [
|
|
22
|
+
['C', 'US'], ['ST', 'Washington'], ['L', 'Seattle'],
|
|
23
|
+
['O', 'Amazon.com, Inc.'], ['CN', 'Host Agent TEST CA Root G1']
|
|
24
|
+
]
|
|
25
|
+
@root_cert.issuer = @root_cert.subject
|
|
26
|
+
@root_cert.public_key = @root_key.public_key
|
|
27
|
+
@root_cert.not_before = Time.now
|
|
28
|
+
@root_cert.not_after = Time.now + 60
|
|
29
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
|
30
|
+
|
|
31
|
+
ef.subject_certificate = @root_cert
|
|
32
|
+
ef.issuer_certificate = @root_cert
|
|
33
|
+
@root_cert.extensions = [
|
|
34
|
+
ef.create_extension("basicConstraints","CA:TRUE",true),
|
|
35
|
+
ef.create_extension("keyUsage","keyCertSign, cRLSign", true),
|
|
36
|
+
ef.create_extension("subjectKeyIdentifier","hash",false),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
@root_cert.sign(@root_key, OpenSSL::Digest::SHA1.new)
|
|
40
|
+
|
|
41
|
+
return @root_cert
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def generate_intermediate()
|
|
45
|
+
@intermediate_key = OpenSSL::PKey::RSA.new(1024)
|
|
46
|
+
@intermediate_cert = OpenSSL::X509::Certificate.new
|
|
47
|
+
@intermediate_cert.version = 2
|
|
48
|
+
@intermediate_cert.serial = 1
|
|
49
|
+
@intermediate_cert.subject = OpenSSL::X509::Name.new [
|
|
50
|
+
['C', 'US'], ['ST', 'Washington'], ['L', 'Seattle'],
|
|
51
|
+
['O', 'Amazon.com, Inc.'], ['CN', 'Host Agent TEST CA Intermediate G1']
|
|
52
|
+
]
|
|
53
|
+
@intermediate_cert.issuer = @root_cert.subject
|
|
54
|
+
@intermediate_cert.public_key = @intermediate_key.public_key
|
|
55
|
+
@intermediate_cert.not_before = Time.now
|
|
56
|
+
@intermediate_cert.not_after = Time.now + 60
|
|
57
|
+
|
|
58
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
|
59
|
+
ef.subject_certificate = @intermediate_cert
|
|
60
|
+
ef.issuer_certificate = @root_cert
|
|
61
|
+
@intermediate_cert.extensions = [
|
|
62
|
+
ef.create_extension("basicConstraints","CA:TRUE",true),
|
|
63
|
+
ef.create_extension("keyUsage","keyCertSign, cRLSign", true),
|
|
64
|
+
ef.create_extension("subjectKeyIdentifier","hash",false)
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
@intermediate_cert.sign(@root_key, OpenSSL::Digest::SHA1.new)
|
|
68
|
+
|
|
69
|
+
return @intermediate_cert
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def generate_signer()
|
|
73
|
+
@signer_key = OpenSSL::PKey::RSA.new(1024)
|
|
74
|
+
@signer_cert = OpenSSL::X509::Certificate.new
|
|
75
|
+
@signer_cert.version = 2
|
|
76
|
+
@signer_cert.serial = 1
|
|
77
|
+
@signer_cert.subject = OpenSSL::X509::Name.new [
|
|
78
|
+
['C', 'US'], ['ST', 'Washington'], ['L', 'Seattle'],
|
|
79
|
+
['O', 'Amazon.com, Inc.'], ['CN', 'codedeploy-signer-us-east-1.amazonaws.com']
|
|
80
|
+
]
|
|
81
|
+
@signer_cert.issuer = @intermediate_cert.subject
|
|
82
|
+
@signer_cert.public_key = @signer_key.public_key
|
|
83
|
+
@signer_cert.not_before = Time.now
|
|
84
|
+
@signer_cert.not_after = Time.now + 60
|
|
85
|
+
|
|
86
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
|
87
|
+
ef.subject_certificate = @signer_cert
|
|
88
|
+
ef.issuer_certificate = @intermediate_cert
|
|
89
|
+
@signer_cert.extensions = [
|
|
90
|
+
ef.create_extension('basicConstraints', 'CA:FALSE', true),
|
|
91
|
+
ef.create_extension('keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature', true),
|
|
92
|
+
ef.create_extension('subjectKeyIdentifier', 'hash')
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
@signer_cert.sign(@intermediate_key, OpenSSL::Digest::SHA1.new)
|
|
96
|
+
|
|
97
|
+
return @signer_cert
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def generate_ca_chain()
|
|
101
|
+
ca_chain_file = Tempfile.new('host-agent-deployment-signer-ca-chain')
|
|
102
|
+
|
|
103
|
+
File.open(ca_chain_file.path, "wb") do |ca_chain|
|
|
104
|
+
ca_chain.print @root_cert.to_pem
|
|
105
|
+
ca_chain.print @intermediate_cert.to_pem
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
return ca_chain_file.path
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def sign_message(message)
|
|
112
|
+
if @signer_key.nil?
|
|
113
|
+
raise "Signer key not initialized"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
pkcs7 = OpenSSL::PKCS7::sign(@signer_cert, @signer_key, message, [], OpenSSL::PKCS7::BINARY)
|
|
117
|
+
|
|
118
|
+
return pkcs7.to_pem
|
|
119
|
+
end
|
|
120
|
+
end
|