diff --git a/Rakefile b/Rakefile index 105de0d8..19086344 100644 --- a/Rakefile +++ b/Rakefile @@ -12,6 +12,7 @@ Rake::TestTask.new(:test) do |t| t.verbose = true end task :default => :test +task :release => :test # Run units tests in test/instance_agent/ Rake::TestTask.new(:test_instance_agent) do |t| diff --git a/init.d/codedeploy-agent b/init.d/codedeploy-agent index c6c26ef0..beecad05 100755 --- a/init.d/codedeploy-agent +++ b/init.d/codedeploy-agent @@ -17,7 +17,9 @@ # the deployment artifacts on to this instance. ### END INIT INFO + RETVAL=0 +[ -f /etc/profile ] && [ "`stat --format '%U %G' /etc/profile`" == "root root" ] && source /etc/profile prog="codedeploy-agent" AGENT_ROOT="/opt/codedeploy-agent/" @@ -52,12 +54,15 @@ update() { case "$1" in start) - update start ;; start-no-update) start ;; + start-with-update) + update + start + ;; stop) stop ;; diff --git a/lib/instance_agent.rb b/lib/instance_agent.rb index d616f524..5d25c037 100644 --- a/lib/instance_agent.rb +++ b/lib/instance_agent.rb @@ -1,6 +1,7 @@ # encoding: UTF-8 Gem.use_paths(nil, Gem.path << "/opt/codedeploy-agent/vendor") + require 'core_ext' require 'rubygems' diff --git a/lib/instance_agent/plugins/codedeploy/codedeploy_control.rb b/lib/instance_agent/plugins/codedeploy/codedeploy_control.rb index fc4acfa5..a0c11440 100644 --- a/lib/instance_agent/plugins/codedeploy/codedeploy_control.rb +++ b/lib/instance_agent/plugins/codedeploy/codedeploy_control.rb @@ -78,20 +78,7 @@ def verify_cert # Do minimal cert pinning def verify_subject InstanceAgent::Log.debug("#{self.class.to_s}: Actual certificate subject is '#{@cert.subject.to_s}'") - - case @region - when 'us-east-1' - @cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-commands.us-east-1.amazonaws.com" - when 'us-west-2' - @cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-commands.us-west-2.amazonaws.com" - when 'eu-west-1' - @cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-commands.eu-west-1.amazonaws.com" - when 'ap-southeast-2' - @cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-commands.ap-southeast-2.amazonaws.com" - else - InstanceAgent::Log.debug("#{self.class.to_s}: Unsupported region '#{@region}'") - false - end + @cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-commands."+@region+".amazonaws.com" end end diff --git a/lib/instance_agent/plugins/codedeploy/command_executor.rb b/lib/instance_agent/plugins/codedeploy/command_executor.rb index cc0b96f1..7718c6be 100644 --- a/lib/instance_agent/plugins/codedeploy/command_executor.rb +++ b/lib/instance_agent/plugins/codedeploy/command_executor.rb @@ -176,11 +176,13 @@ def download_from_s3(deployment_spec, bucket, key, version, etag) File.join(InstanceAgent::Config.config[:log_dir], "#{InstanceAgent::Config.config[:program_name]}.aws_wire.log"), 16, 64 * 1024 * 1024), - :http_wire_trace => true) + :http_wire_trace => true, + :signature_version => 'v4') else s3 = Aws::S3::Client.new( :region => region, - :ssl_ca_directory => ENV['AWS_SSL_CA_DIRECTORY']) + :ssl_ca_directory => ENV['AWS_SSL_CA_DIRECTORY'], + :signature_version => 'v4') end File.open(artifact_bundle(deployment_spec), 'wb') do |file| @@ -316,16 +318,22 @@ def update_last_successful_install(deployment_spec) private def cleanup_old_archives(deployment_group) - deployment_archives = Dir[File.join(ProcessManager::Config.config[:root_dir], deployment_group, '*')] - extra = deployment_archives.size - ARCHIVES_TO_RETAIN + deployment_archives = Dir.entries(File.join(ProcessManager::Config.config[:root_dir], deployment_group)) + # remove . and .. + deployment_archives.delete(".") + deployment_archives.delete("..") + + full_path_deployment_archives = deployment_archives.map{ |f| File.join(ProcessManager::Config.config[:root_dir], deployment_group, f)} + + extra = full_path_deployment_archives.size - ARCHIVES_TO_RETAIN return unless extra > 0 # Never remove the last successful deployment last_success = last_successful_deployment_dir(deployment_group) - deployment_archives.delete(last_success) + full_path_deployment_archives.delete(last_success) # Sort oldest -> newest, take first `extra` elements - oldest_extra = deployment_archives.sort_by{ |f| File.mtime(f) }.take(extra) + oldest_extra = full_path_deployment_archives.sort_by{ |f| File.mtime(f) }.take(extra) # Absolute path takes care of relative root directories directories = oldest_extra.map{ |f| File.absolute_path(f) } diff --git a/lib/instance_agent/plugins/codedeploy/command_poller.rb b/lib/instance_agent/plugins/codedeploy/command_poller.rb index a2d245d8..859856d8 100644 --- a/lib/instance_agent/plugins/codedeploy/command_poller.rb +++ b/lib/instance_agent/plugins/codedeploy/command_poller.rb @@ -8,6 +8,15 @@ class CommandPoller < InstanceAgent::Agent::Base VERSION = "2013-04-23" def initialize + test_profile = InstanceAgent::Config.config[:codedeploy_test_profile] + unless ["beta", "gamma"].include?(test_profile.downcase) + # Remove any user overrides set in the environment. + # The agent should always pull credentials from the EC2 instance + # profile or the credentials in the OnPremises config file. + ENV['AWS_ACCESS_KEY_ID'] = nil + ENV['AWS_SECRET_ACCESS_KEY'] = nil + ENV['AWS_CREDENTIAL_FILE'] = nil + end CodeDeployPlugin::OnPremisesConfig.configure region = ENV['AWS_REGION'] || InstanceMetadata.region @host_identifier = ENV['AWS_HOST_IDENTIFIER'] || InstanceMetadata.host_identifier @@ -151,4 +160,4 @@ def gather_diagnostics() end end end -end \ No newline at end of file +end diff --git a/lib/instance_agent/plugins/codedeploy/deployment_specification.rb b/lib/instance_agent/plugins/codedeploy/deployment_specification.rb index 808194bc..c2f191c0 100644 --- a/lib/instance_agent/plugins/codedeploy/deployment_specification.rb +++ b/lib/instance_agent/plugins/codedeploy/deployment_specification.rb @@ -1,5 +1,6 @@ require 'openssl' require 'instance_metadata' +require 'open-uri' module InstanceAgent module Plugins @@ -132,18 +133,7 @@ def self.verify_pkcs7_signer_cert(cert) when 'beta', 'gamma' cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-signer-integ.amazonaws.com" when 'prod' - case @@region - when 'us-east-1' - cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-signer-us-east-1.amazonaws.com" - when 'us-west-2' - cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-signer-us-west-2.amazonaws.com" - when 'eu-west-1' - cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-signer-eu-west-1.amazonaws.com" - when 'ap-southeast-2' - cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-signer-ap-southeast-2.amazonaws.com" - else - raise "Unknown region '#{@region}'" - end + cert.subject.to_s == "/C=US/ST=Washington/L=Seattle/O=Amazon.com, Inc./CN=codedeploy-signer-"+@@region+".amazonaws.com" else raise "Unknown profile '#{Config.config()[:codedeploy_test_profile]}'" end diff --git a/lib/instance_metadata.rb b/lib/instance_metadata.rb index 55693004..2eb9b594 100644 --- a/lib/instance_metadata.rb +++ b/lib/instance_metadata.rb @@ -6,7 +6,7 @@ class InstanceMetadata IP_ADDRESS = '169.254.169.254' PORT = 80 - + def self.host_identifier doc = JSON.parse(http_get('/latest/dynamic/instance-identity/document').strip) "arn:aws:ec2:#{doc['region']}:#{doc['accountId']}:instance/#{doc['instanceId']}" diff --git a/test/instance_agent/plugins/codedeploy/command_executor_test.rb b/test/instance_agent/plugins/codedeploy/command_executor_test.rb index 23635371..5badfe63 100644 --- a/test/instance_agent/plugins/codedeploy/command_executor_test.rb +++ b/test/instance_agent/plugins/codedeploy/command_executor_test.rb @@ -184,6 +184,7 @@ def generate_signed_message_for(map) @mock_file = mock Net::HTTP.stubs(:start).yields(@http) File.stubs(:open).returns @mock_file + Dir.stubs(:entries).returns [] @mock_file.stubs(:close) @http.stubs(:request_get) @s3 = mock