diff --git a/History.txt b/History.txt index 57610ca..dc20425 100644 --- a/History.txt +++ b/History.txt @@ -294,6 +294,8 @@ the source key. - Tags Suport - ClientToken support added on instance launch - RDS: API "2010-07-28" + - ELB: API '2010-07-01' (SSL support) + - IAM: API '2010-05-08' (AWS Identity and Access Management interface) - 301 Redirect support added - Removed: - ActiveSupport dependency diff --git a/Manifest.txt b/Manifest.txt index deeb917..5a846d9 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -33,6 +33,11 @@ lib/acf/right_acf_interface.rb lib/acf/right_acf_streaming_interface.rb lib/acf/right_acf_origin_access_identities.rb lib/rds/right_rds_interface.rb +lib/iam/right_iam_interface.rb +lib/iam/right_iam_groups.rb +lib/iam/right_iam_users.rb +lib/iam/right_iam_access_keys.rb +lib/iam/right_iam_mfa_devices.rb test/ec2/test_helper.rb test/ec2/test_right_ec2.rb test/http_connection.rb diff --git a/README.txt b/README.txt index 8d77756..69a6d33 100644 --- a/README.txt +++ b/README.txt @@ -68,10 +68,6 @@ concurrent requests to AWS. The way this plays out in practice is: Note that due to limitations in the I/O of the Ruby interpreter you may not get the degree of parallelism you may expect with the multi-threaded setting. -By default, EC2/S3/SQS/SDB/ACF interface instances are created in single-threaded mode. Set -"params[:multi_thread]" to "true" in the initialization arguments to use -multithreaded mode. - == GETTING STARTED: * For EC2 read RightAws::Ec2 and consult the Amazon EC2 API documentation at diff --git a/lib/acf/right_acf_interface.rb b/lib/acf/right_acf_interface.rb index 31734e6..038396e 100644 --- a/lib/acf/right_acf_interface.rb +++ b/lib/acf/right_acf_interface.rb @@ -96,7 +96,6 @@ def self.bench_service # * :server: CloudFront service host, default: DEFAULT_HOST # * :port: CloudFront service port, default: DEFAULT_PORT # * :protocol: 'http' or 'https', default: DEFAULT_PROTOCOL - # * :multi_thread: true=HTTP connection per thread, false=per process # * :logger: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT # # acf = RightAws::AcfInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX', diff --git a/lib/acw/right_acw_interface.rb b/lib/acw/right_acw_interface.rb index f6a6a3d..0691794 100644 --- a/lib/acw/right_acw_interface.rb +++ b/lib/acw/right_acw_interface.rb @@ -54,7 +54,6 @@ def self.bench_service # * :server: ACW service host, default: DEFAULT_HOST # * :port: ACW service port, default: DEFAULT_PORT # * :protocol: 'http' or 'https', default: DEFAULT_PROTOCOL - # * :multi_thread: true=HTTP connection per thread, false=per process # * :logger: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT # * :signature_version: The signature version : '0','1' or '2'(default) # * :cache: true/false(default): list_metrics diff --git a/lib/as/right_as_interface.rb b/lib/as/right_as_interface.rb index d1840aa..bd3bd33 100644 --- a/lib/as/right_as_interface.rb +++ b/lib/as/right_as_interface.rb @@ -95,7 +95,6 @@ def self.bench_service # * :server: AS service host, default: DEFAULT_HOST # * :port: AS service port, default: DEFAULT_PORT # * :protocol: 'http' or 'https', default: DEFAULT_PROTOCOL - # * :multi_thread: true=HTTP connection per thread, false=per process # * :logger: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT # * :signature_version: The signature version : '0','1' or '2'(default) # * :cache: true/false(default): describe_auto_scaling_groups diff --git a/lib/awsbase/right_awsbase.rb b/lib/awsbase/right_awsbase.rb index 867fd88..0261d42 100644 --- a/lib/awsbase/right_awsbase.rb +++ b/lib/awsbase/right_awsbase.rb @@ -23,7 +23,6 @@ # Test module RightAws -# require 'md5' require 'digest/md5' require 'pp' @@ -288,7 +287,6 @@ def init(service_info, aws_access_key_id, aws_secret_access_key, params={}) #:no # a set of options to be passed to RightHttpConnection object @params[:connection_options] = {} unless @params[:connection_options].is_a?(Hash) @with_connection_options = {} -# @params[:multi_thread] ||= defined?(AWS_DAEMON) @params[:connections] ||= :shared # || :dedicated @params[:max_connections] ||= 10 @params[:connection_lifetime] ||= 20*60 @@ -360,11 +358,6 @@ def on_exception(options={:raise=>true, :log=>true}) # :nodoc: AwsError::on_aws_exception(self, options) end -# # Return +true+ if this instance works in multi_thread mode and +false+ otherwise. -# def multi_thread -# @params[:multi_thread] -# end - # ACF, AMS, EC2, LBS and SDB uses this guy # SQS and S3 use their own methods def generate_request_impl(verb, action, options={}) #:nodoc: @@ -535,6 +528,20 @@ def last_request_id @last_response && @last_response.body.to_s[%r{(.+?)}i] && $1 end + # Incrementally lists something. + def incrementally_list_items(action, parser_class, params={}, &block) # :nodoc: + params = params.dup + params['MaxItems'] = params.delete(:max_items) if params[:max_items] + params['Marker'] = params.delete(:marker) if params[:marker] + last_response = nil + loop do + last_response = request_info( generate_request(action, params), parser_class.new(:logger => @logger)) + params['Marker'] = last_response[:marker] + break unless block && block.call(last_response) && !last_response[:marker].right_blank? + end + last_response + end + # Format array of items into Amazons handy hash ('?' is a place holder): # Options: # :default => "something" : Set a value to "something" when it is nil diff --git a/lib/ec2/right_ec2.rb b/lib/ec2/right_ec2.rb index 97c4995..3782129 100644 --- a/lib/ec2/right_ec2.rb +++ b/lib/ec2/right_ec2.rb @@ -107,7 +107,6 @@ def self.api # * :region: EC2 region (North America by default) # * :port: EC2 service port, default: DEFAULT_PORT # * :protocol: 'http' or 'https', default: DEFAULT_PROTOCOL - # * :multi_thread: true=HTTP connection per thread, false=per process # * :logger: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT # * :signature_version: The signature version : '0','1' or '2'(default) # * :cache: true/false: caching for: ec2_describe_images, describe_instances, diff --git a/lib/elb/right_elb_interface.rb b/lib/elb/right_elb_interface.rb index 3e9a990..986e269 100644 --- a/lib/elb/right_elb_interface.rb +++ b/lib/elb/right_elb_interface.rb @@ -62,12 +62,14 @@ class ElbInterface < RightAwsBase include RightAwsBaseInterface # Amazon ELB API version being used - API_VERSION = "2009-11-25" + API_VERSION = "2010-07-01" DEFAULT_HOST = "elasticloadbalancing.amazonaws.com" DEFAULT_PATH = '/' DEFAULT_PROTOCOL = 'https' DEFAULT_PORT = 443 + LISTENER_PROTOCOLS = [ 'HTTP', 'HTTPS', 'TCP', 'SSL' ] + @@bench = AwsBenchmarkingBlock.new def self.bench_xml @@bench.xml @@ -83,7 +85,6 @@ def self.bench_service # * :server: ELB service host, default: DEFAULT_HOST # * :port: ELB service port, default: DEFAULT_PORT # * :protocol: 'http' or 'https', default: DEFAULT_PROTOCOL - # * :multi_thread: true=HTTP connection per thread, false=per process # * :logger: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT # * :signature_version: The signature version : '0','1' or '2'(default) # * :cache: true/false(default): caching works for: describe_load_balancers @@ -172,11 +173,15 @@ def describe_load_balancers(*load_balancers) # Create new load balancer. # Returns a new load balancer DNS name. # - # lb = elb.create_load_balancer( 'test-kd1', - # ['us-east-1a', 'us-east-1b'], - # [ { :protocol => :http, :load_balancer_port => 80, :instance_port => 80 }, - # { :protocol => :tcp, :load_balancer_port => 443, :instance_port => 443 } ]) - # puts lb #=> "test-kd1-1519253964.us-east-1.elb.amazonaws.com" + # Listener options: :protocol, :load_balancer_port, :instance_port and :ssl_certificate_id + # Protocols: :tcp, :http, :https or :ssl + # + # elb.create_load_balancer( 'test-kd1', + # ['us-east-1a', 'us-east-1b'], + # [ { :protocol => :http, :load_balancer_port => 80, :instance_port => 80 }, + # { :protocol => :https, :load_balancer_port => 443, :instance_port => 443, + # :ssl_certificate_id => 'arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/Bob' } ]) + # #=> "test-kd1-1519253964.us-east-1.elb.amazonaws.com" # def create_load_balancer(load_balancer_name, availability_zones=[], listeners=[]) request_hash = { 'LoadBalancerName' => load_balancer_name } @@ -188,13 +193,7 @@ def create_load_balancer(load_balancer_name, availability_zones=[], listeners=[] :load_balancer_port => 80, :instance_port => 80 } end - listeners = [listeners] unless listeners.is_a?(Array) - request_hash.merge!( amazonize_list( ['Listeners.member.?.Protocol', - 'Listeners.member.?.LoadBalancerPort', - 'Listeners.member.?.InstancePort'], - listeners.map{|i| [ (i[:protocol] || 'HTTP').to_s.upcase, - (i[:load_balancer_port] || 80), - (i[:instance_port] || 80) ] } ) ) + request_hash = merge_listeners_into_request_hash(request_hash, listeners) link = generate_request("CreateLoadBalancer", request_hash) request_info(link, CreateLoadBalancerParser.new(:logger => @logger)) end @@ -212,6 +211,37 @@ def delete_load_balancer(load_balancer_name) request_info(link, DeleteLoadBalancerParser.new(:logger => @logger)) end + # Creates one or more new listeners on a LoadBalancer for the specified port. If a listener with the given + # port does not already exist, it will be created; otherwise, the properties of the new listener must match + # the the properties of the existing listener. + # + # Listener options: :protocol, :load_balancer_port, :instance_port and :ssl_certificate_id + # Protocols: :tcp, :http, :https or :ssl + # + # elb.create_load_balancer_listeners( 'test-kd1', + # [ { :protocol => :http, :load_balancer_port => 80, :instance_port => 80 }, + # { :protocol => :https, :load_balancer_port => 443, :instance_port => 443, + # :ssl_certificate_id => 'arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/Bob' } ]) #=> true + # + def create_load_balancer_listeners(load_balancer_name, listeners) + request_hash = { 'LoadBalancerName' => load_balancer_name } + request_hash = merge_listeners_into_request_hash(request_hash, listeners) + link = generate_request("CreateLoadBalancerListeners", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + # Removes listeners from the load balancer for the specified port number. + # + # elb.delete_load_balancer_listeners( 'kd_test', 80, 443) #=> true + # + def delete_load_balancer_listeners(load_balancer_name, *load_balancer_ports) + load_balancer_ports.flatten! + request_hash = { 'LoadBalancerName' => load_balancer_name } + request_hash.merge!( amazonize_list("LoadBalancerPorts.member", load_balancer_ports ) ) + link = generate_request("DeleteLoadBalancerListeners", request_hash ) + request_info(link, DeleteLoadBalancerParser.new(:logger => @logger)) + end + # Add one or more zones to a load balancer. # Returns a list of updated availability zones for the load balancer. # @@ -368,6 +398,35 @@ def delete_load_balancer_policy(load_balancer_name, policy_name) request_info(link, RightHttp2xxParser.new(:logger => @logger)) end + def set_load_balancer_listener_ssl_certificate(load_balancer_name, load_balancer_port, ssl_sertificate_id) + request_hash = { 'LoadBalancerName' => load_balancer_name, + 'LoadBalancerPort' => load_balancer_port, + 'SSLCertificateId' => ssl_sertificate_id } + link = generate_request("SetLoadBalancerListenerSSLCertificate", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # Helpers + #----------------------------------------------------------------- + + def merge_listeners_into_request_hash(request_hash, listeners) # :nodoc: + listeners = [listeners] unless listeners.is_a?(Array) + request_hash.merge(amazonize_list( ['Listeners.member.?.Protocol', + 'Listeners.member.?.LoadBalancerPort', + 'Listeners.member.?.InstancePort', + 'Listeners.member.?.SSLCertificateId'], + listeners.map{ |i| + [ (i[:protocol] || 'HTTP').to_s.upcase, + i[:load_balancer_port] || 80, + i[:instance_port] || 80, + i[:ssl_certificate_id]] + }, + :default => :skip_nils + ) + ) + end + #----------------------------------------------------------------- # PARSERS: Load Balancers #----------------------------------------------------------------- @@ -400,6 +459,7 @@ def tagend(name) when 'Protocol' then @listener[:protocol] = @text when 'LoadBalancerPort' then @listener[:load_balancer_port] = @text when 'InstancePort' then @listener[:instance_port] = @text + when 'SSLCertificateId' then @listener[:ssl_certificate_id] = @text end case full_tag_name when %r{AvailabilityZones/member$} then @item[:availability_zones] << @text diff --git a/lib/iam/right_iam_access_keys.rb b/lib/iam/right_iam_access_keys.rb new file mode 100644 index 0000000..92df5e6 --- /dev/null +++ b/lib/iam/right_iam_access_keys.rb @@ -0,0 +1,71 @@ +module RightAws + + class IamInterface < RightAwsBase + + #----------------------------------------------------------------- + # Access Keys + #----------------------------------------------------------------- + + # Returns information about the Access Key IDs associated with the specified User. + # + # Options: :user_name, :max_items, :marker + # + # iam.list_access_keys #=> + # [{:create_date=>"2007-01-09T06:16:30Z", + # :status=>"Active", + # :access_key_id=>"00000000000000000000"}] + # + def list_access_keys(options={}, &block) + incrementally_list_iam_resources('ListAccessKeys', options, &block) + end + + # Creates a new AWS Secret Access Key and corresponding AWS Access Key ID for the specified User. + # + # Options: :user_name + # + # iam.create_access_key(:user_name => 'kd1') #=> + # {:access_key_id=>"AK0000000000000000ZQ", + # :status=>"Active", + # :secret_access_key=>"QXN0000000000000000000000000000000000Ioj", + # :create_date=>"2010-10-29T07:16:32.210Z", + # :user_name=>"kd1"} + # + def create_access_key(options={}) + request_hash = {} + request_hash['UserName'] = options[:user_name] unless options[:user_name].right_blank? + link = generate_request("CreateAccessKey", request_hash) + request_info(link, CreateAccessKeyParser.new(:logger => @logger)) + end + + # Deletes the access key associated with the specified User. + # + # Options: :user_name + # + # iam.delete_access_key('AK00000000000000006A', :user_name => 'kd1') #=> true + # + def delete_access_key(access_key_id, options={}) + request_hash = { 'AccessKeyId' => access_key_id } + request_hash['UserName'] = options[:user_name] unless options[:user_name].right_blank? + link = generate_request("DeleteAccessKey", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # PARSERS + #----------------------------------------------------------------- + + class ListAccessKeysParser < BasicIamListParser #:nodoc: + def reset + @expected_tags = %w{ AccessKeyId CreateDate Status UserName } + end + end + + class CreateAccessKeyParser < BasicIamParser #:nodoc: + def reset + @expected_tags = %w{ AccessKeyId CreateDate SecretAccessKey Status UserName } + end + end + + end + +end \ No newline at end of file diff --git a/lib/iam/right_iam_groups.rb b/lib/iam/right_iam_groups.rb new file mode 100644 index 0000000..3d86937 --- /dev/null +++ b/lib/iam/right_iam_groups.rb @@ -0,0 +1,195 @@ +module RightAws + + class IamInterface < RightAwsBase + + #----------------------------------------------------------------- + # Groups + #----------------------------------------------------------------- + + # Lists the groups that have the specified path prefix. + # + # Options: :path_prefix, :max_items, :marker + # + # iam.list_groups #=> + # [{:group_id=>"AGP000000000000000UTY", + # :arn=>"arn:aws:iam::640000000037:group/kd_test", + # :path=>"/", + # :group_name=>"kd_test"}] + # + def list_groups(options={}, &block) + incrementally_list_iam_resources('ListGroups', options, &block) + end + + # Creates a new group. + # + # iam.create_group('kd_group') #=> + # {:group_id=>"AGP000000000000000UTY", + # :arn=>"arn:aws:iam::640000000037:group/kd_test", + # :path=>"/", + # :group_name=>"kd_test"} + # + # iam.create_group('kd_test_3', '/kd/') #=> + # {:group_id=>"AGP000000000000000G6Q", + # :arn=>"arn:aws:iam::640000000037:group/kd/kd_test_3", + # :path=>"/kd/", + # :group_name=>"kd_test_3"} + # + def create_group(group_name, path=nil) + request_hash = { 'GroupName' => group_name } + request_hash['Path'] = path unless path.right_blank? + link = generate_request("CreateGroup", request_hash) + request_info(link, CreateGroupParser.new(:logger => @logger)) + end + + # Updates the name and/or the path of the specified group + # + # Options: :new_group_name, :new_path + # + # iam.update_group('kd_test', :new_group_name => 'kd_test_1', :new_path => '/kd1/') #=> true + # + def update_group(group_name, options={}) + request_hash = { 'GroupName' => group_name} + request_hash['NewGroupName'] = options[:new_group_name] unless options[:new_group_name].right_blank? + request_hash['NewPath'] = options[:new_path] unless options[:new_path].right_blank? + link = generate_request("UpdateGroup", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + # Returns a list of Users that are in the specified group. + # + # Options: :max_items, :marker + # + # iam.get_group('kd_test') #=> + # {:arn=>"arn:aws:iam::640000000037:group/kd1/kd_test_1", + # :users=> + # [{:arn=>"arn:aws:iam::640000000037:user/kd", + # :path=>"/", + # :user_name=>"kd", + # :user_id=>"AID000000000000000WZ2"}], + # :group_name=>"kd_test_1", + # :group_id=>"AGP000000000000000UTY", + # :path=>"/kd1/"} + # + def get_group(group_name, options={}, &block) + options[:group_name] = group_name + incrementally_list_iam_resources('GetGroup', options, :items => :users, :except => [:marker, :is_truncated], &block) + end + + # Deletes the specified group. The group must not contain any Users or have any attached policies. + # + # iam.delete_group('kd_test_3') #=> true + # + def delete_group(group_name) + request_hash = { 'GroupName' => group_name } + link = generate_request("DeleteGroup", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # Group Policies + #----------------------------------------------------------------- + + # Lists the names of the policies associated with the specified group. + # + # Options: :max_items, :marker + # + # iam.list_group_policies('kd_test') #=> ["kd_policy_1"] + # + def list_group_policies(group_name, options={}, &block) + options[:group_name] = group_name + incrementally_list_iam_resources('ListGroupPolicies', options, :parser => BasicIamListParser, &block) + end + + # Adds (or updates) a policy document associated with the specified group. + # + # iam.put_group_policy('kd_test', 'kd_policy_1', %Q({"Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]})) #=> true + # + def put_group_policy(group_name, policy_name, policy_document) + request_hash = { 'GroupName' => group_name, + 'PolicyDocument' => policy_document, + 'PolicyName' => policy_name } + link = generate_request_impl(:post, "PutGroupPolicy", request_hash) + result = request_info(link, RightHttp2xxParser.new(:logger => @logger)) + result[:policy_document] = URI::decode(result[:policy_document]) + result + end + + # Retrieves the specified policy document for the specified group. + # + # iam.get_group_policy('kd_test', 'kd_policy_1') #=> + # {:policy_name=>"kd_policy_1", + # :policy_document=>"{\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"*\",\"Resource\":\"*\"}]}", + # :group_name=>"kd_test"} + # + def get_group_policy(group_name, policy_name) + request_hash = { 'GroupName' => group_name, + 'PolicyName' => policy_name } + link = generate_request("GetGroupPolicy", request_hash) + request_info(link, GetGroupPolicyParser.new(:logger => @logger)) + end + + # Deletes the specified policy that is associated with the specified group + # + # iam.delete_group_policy('kd_test', 'kd_policy_1') #=> true + # + def delete_group_policy(group_name, policy_name) + request_hash = { 'GroupName' => group_name, + 'PolicyName' => policy_name } + link = generate_request("DeleteGroupPolicy", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # PARSERS: + #----------------------------------------------------------------- + + class ListGroupsParser < BasicIamListParser #:nodoc: + def reset + @expected_tags = %w{ Arn GroupId GroupName Path } + end + end + + class CreateGroupParser < BasicIamParser #:nodoc: + def reset + @expected_tags = %w{ Arn GroupId GroupName Path } + end + end + + class GetGroupParser < RightAWSParser #:nodoc: + def tagstart(name, attributes) + @item = {} if name == 'member' + end + def tagend(name) + case name + when 'Marker' then @result[:marker] = @text + when 'IsTruncated' then @result[:is_truncated] = @text == 'true' + + when 'GroupName' then @result[:group_name] = @text + when 'GroupId' then @result[:group_id] = @text + when 'UserName' then @item[:user_name] = @text + when 'UserId' then @item[:user_id] = @text + when 'member' then @result[:users] << @item + else + case full_tag_name + when %r{/Group/Path$} then @result[:path] = @text + when %r{/Group/Arn$} then @result[:arn] = @text + when %r{/member/Path$} then @item[:path] = @text + when %r{/member/Arn$} then @item[:arn] = @text + end + end + end + def reset + @result = { :users => [] } + end + end + + class GetGroupPolicyParser < BasicIamParser #:nodoc: + def reset + @expected_tags = %w{ GroupName PolicyDocument PolicyName } + end + end + + end + +end + diff --git a/lib/iam/right_iam_interface.rb b/lib/iam/right_iam_interface.rb new file mode 100644 index 0000000..9ae659d --- /dev/null +++ b/lib/iam/right_iam_interface.rb @@ -0,0 +1,341 @@ +# +# Copyright (c) 2007-2010 RightScale Inc +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +module RightAws + + # = RightAWS::Iam -- RightScale AWS Identity and Access Management (IAM) interface + # + # The RightAws::Iam class provides a complete interface to Amazon's Identity and + # Access Management service. + # + # For explanations of the semantics of each call, please refer to Amazon's documentation at + # http://aws.amazon.com/documentation/iam/ + # + # Examples: + # + # Create an EC2 interface handle: + # + # iam = RightAws::IamInterface.new(aws_access_key_id, aws_secret_access_key) + # iam.list_access_keys + # iam.list_users + # iam.list_groups + # + class IamInterface < RightAwsBase + include RightAwsBaseInterface + + API_VERSION = "2010-05-08" + DEFAULT_HOST = "iam.amazonaws.com" + DEFAULT_PATH = '/' + DEFAULT_PROTOCOL = 'https' + DEFAULT_PORT = 443 + + @@bench = AwsBenchmarkingBlock.new + def self.bench_xml + @@bench.xml + end + def self.bench_service + @@bench.service + end + + # Create a new handle to an IAM account. All handles share the same per process or per thread + # HTTP connection to Amazon IAM. Each handle is for a specific account. The params have the + # following options: + # * :endpoint_url a fully qualified url to Amazon API endpoint (this overwrites: :server, :port, :service, :protocol). + # * :server: IAM service host, default: DEFAULT_HOST + # * :port: IAM service port, default: DEFAULT_PORT + # * :protocol: 'http' or 'https', default: DEFAULT_PROTOCOL + # * :logger: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT + # * :signature_version: The signature version : '0','1' or '2'(default) + # * :cache: true/false(default): caching works for: describe_load_balancers + # + def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={}) + init({ :name => 'IAM', + :default_host => ENV['IAM_URL'] ? URI.parse(ENV['IAM_URL']).host : DEFAULT_HOST, + :default_port => ENV['IAM_URL'] ? URI.parse(ENV['IAM_URL']).port : DEFAULT_PORT, + :default_service => ENV['IAM_URL'] ? URI.parse(ENV['IAM_URL']).path : DEFAULT_PATH, + :default_protocol => ENV['IAM_URL'] ? URI.parse(ENV['IAM_URL']).scheme : DEFAULT_PROTOCOL, + :default_api_version => ENV['IAM_API_VERSION'] || API_VERSION }, + aws_access_key_id || ENV['AWS_ACCESS_KEY_ID'] , + aws_secret_access_key|| ENV['AWS_SECRET_ACCESS_KEY'], + params) + end + + def generate_request(action, params={}) #:nodoc: + generate_request_impl(:get, action, params ) + end + + # Sends request to Amazon and parses the response + # Raises AwsError if any banana happened + def request_info(request, parser) #:nodoc: + request_info_impl(:iam_connection, @@bench, request, parser) + end + + # Options: :parser, :except, :items + # + def incrementally_list_iam_resources(api_function, params={}, options={}, &block) #:nodoc: + items = options[:items] || :items + result = { items => [] } + parser = options[:parser] || "RightAws::IamInterface::#{api_function}Parser".right_constantize + request_hash = {} + params.each { |key,value| request_hash[key.to_s.right_camelize] = value unless value.right_blank? } + incrementally_list_items(api_function, parser, request_hash) do |response| + if result[items].right_blank? + result = response + else + result[items] += response[items] + end + block ? block.call(response) : true + end + if options[:except] + Array(options[:except]).each{ |key| result.delete(key)} + result + else + result[items] + end + end + + #----------------------------------------------------------------- + # Server Certificates + #----------------------------------------------------------------- + + # Lists the server certificates that have the specified path prefix. If none exist, the action returns an empty list. + # + # Options: :path_prefix, :max_items, :marker + # + # iam.list_server_certificates #=> + # {:server_certificate_id=>"ASCDJN5K5HRGS1N2UJWWU", + # :server_certificate_name=>"KdCert1", + # :upload_date=>"2010-12-09T13:21:07.226Z", + # :path=>"/kdcert/", + # :arn=>"arn:aws:iam::600000000007:server-certificate/kdcert/KdCert1"} + # + def list_server_certificates(options={}, &block) + incrementally_list_iam_resources('ListServerCertificates', options, &block) + end + + # Uploads a server certificate entity for the AWS Account. The server certificate + # entity includes a public key certificate, a private key, and an optional certificate + # chain, which should all be PEM-encoded. + # + # Options: :certificate_chain, :path + # + # certificate_body =<<-EOB + # -----BEGIN CERTIFICATE----- + # MIICdzCCAeCgAwIBAgIGANc+Ha2wMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNVBAYT + # AlVTMRMwEQYDVQQKEwpBbWF6b24uY29tMQwwCgYDVQQLEwNBV1MxITAfBgNVBAMT + # GEFXUyBMaW1pdGVkLUFzc3VyYW5jZSBDQTAeFw0wOTAyMDQxNzE5MjdaFw0xMDAy + # AEaHzTpmEXAMPLE= + # EOB + # + # private_key =<'/kdcert/') #=> + # {:server_certificate_id=>"ASCDJN5K5HRGS1N2UJWWU", + # :server_certificate_name=>"KdCert1", + # :upload_date=>"2010-12-09T13:21:07.226Z", + # :path=>"/kdcert/", + # :arn=>"arn:aws:iam::600000000007:server-certificate/kdcert/KdCert1"} + # + def upload_server_certificate(server_certificate_name, certificate_body, private_key, options={}) + request_hash = { 'CertificateBody' => certificate_body, + 'PrivateKey' => private_key, + 'ServerCertificateName' => server_certificate_name } + request_hash['CertificateChain'] = options[:certificate_chain] unless options[:certificate_chain].right_blank? + request_hash['Path'] = options[:path] unless options[:path].right_blank? + link = generate_request_impl(:post, "UploadServerCertificate", request_hash) + request_info(link, GetServerCertificateParser.new(:logger => @logger)) + end + + # Updates the name and/or the path of the specified server certificate. + # + # Options: :new_server_certificate_name, :new_path + # + # iam.update_server_certificate('ProdServerCert', :new_server_certificate_name => 'OldServerCert') #=> true + # + def update_server_certificate(server_certificate_name, options={}) + request_hash = { 'ServerCertificateName' => server_certificate_name} + request_hash['NewServerCertificateName'] = options[:new_server_certificate_name] unless options[:new_server_certificate_name].right_blank? + request_hash['NewPath'] = options[:new_path] unless options[:new_path].right_blank? + link = generate_request("UpdateServerCertificate", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + # Retrieves information about the specified server certificate. + # + # iam.get_server_certificate('KdCert1') + # {:certificate_body=> + # "-----BEGIN CERTIFICATE-----\nMIICATC...TiU5TibMpD1g==\n-----END CERTIFICATE-----", + # :server_certificate_id=>"ASCDJN5K5HRGS1N2UJWWU", + # :server_certificate_name=>"KdCert1", + # :upload_date=>"2010-12-09T13:21:07Z", + # :path=>"/kdcert/", + # :certificate_chain=>"", + # :arn=>"arn:aws:iam::600000000007:server-certificate/kdcert/KdCert1"} + # + def get_server_certificate(server_certificate_name) + request_hash = { 'ServerCertificateName' => server_certificate_name} + link = generate_request("GetServerCertificate", request_hash) + request_info(link, GetServerCertificateParser.new(:logger => @logger)) + end + + # Deletes the specified server certificate + # + # iam.delete_server_certificate('ProdServerCert') #=> true + # + def delete_server_certificate(server_certificate_name) + request_hash = { 'ServerCertificateName' => server_certificate_name } + link = generate_request("DeleteServerCertificate", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # Signing Certificates + #----------------------------------------------------------------- + + # Returns information about the signing certificates associated with the specified User. + # + # Options: :user_name, :max_items, :marker + # + # iam.list_signing_certificates #=> + # [{:upload_date => "2007-08-11T06:48:35Z", + # :status => "Active", + # :certificate_id => "00000000000000000000000000000000", + # :certificate_body => "-----BEGIN CERTIFICATE-----\nMIICd...PPHQ=\n-----END CERTIFICATE-----\n"}] + # + def list_signing_certificates(options={}, &block) + incrementally_list_iam_resources('ListSigningCertificates', options, &block) + end + + # Uploads an X.509 signing certificate and associates it with the specified User. + # + # Options: :user_name + # + # certificate_body =<<-EOB + # -----BEGIN CERTIFICATE----- + # MIICdzCCAeCgAwIBAgIGANc+Ha2wMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNVBAYT + # AlVTMRMwEQYDVQQKEwpBbWF6b24uY29tMQwwCgYDVQQLEwNBV1MxITAfBgNVBAMT + # GEFXUyBMaW1pdGVkLUFzc3VyYW5jZSBDQTAeFw0wOTAyMDQxNzE5MjdaFw0xMDAy + # AEaHzTpmEXAMPLE= + # EOB + # + # iam.upload_signing_certificate(certificate_body, :user_name => 'kd1') #=> + # {:user_name => "kd1", + # :certificate_id => "OBG00000000000000000000000000DHY", + # :status => "Active", + # :certificate_body => "-----BEGIN CERTIFICATE-----\nMII...5GS\n-----END CERTIFICATE-----\n", + # :upload_date => "2010-10-29T10:02:05.929Z"} + # + def upload_signing_certificate(certificate_body, options={}) + request_hash = { 'CertificateBody' => certificate_body } + request_hash['UserName'] = options[:user_name] unless options[:user_name].right_blank? + link = generate_request_impl(:post, "UploadSigningCertificate", request_hash) + request_info(link, GetSigningCertificateParser.new(:logger => @logger)) + end + + # Deletes the specified signing certificate associated with the specified User. + # + # Options: :user_name + # + # pp iam.delete_signing_certificate('OB0000000000000000000000000000HY', :user_name => 'kd1') + # + def delete_signing_certificate(certificate_id, options={}) + request_hash = { 'CertificateId' => certificate_id } + request_hash['UserName'] = options[:user_name] unless options[:user_name].right_blank? + link = generate_request("DeleteSigningCertificate", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # PARSERS: + #----------------------------------------------------------------- + + class BasicIamParser < RightAWSParser #:nodoc: + def tagstart(name, attributes) + @result ||= {} + end + def tagend(name) + if Array(@expected_tags).include?(name) + @result[name.right_underscore.to_sym] = @text + end + end + end + + class BasicIamListParser < RightAWSParser #:nodoc: + def tagstart(name, attributes) + @result ||= { :items => [] } + @item = {} if name == (@items_splitter || 'member') + end + def tagend(name) + case name + when 'Marker' then @result[:marker] = @text + when 'IsTruncated' then @result[:is_truncated] = @text == 'true' + when (@items_splitter || 'member') + @result[:items] << (@item.right_blank? ? @text : @item) + else + if Array(@expected_tags).include?(name) + @item[name.right_underscore.to_sym] = @text + end + end + end + end + + #----------------------------------------------------------------- + # Server Certificates + #----------------------------------------------------------------- + + class GetServerCertificateParser < BasicIamParser #:nodoc: + def reset + @expected_tags = %w{ Arn Path ServerCertificateId ServerCertificateName UploadDate CertificateBody CertificateChain } + end + end + + class ListServerCertificatesParser < BasicIamListParser #:nodoc: + def reset + @expected_tags = %w{ Arn Path ServerCertificateId ServerCertificateName UploadDate } + end + end + + #----------------------------------------------------------------- + # Signing Certificates + #----------------------------------------------------------------- + + class ListSigningCertificatesParser < BasicIamListParser #:nodoc: + def reset + @expected_tags = %w{ CertificateBody CertificateId Status UploadDate UserName } + end + end + + class GetSigningCertificateParser < BasicIamParser #:nodoc: + def reset + @expected_tags = %w{ CertificateBody CertificateId Status UploadDate UserName } + end + end + + end + +end diff --git a/lib/iam/right_iam_mfa_devices.rb b/lib/iam/right_iam_mfa_devices.rb new file mode 100644 index 0000000..85ea723 --- /dev/null +++ b/lib/iam/right_iam_mfa_devices.rb @@ -0,0 +1,67 @@ +module RightAws + + class IamInterface < RightAwsBase + + #----------------------------------------------------------------- + # MFADevices + #----------------------------------------------------------------- + + # Lists the MFA devices associated with the specified User name. + # + # Options: :user_name, :max_items, :marker + # + def list_mfa_devices(options={}, &block) + incrementally_list_iam_resources('ListMFADevices', options, &block) + end + + # Enables the specified MFA device and associates it with the specified User name. + # Once enabled, the MFA device is required for every subsequent login by the User name associated with the device. + # + # iam.enable_mfa_device('kd1', 'x12345', '12345', '67890') #=> true + # + def enable_mfa_device(user_name, serial_number, auth_code1, auth_code2) + request_hash = { 'UserName' => user_name, + 'SerialNumber' => serial_number, + 'AuthenticationCode1' => auth_code1, + 'AuthenticationCode2' => auth_code2 } + link = generate_request("EnableMFADevice", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + # Synchronizes the specified MFA device with AWS servers. + # + # iam.resync_mfa_device('kd1', 'x12345', '12345', '67890') #=> true + # + def resync_mfa_device(user_name, serial_number, auth_code1, auth_code2) + request_hash = { 'UserName' => user_name, + 'SerialNumber' => serial_number, + 'AuthenticationCode1' => auth_code1, + 'AuthenticationCode2' => auth_code2 } + link = generate_request("ResyncMFADevice", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + # Deactivates the specified MFA device and removes it from association with the User name for which it was originally enabled. + # + # deactivate_mfa_device('kd1', 'dev1234567890') #=> true + # + def deactivate_mfa_device(user_name, serial_number) + request_hash = { 'UserName' => user_name, + 'SerialNumber' => serial_number } + link = generate_request("DeactivateMFADevice", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # PARSERS + #----------------------------------------------------------------- + + class ListMFADevicesParser < BasicIamListParser #:nodoc: + def reset + @expected_tags = %w{ SerialNumber UserName } + end + end + + end + +end \ No newline at end of file diff --git a/lib/iam/right_iam_users.rb b/lib/iam/right_iam_users.rb new file mode 100644 index 0000000..0201533 --- /dev/null +++ b/lib/iam/right_iam_users.rb @@ -0,0 +1,251 @@ +module RightAws + + class IamInterface < RightAwsBase + + #----------------------------------------------------------------- + # Users + #----------------------------------------------------------------- + + # Lists the Users that have the specified path prefix. + # + # Options: :path_prefix, :max_items, :marker + # + # iam.list_users #=> + # [{:user_name=>"kd", + # :user_id=>"AI000000000000000006A", + # :arn=>"arn:aws:iam::640000000037:user/kd", + # :path=>"/"}] + # + def list_users(options={}, &block) + incrementally_list_iam_resources('ListUsers', options, &block) + end + + # Creates a new User for your AWS Account. + # + # Options: :path + # + # iam.create_user('kd') #=> + # {:user_name=>"kd", + # :user_id=>"AI000000000000000006A", + # :arn=>"arn:aws:iam::640000000037:user/kd", + # :path=>"/"} + # + def create_user(user_name, options={}) + request_hash = { 'UserName' => user_name } + request_hash['Path'] = options[:path] unless options[:path] + link = generate_request("CreateUser", request_hash) + request_info(link, GetUserParser.new(:logger => @logger)) + end + + # Updates the name and/or the path of the specified User. + # + # iam.update_user('kd1', :new_user_name => 'kd1', :new_path => '/kd1/') #=> true + # + def update_user(user_name, options={}) + request_hash = { 'UserName' => user_name} + request_hash['NewUserName'] = options[:new_user_name] unless options[:new_user_name].right_blank? + request_hash['NewPath'] = options[:new_path] unless options[:new_path].right_blank? + link = generate_request("UpdateUser", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + # Retrieves information about the specified User, including the User's path, GUID, and ARN. + # + # iam.get_user('kd') #=> + # {:user_name=>"kd", + # :user_id=>"AI000000000000000006A", + # :arn=>"arn:aws:iam::640000000037:user/kd", + # :path=>"/"} + # + def get_user(user_name) + request_hash = { 'UserName' => user_name } + link = generate_request("GetUser", request_hash) + request_info(link, GetUserParser.new(:logger => @logger)) + end + + # Deletes the specified User. The User must not belong to any groups, have any keys or signing certificates, or have any attached policies. + # + # iam.delete_user('kd') #=> true + # + def delete_user(user_name) + request_hash = { 'UserName' => user_name } + link = generate_request("DeleteUser", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # User Policies + #----------------------------------------------------------------- + + # Lists the names of the policies associated with the specified User. + # + # Options: :max_items, :marker + # + # iam.list_user_policies('kd') #=> ["kd_user_policy_1"] + # + def list_user_policies(user_name, options={}, &block) + options[:user_name] = user_name + incrementally_list_iam_resources('ListUserPolicies', options, :parser => BasicIamListParser, &block) + end + + # Adds (or updates) a policy document associated with the specified User + # + # iam.put_user_policy('kd', 'kd_user_policy_1', %Q({"Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]})) #=> true + # + def put_user_policy(user_name, policy_name, policy_document) + request_hash = { 'UserName' => user_name, + 'PolicyDocument' => policy_document, + 'PolicyName' => policy_name } + link = generate_request_impl(:post, "PutUserPolicy", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + # Retrieves the specified policy document for the specified User. + # + # iam.get_user_policy('kd','kd_user_policy_1') #=> + # {:user_name=>"kd", + # :policy_name=>"kd_user_policy_1", + # :policy_document=>"{\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"*\",\"Resource\":\"*\"}]}"} + # + def get_user_policy(user_name, policy_name) + request_hash = { 'UserName' => user_name, + 'PolicyName' => policy_name } + link = generate_request("GetUserPolicy", request_hash) + result = request_info(link, GetUserPolicyParser.new(:logger => @logger)) + result[:policy_document] = URI::decode(result[:policy_document]) + result + end + + # Deletes the specified policy associated with the specified User. + # + # iam.delete_user_policy('kd','kd_user_policy_1') #=> true + # + def delete_user_policy(user_name, policy_name) + request_hash = { 'UserName' => user_name, + 'PolicyName' => policy_name } + link = generate_request("DeleteUserPolicy", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # User Groups + #----------------------------------------------------------------- + + # Lists the names of the policies associated with the specified group. If there are none, + # the action returns an empty list. + # + # Options: :max_items, :marker + # + # iam.list_groups_for_user('kd') #=> + # [{:group_name=>"kd_test_1", + # :group_id=>"AGP000000000000000UTY", + # :arn=>"arn:aws:iam::640000000037:group/kd1/kd_test_1", + # :path=>"/kd1/"}] + # + def list_groups_for_user(user_name, options={}, &block) + options[:user_name] = user_name + incrementally_list_iam_resources('ListGroupsForUser', options, :parser => ListGroupsParser, &block) + end + + # Adds the specified User to the specified group. + # + # iam.add_user_to_group('kd', 'kd_test_1') #=> true + # + def add_user_to_group(user_name, group_name) + request_hash = { 'UserName' => user_name, + 'GroupName' => group_name } + link = generate_request("AddUserToGroup", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + # Removes the specified User from the specified group. + # + # iam.remove_user_from_group('kd', 'kd_test_1') #=> true + # + def remove_user_from_group(user_name, group_name) + request_hash = { 'UserName' => user_name, + 'GroupName' => group_name } + link = generate_request("RemoveUserFromGroup", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # User Login Profiles + #----------------------------------------------------------------- + + # Creates a login profile for the specified User, giving the User the ability to access + # AWS services such as the AWS Management Console. + # + # iam.create_login_profile('kd','q1w2e3r4t5') #=> { :user_name => 'kd' } + # + def create_login_profile(user_name, password) + request_hash = { 'UserName' => user_name, + 'Password' => password} + link = generate_request("CreateLoginProfile", request_hash) + request_info(link, GetLoginProfileParser.new(:logger => @logger)) + end + + # Updates the login profile for the specified User. Use this API to change the User's password. + # + # update_login_profile('kd', '00000000') #=> true + # + def update_login_profile(user_name, options={}) + request_hash = { 'UserName' => user_name} + request_hash['Password'] = options[:password] unless options[:passwrod].right_blank? + link = generate_request("UpdateLoginProfile", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + # Retrieves the login profile for the specified User + # + # iam.create_login_profile('kd','q1w2e3r4t5') #=> { :user_name => 'kd' } + # + def get_login_profile(user_name) + request_hash = { 'UserName' => user_name } + link = generate_request("GetLoginProfile", request_hash) + request_info(link, GetLoginProfileParser.new(:logger => @logger)) + end + + # Deletes the login profile for the specified User, which terminates the User's ability to access + # AWS services through the IAM login page. + # + # iam.delete_login_profile('kd') #=> true + # + def delete_login_profile(user_name) + request_hash = { 'UserName' => user_name } + link = generate_request("DeleteLoginProfile", request_hash) + request_info(link, RightHttp2xxParser.new(:logger => @logger)) + end + + #----------------------------------------------------------------- + # PARSERS + #----------------------------------------------------------------- + + class ListUsersParser < BasicIamListParser #:nodoc: + def reset + @expected_tags = %w{ Arn Path UserId UserName } + end + end + + class GetUserParser < BasicIamParser #:nodoc: + def reset + @expected_tags = %w{ Arn Path UserId UserName } + end + end + + class GetUserPolicyParser < BasicIamParser #:nodoc: + def reset + @expected_tags = %w{ PolicyDocument PolicyName UserName } + end + end + + class GetLoginProfileParser < BasicIamParser #:nodoc: + def reset + @expected_tags = %w{ UserName } + end + end + + end + +end + diff --git a/lib/rds/right_rds_interface.rb b/lib/rds/right_rds_interface.rb index b9b0017..19742fb 100644 --- a/lib/rds/right_rds_interface.rb +++ b/lib/rds/right_rds_interface.rb @@ -51,7 +51,6 @@ def self.bench_service # * :server: RDS service host, default: DEFAULT_HOST # * :port: RDS service port, default: DEFAULT_PORT # * :protocol: 'http' or 'https', default: DEFAULT_PROTOCOL - # * :multi_thread: true=HTTP connection per thread, false=per process # * :logger: for log messages, default: RAILS_DEFAULT_LOGGER else STDOUT # # rds = RightAws::RdsInterface.new('xxxxxxxxxxxxxxxxxxxxx','xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', diff --git a/lib/right_aws.rb b/lib/right_aws.rb index 80b7b04..f58a467 100644 --- a/lib/right_aws.rb +++ b/lib/right_aws.rb @@ -65,6 +65,12 @@ require 'acf/right_acf_streaming_interface' require 'acf/right_acf_origin_access_identities' require 'rds/right_rds_interface' +require 'iam/right_iam_interface' +require 'iam/right_iam_groups' +require 'iam/right_iam_users' +require 'iam/right_iam_access_keys' +require 'iam/right_iam_mfa_devices' + #- # We also want everything available in the Rightscale namespace for backward diff --git a/lib/s3/right_s3.rb b/lib/s3/right_s3.rb index 459c857..7d19604 100644 --- a/lib/s3/right_s3.rb +++ b/lib/s3/right_s3.rb @@ -59,7 +59,6 @@ class S3 # {:server => 's3.amazonaws.com' # Amazon service host: 's3.amazonaws.com'(default) # :port => 443 # Amazon service port: 80 or 443(default) # :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default) - # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default) # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted } def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={}) @interface = S3Interface.new(aws_access_key_id, aws_secret_access_key, params) diff --git a/lib/s3/right_s3_interface.rb b/lib/s3/right_s3_interface.rb index f93015b..bf816fc 100644 --- a/lib/s3/right_s3_interface.rb +++ b/lib/s3/right_s3_interface.rb @@ -63,14 +63,13 @@ def param(name) # Creates new RightS3 instance. # - # s3 = RightAws::S3Interface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX', {:multi_thread => true, :logger => Logger.new('/tmp/x.log')}) #=> # + # s3 = RightAws::S3Interface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX', {:logger => Logger.new('/tmp/x.log')}) #=> # # # Params is a hash: # # {:server => 's3.amazonaws.com' # Amazon service host: 's3.amazonaws.com'(default) # :port => 443 # Amazon service port: 80 or 443(default) # :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default) - # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default) # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted } # def initialize(aws_access_key_id=nil, aws_secret_access_key=nil, params={}) diff --git a/lib/sdb/active_sdb.rb b/lib/sdb/active_sdb.rb index ee5fea9..cbbafb1 100644 --- a/lib/sdb/active_sdb.rb +++ b/lib/sdb/active_sdb.rb @@ -152,7 +152,6 @@ def connection # :port => 443 # Amazon service port: 80 or 443(default) # :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default) # :signature_version => '0' # The signature version : '0' or '1'(default) - # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default) # :logger => Logger Object # Logger instance: logs to STDOUT if omitted # :nil_representation => 'mynil'} # interpret Ruby nil as this string value; i.e. use this string in SDB to represent Ruby nils (default is the string 'nil') diff --git a/lib/sdb/right_sdb_interface.rb b/lib/sdb/right_sdb_interface.rb index f712c69..44717d7 100644 --- a/lib/sdb/right_sdb_interface.rb +++ b/lib/sdb/right_sdb_interface.rb @@ -49,13 +49,12 @@ def self.bench_sdb; @@bench.service; end # :port => 443 # Amazon service port: 80 or 443(default) # :protocol => 'https' # Amazon service protocol: 'http' or 'https'(default) # :signature_version => '0' # The signature version : '0','1 or '2'(default) - # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default) # :logger => Logger Object # Logger instance: logs to STDOUT if omitted # :nil_representation => 'mynil'} # interpret Ruby nil as this string value; i.e. use this string in SDB to represent Ruby nils (default is the string 'nil') # # Example: # - # sdb = RightAws::SdbInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX', {:multi_thread => true, :logger => Logger.new('/tmp/x.log')}) #=> # + # sdb = RightAws::SdbInterface.new('1E3GDYEOGFJPIT7XXXXXX','hgTHt68JY07JKUY08ftHYtERkjgtfERn57XXXXXX', {:logger => Logger.new('/tmp/x.log')}) #=> # # # see: http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/ # diff --git a/lib/sqs/right_sqs.rb b/lib/sqs/right_sqs.rb index 13decbf..22b337c 100644 --- a/lib/sqs/right_sqs.rb +++ b/lib/sqs/right_sqs.rb @@ -59,7 +59,6 @@ module RightAws # # {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com' (default) # :port => 443 # Amazon service port: 80 or 443 (default) - # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default) # :signature_version => '0' # The signature version : '0' or '1'(default) # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted } # diff --git a/lib/sqs/right_sqs_gen2.rb b/lib/sqs/right_sqs_gen2.rb index 1f9ff48..8575c57 100644 --- a/lib/sqs/right_sqs_gen2.rb +++ b/lib/sqs/right_sqs_gen2.rb @@ -60,7 +60,6 @@ module RightAws # # {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com' (default) # :port => 443 # Amazon service port: 80 or 443 (default) - # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default) # :signature_version => '0' # The signature version : '0' or '1'(default) # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted } class SqsGen2 diff --git a/lib/sqs/right_sqs_gen2_interface.rb b/lib/sqs/right_sqs_gen2_interface.rb index 2928ae0..8bf1758 100644 --- a/lib/sqs/right_sqs_gen2_interface.rb +++ b/lib/sqs/right_sqs_gen2_interface.rb @@ -65,13 +65,12 @@ def self.api # Amazon's article "Migrating to Amazon SQS API version 2008-01-01" at: # http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1148 # - # sqs = RightAws::SqsGen2Interface.new('1E3GDYEOGFJPIT75KDT40','hgTHt68JY07JKUY08ftHYtERkjgtfERn57DFE379', {:multi_thread => true, :logger => Logger.new('/tmp/x.log')}) + # sqs = RightAws::SqsGen2Interface.new('1E3GDYEOGFJPIT75KDT40','hgTHt68JY07JKUY08ftHYtERkjgtfERn57DFE379', {:logger => Logger.new('/tmp/x.log')}) # # Params is a hash: # # {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com' (default) # :port => 443 # Amazon service port: 80 or 443 (default) - # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false (default) # :signature_version => '0' # The signature version : '0', '1' or '2'(default) # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted } # diff --git a/lib/sqs/right_sqs_interface.rb b/lib/sqs/right_sqs_interface.rb index e9c4723..5e50b78 100644 --- a/lib/sqs/right_sqs_interface.rb +++ b/lib/sqs/right_sqs_interface.rb @@ -49,13 +49,12 @@ def self.api # Creates a new SqsInterface instance. # - # sqs = RightAws::SqsInterface.new('1E3GDYEOGFJPIT75KDT40','hgTHt68JY07JKUY08ftHYtERkjgtfERn57DFE379', {:multi_thread => true, :logger => Logger.new('/tmp/x.log')}) + # sqs = RightAws::SqsInterface.new('1E3GDYEOGFJPIT75KDT40','hgTHt68JY07JKUY08ftHYtERkjgtfERn57DFE379', {:logger => Logger.new('/tmp/x.log')}) # # Params is a hash: # # {:server => 'queue.amazonaws.com' # Amazon service host: 'queue.amazonaws.com'(default) # :port => 443 # Amazon service port: 80 or 443(default) - # :multi_thread => true|false # Multi-threaded (connection per each thread): true or false(default) # :signature_version => '0' # The signature version : '0', '1' or '2'(default) # :logger => Logger Object} # Logger instance: logs to STDOUT if omitted } # diff --git a/test/sqs/test_right_sqs.rb b/test/sqs/test_right_sqs.rb index ea780e8..b13c7be 100644 --- a/test/sqs/test_right_sqs.rb +++ b/test/sqs/test_right_sqs.rb @@ -273,12 +273,6 @@ def test_27_set_amazon_problems assert_nil(Rightscale::SqsInterface.amazon_problems) end - def test_28_check_threading_model - assert(!@sqs.multi_thread) - newsqs = Rightscale::SqsInterface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key, {:multi_thread => true}) - assert(newsqs.multi_thread) - end - def test_29_signature_version_0 sqs = Rightscale::SqsInterface.new(TestCredentials.aws_access_key_id, TestCredentials.aws_secret_access_key, :signature_version => '0') assert_nothing_raised do