elastic-mapreduce 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/CHANGELOG +51 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +16 -0
- data/LICENSE.txt +393 -0
- data/NOTICE.txt +26 -0
- data/README +1007 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/bin/elastic-mapreduce +27 -0
- data/cacert.pem +280 -0
- data/elastic-mapreduce.gemspec +104 -0
- data/lib/amazon/aws/exceptions.rb +211 -0
- data/lib/amazon/coral/awsquery.rb +128 -0
- data/lib/amazon/coral/awsquerychainhelper.rb +92 -0
- data/lib/amazon/coral/awsqueryhandler.rb +170 -0
- data/lib/amazon/coral/awsqueryurihandler.rb +34 -0
- data/lib/amazon/coral/call.rb +68 -0
- data/lib/amazon/coral/dispatcher.rb +33 -0
- data/lib/amazon/coral/ec2client.rb +91 -0
- data/lib/amazon/coral/elasticmapreduceclient.rb +198 -0
- data/lib/amazon/coral/handler.rb +20 -0
- data/lib/amazon/coral/httpdelegationhelper.rb +27 -0
- data/lib/amazon/coral/httpdestinationhandler.rb +36 -0
- data/lib/amazon/coral/httphandler.rb +124 -0
- data/lib/amazon/coral/identityhandler.rb +32 -0
- data/lib/amazon/coral/job.rb +25 -0
- data/lib/amazon/coral/logfactory.rb +35 -0
- data/lib/amazon/coral/option.rb +70 -0
- data/lib/amazon/coral/orchestrator.rb +49 -0
- data/lib/amazon/coral/querystringmap.rb +93 -0
- data/lib/amazon/coral/service.rb +130 -0
- data/lib/amazon/coral/simplelog.rb +98 -0
- data/lib/amazon/coral/urlencoding.rb +19 -0
- data/lib/amazon/coral/v0signaturehandler.rb +33 -0
- data/lib/amazon/coral/v0signaturehelper.rb +83 -0
- data/lib/amazon/coral/v1signaturehandler.rb +32 -0
- data/lib/amazon/coral/v1signaturehelper.rb +58 -0
- data/lib/amazon/coral/v2signaturehandler.rb +46 -0
- data/lib/amazon/coral/v2signaturehelper.rb +76 -0
- data/lib/amazon/retry_delegator.rb +66 -0
- data/lib/amazon/stderr_logger.rb +23 -0
- data/lib/client.rb +117 -0
- data/lib/commands.rb +1690 -0
- data/lib/credentials.rb +86 -0
- data/lib/ec2_client_wrapper.rb +73 -0
- data/lib/json/lexer.rb +294 -0
- data/lib/json/objects.rb +200 -0
- data/lib/json.rb +58 -0
- data/lib/simple_executor.rb +11 -0
- data/lib/simple_logger.rb +38 -0
- data/lib/uuidtools/version.rb +32 -0
- data/lib/uuidtools.rb +655 -0
- data/run_tests.rb +8 -0
- data/samples/freebase/code/freebase_jobflow.json +44 -0
- data/samples/similarity/lastfm_jobflow.json +78 -0
- data/samples/wordSplitter.py +18 -0
- data/tests/commands_test.rb +587 -0
- data/tests/credentials.json +7 -0
- data/tests/example.json +14 -0
- metadata +154 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
require 'amazon/coral/urlencoding'
|
|
5
|
+
|
|
6
|
+
module Amazon
|
|
7
|
+
module Coral
|
|
8
|
+
|
|
9
|
+
# A hash containing query string parameters that produces a query
|
|
10
|
+
# string via to_s. Also consumes hashes representing hierarchies of
|
|
11
|
+
# data to encode as query parameters.
|
|
12
|
+
class QueryStringMap < Hash
|
|
13
|
+
|
|
14
|
+
# Instantiate a QueryStringMap with the contents of the specified
|
|
15
|
+
# hash. If no hash is provided, an empty map is created.
|
|
16
|
+
def initialize(hash = {})
|
|
17
|
+
add_flattened(hash)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns the query string representation of this map by collapsing
|
|
21
|
+
# its key-value pairs into URL parameters.
|
|
22
|
+
def to_s
|
|
23
|
+
qstr = ''
|
|
24
|
+
isFirst = true
|
|
25
|
+
each_pair { |k,v|
|
|
26
|
+
if isFirst then
|
|
27
|
+
isFirst = false
|
|
28
|
+
else
|
|
29
|
+
qstr << '&'
|
|
30
|
+
end
|
|
31
|
+
qstr << UrlEncoding.encode(k.to_s)
|
|
32
|
+
unless(v.nil?) then
|
|
33
|
+
qstr << '='
|
|
34
|
+
qstr << UrlEncoding.encode(v.to_s)
|
|
35
|
+
end
|
|
36
|
+
}
|
|
37
|
+
return qstr
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
def add_flattened(hash)
|
|
42
|
+
stack = []
|
|
43
|
+
add_flattened_helper(stack, hash)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def add_flattened_helper(stack, obj)
|
|
47
|
+
return if obj.nil?
|
|
48
|
+
|
|
49
|
+
case obj
|
|
50
|
+
when Hash
|
|
51
|
+
|
|
52
|
+
obj.each_pair { |k,v|
|
|
53
|
+
stack.push(k)
|
|
54
|
+
add_flattened_helper(stack, v)
|
|
55
|
+
stack.pop
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
when Array
|
|
59
|
+
|
|
60
|
+
# Do artificial list member wrapping (Coral requires this
|
|
61
|
+
# level of indirection, but doesn't validate the member name)
|
|
62
|
+
stack.push("member")
|
|
63
|
+
|
|
64
|
+
obj.each_index { |i|
|
|
65
|
+
v = obj[i]
|
|
66
|
+
stack.push(i + 1) # query string arrays are 1-based
|
|
67
|
+
add_flattened_helper(stack, v)
|
|
68
|
+
stack.pop
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
stack.pop
|
|
72
|
+
|
|
73
|
+
else
|
|
74
|
+
|
|
75
|
+
# this works for symbols also, because sym.id2name == sym.to_s
|
|
76
|
+
self[get_key(stack)] = obj.to_s
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def get_key(stack)
|
|
82
|
+
key = ''
|
|
83
|
+
stack.each_index { |i|
|
|
84
|
+
key << '.' if(i > 0)
|
|
85
|
+
key << stack[i].to_s
|
|
86
|
+
}
|
|
87
|
+
return key
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
require 'amazon/coral/option'
|
|
5
|
+
require 'amazon/coral/orchestrator'
|
|
6
|
+
require 'amazon/coral/dispatcher'
|
|
7
|
+
require 'amazon/coral/call'
|
|
8
|
+
require 'amazon/coral/awsquery'
|
|
9
|
+
require 'amazon/coral/simplelog'
|
|
10
|
+
|
|
11
|
+
module Amazon
|
|
12
|
+
module Coral
|
|
13
|
+
|
|
14
|
+
# Provides a simple command-line interface to call remote services.
|
|
15
|
+
class Service
|
|
16
|
+
|
|
17
|
+
@@command_arguments = [
|
|
18
|
+
Option.new({:long => 'help', :short => 'h'}),
|
|
19
|
+
Option.new({:long => 'url', :short => 'u', :parameters => 1}),
|
|
20
|
+
Option.new({:long => 'awsAccessKey', :short => 'a', :parameters => 1}),
|
|
21
|
+
Option.new({:long => 'awsSecretKey', :short => 's', :parameters => 1}),
|
|
22
|
+
Option.new({:long => 'v0'}),
|
|
23
|
+
Option.new({:long => 'v1'}),
|
|
24
|
+
Option.new({:long => 'timeout', :parameters => 1}),
|
|
25
|
+
Option.new({:long => 'connect_timeout', :parameters => 1}),
|
|
26
|
+
Option.new({:long => 'input', :short => 'i', :parameters => 1}),
|
|
27
|
+
Option.new({:long => 'operation', :short => 'o', :parameters => 1}),
|
|
28
|
+
Option.new({:long => 'verbose', :short => 'v'})];
|
|
29
|
+
|
|
30
|
+
# Initializes a Service object with the specified arguments.
|
|
31
|
+
# Possible arguments include:
|
|
32
|
+
# [:orchestrator_helper]
|
|
33
|
+
# A class that responds to self.new_orchestrator create the necessary orchestrator.
|
|
34
|
+
# By default the AwsQueryChainHelper is used.
|
|
35
|
+
# [:service]
|
|
36
|
+
# The name of the service to be called.
|
|
37
|
+
# [:operations]
|
|
38
|
+
# A list naming the operations available on the remote service.
|
|
39
|
+
def initialize(args)
|
|
40
|
+
@orchestrator_helper_class = args[:orchestrator_helper]
|
|
41
|
+
@orchestrator_helper_class = AwsQuery if @orchestrator_helper_class.nil?
|
|
42
|
+
|
|
43
|
+
@service_name = args[:service]
|
|
44
|
+
@operation_names = args[:operations]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Runs the command line client application.
|
|
48
|
+
def main
|
|
49
|
+
|
|
50
|
+
if ARGV.length == 0 then
|
|
51
|
+
print_usage
|
|
52
|
+
exit
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
args = Option.parse(@@command_arguments, ARGV)
|
|
56
|
+
if(args.length == 0 || !args['help'].nil?) then
|
|
57
|
+
print_usage
|
|
58
|
+
exit
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
raise "the 'url' parameter is required" if(args['url'].nil?)
|
|
64
|
+
url = args['url'][0]
|
|
65
|
+
|
|
66
|
+
input = nil
|
|
67
|
+
input = eval(args['input'][0]) unless args['input'].nil?
|
|
68
|
+
|
|
69
|
+
raise "the 'operation' parameter is required" if(args['operation'].nil?)
|
|
70
|
+
operation = args['operation'][0]
|
|
71
|
+
raise "operation '#{operation}' is not valid for this service" unless @operation_names.include?(operation)
|
|
72
|
+
|
|
73
|
+
verbose = !args['verbose'].nil?
|
|
74
|
+
|
|
75
|
+
timeout = Float(args['timeout'][0]) unless args['timeout'].nil?
|
|
76
|
+
connect_timeout = Float(args['connect_timeout'][0]) unless args['connect_timeout'].nil?
|
|
77
|
+
|
|
78
|
+
aws_access_key = nil
|
|
79
|
+
aws_secret_key = nil
|
|
80
|
+
signature_algorithm = nil
|
|
81
|
+
|
|
82
|
+
if(!args['awsAccessKey'].nil? && !args['awsSecretKey'].nil?) then
|
|
83
|
+
aws_access_key = args['awsAccessKey'][0]
|
|
84
|
+
aws_secret_key = args['awsSecretKey'][0]
|
|
85
|
+
signature_algorithm = :V2
|
|
86
|
+
signature_algorithm = :V0 if !args['v0'].nil?
|
|
87
|
+
signature_algorithm = :V1 if !args['v1'].nil?
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
helper_args = {:endpoint => url, :signature_algorithm => signature_algorithm, :verbose => verbose, :timeout => timeout, :connect_timeout => connect_timeout}
|
|
91
|
+
|
|
92
|
+
orchestrator = @orchestrator_helper_class.new_orchestrator(helper_args)
|
|
93
|
+
dispatcher = Dispatcher.new(orchestrator, @service_name, operation)
|
|
94
|
+
call = Call.new(dispatcher)
|
|
95
|
+
|
|
96
|
+
call.identity[:aws_access_key] = aws_access_key
|
|
97
|
+
call.identity[:aws_secret_key] = aws_secret_key
|
|
98
|
+
|
|
99
|
+
output = call.call(input)
|
|
100
|
+
|
|
101
|
+
puts output.inspect
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# Prints to STDOUT a help message describing how to use the application.
|
|
107
|
+
def print_usage
|
|
108
|
+
puts "#{@service_name} ruby client"
|
|
109
|
+
puts "Usage:"
|
|
110
|
+
puts " -h --help"
|
|
111
|
+
puts " -u --url"
|
|
112
|
+
puts " -o --operation OPERATION"
|
|
113
|
+
puts " -i --input INPUT"
|
|
114
|
+
puts " -a --awsAccessKey KEY"
|
|
115
|
+
puts " -s --awsSecretKey SECRET_KEY"
|
|
116
|
+
puts " --v0"
|
|
117
|
+
puts " --v1"
|
|
118
|
+
puts " -v --verbose"
|
|
119
|
+
puts ""
|
|
120
|
+
puts "Available operations:"
|
|
121
|
+
@operation_names.each { |name|
|
|
122
|
+
puts(" #{name}")
|
|
123
|
+
} unless @operation_names.nil?
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
require 'amazon/coral/logfactory'
|
|
5
|
+
require 'logger'
|
|
6
|
+
|
|
7
|
+
module Amazon
|
|
8
|
+
module Coral
|
|
9
|
+
|
|
10
|
+
# Wraps Ruby's built in Logger to prepend a context string to log messages.
|
|
11
|
+
# This is useful to prefix log messages with the name of the originating class, etc.
|
|
12
|
+
class WrappedLogger
|
|
13
|
+
def initialize(key, logger)
|
|
14
|
+
@key = key
|
|
15
|
+
@logger = logger
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def debug(s)
|
|
19
|
+
@logger.debug(format(s))
|
|
20
|
+
end
|
|
21
|
+
def info(s)
|
|
22
|
+
@logger.info(format(s))
|
|
23
|
+
end
|
|
24
|
+
def warn(s)
|
|
25
|
+
@logger.warn(format(s))
|
|
26
|
+
end
|
|
27
|
+
def error(s)
|
|
28
|
+
@logger.error(format(s))
|
|
29
|
+
end
|
|
30
|
+
def fatal(s)
|
|
31
|
+
@logger.fatal(format(s))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def debug?
|
|
35
|
+
@logger.debug?
|
|
36
|
+
end
|
|
37
|
+
def info?
|
|
38
|
+
@logger.info?
|
|
39
|
+
end
|
|
40
|
+
def warn?
|
|
41
|
+
@logger.warn?
|
|
42
|
+
end
|
|
43
|
+
def error?
|
|
44
|
+
@logger.error?
|
|
45
|
+
end
|
|
46
|
+
def fatal?
|
|
47
|
+
@logger.fatal?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def format(s)
|
|
51
|
+
return "#{@key}: #{s}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# Provides a LogFactory implementation that supplies WrappedLogger objects to requestors.
|
|
57
|
+
# The key provided to getLog is prepended to log messages from each Logger.
|
|
58
|
+
#
|
|
59
|
+
# Copyright:: Copyright (c) 2008 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
60
|
+
#
|
|
61
|
+
class SimpleLogFactory < LogFactory
|
|
62
|
+
def initialize(output, level)
|
|
63
|
+
@output = output
|
|
64
|
+
@level = level
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def getLog(key)
|
|
68
|
+
logger = Logger.new(@output)
|
|
69
|
+
logger.level = @level
|
|
70
|
+
|
|
71
|
+
return WrappedLogger.new(key, logger)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
#
|
|
76
|
+
# Provides a straightforward facility to configure SimpleLog as the active logging mechanism.
|
|
77
|
+
#
|
|
78
|
+
# Copyright:: Copyright (c) 2008 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
79
|
+
#
|
|
80
|
+
class SimpleLog
|
|
81
|
+
# Registers a SimpleLogFactory with the specified output IO object and logging level.
|
|
82
|
+
#
|
|
83
|
+
# To set logging to its highest level and send output to the console, use:
|
|
84
|
+
# SimpleLog.install(STDOUT, Logger:DEBUG)
|
|
85
|
+
#
|
|
86
|
+
# To send logging output to a file:
|
|
87
|
+
# SimpleLog.install(File.new('/tmp/simplelog.log', 'r'), Logger::INFO)
|
|
88
|
+
#
|
|
89
|
+
# Installing a new LogFactory will not affect objects that have already retrieved their log instances,
|
|
90
|
+
# it's best to initialize logging as early as possible in your code to ensure that all your code gets
|
|
91
|
+
# the proper configuration.
|
|
92
|
+
def SimpleLog.install(output, level)
|
|
93
|
+
LogFactory.setInstance(SimpleLogFactory.new(output, level))
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
require 'cgi'
|
|
4
|
+
|
|
5
|
+
module Amazon
|
|
6
|
+
module Coral
|
|
7
|
+
|
|
8
|
+
# Performs AWS's preferred method of URLEncoding.
|
|
9
|
+
class UrlEncoding
|
|
10
|
+
|
|
11
|
+
# Convert a string into URL encoded form.
|
|
12
|
+
def UrlEncoding.encode(plaintext)
|
|
13
|
+
CGI.escape(plaintext.to_s).gsub("+", "%20").gsub("%7E", "~")
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'base64'
|
|
6
|
+
require 'time'
|
|
7
|
+
require 'amazon/coral/handler'
|
|
8
|
+
require 'amazon/coral/v0signaturehelper'
|
|
9
|
+
|
|
10
|
+
module Amazon
|
|
11
|
+
module Coral
|
|
12
|
+
|
|
13
|
+
# Applies an AWS version 0 signature to the outgoing request.
|
|
14
|
+
class V0SignatureHandler < Handler
|
|
15
|
+
|
|
16
|
+
def before(job)
|
|
17
|
+
request = job.request
|
|
18
|
+
identity = request[:identity]
|
|
19
|
+
aws_access_key = identity[:aws_access_key]
|
|
20
|
+
aws_secret_key = identity[:aws_secret_key]
|
|
21
|
+
|
|
22
|
+
query_string_map = request[:query_string_map]
|
|
23
|
+
|
|
24
|
+
return if aws_access_key.nil? || aws_secret_key.nil? || query_string_map.nil?;
|
|
25
|
+
|
|
26
|
+
V0SignatureHelper.new(aws_access_key, aws_secret_key).sign({:query_string_map => query_string_map})
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'base64'
|
|
6
|
+
require 'time'
|
|
7
|
+
|
|
8
|
+
module Amazon
|
|
9
|
+
module Coral
|
|
10
|
+
|
|
11
|
+
# Performs AWS V0 Signatures on QueryStringMap objects.
|
|
12
|
+
class V0SignatureHelper
|
|
13
|
+
def initialize(aws_access_key_id, aws_secret_key)
|
|
14
|
+
@aws_access_key_id = aws_access_key_id.to_s
|
|
15
|
+
@aws_secret_key = aws_secret_key.to_s
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def sign(args)
|
|
19
|
+
signT(Time.now.iso8601, args)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def signT(time, args)
|
|
23
|
+
query_string_map = args[:query_string_map]
|
|
24
|
+
add_fields(query_string_map, time)
|
|
25
|
+
query_string_map['Signature'] = compute_signature(canonicalize(args))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def canonicalize(args)
|
|
29
|
+
query_string_map = args[:query_string_map]
|
|
30
|
+
|
|
31
|
+
service_name = query_string_map['ServiceName']
|
|
32
|
+
action = query_string_map['Action']
|
|
33
|
+
operation = query_string_map['Operation']
|
|
34
|
+
timestamp = query_string_map['Timestamp']
|
|
35
|
+
expires = query_string_map['Expires']
|
|
36
|
+
credential = query_string_map['Credential']
|
|
37
|
+
|
|
38
|
+
canonical = ''
|
|
39
|
+
|
|
40
|
+
canonical << service_name unless service_name.nil?
|
|
41
|
+
|
|
42
|
+
if !action.nil? then
|
|
43
|
+
canonical << action
|
|
44
|
+
elsif !operation.nil? then
|
|
45
|
+
canonical << operation
|
|
46
|
+
else
|
|
47
|
+
raise 'Query string must contain Action or Operation'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if timestamp.nil? and expires.nil? then
|
|
51
|
+
raise 'Query string must contain Timestamp or Expires'
|
|
52
|
+
elsif !timestamp.nil? and !expires.nil? then
|
|
53
|
+
raise 'Query string may contain only one of Timestamp or Expires'
|
|
54
|
+
elsif !timestamp.nil? then
|
|
55
|
+
canonical << timestamp
|
|
56
|
+
else
|
|
57
|
+
canonical << expires
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
canonical << credential unless credential.nil?
|
|
61
|
+
|
|
62
|
+
return canonical
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def compute_signature(canonical)
|
|
66
|
+
digest = OpenSSL::Digest::Digest.new('sha1')
|
|
67
|
+
return Base64.encode64(OpenSSL::HMAC.digest(digest, @aws_secret_key, canonical)).strip
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def add_fields(query_string_map, time)
|
|
71
|
+
query_string_map['AWSAccessKeyId'] = @aws_access_key_id
|
|
72
|
+
query_string_map['SignatureVersion'] = '0'
|
|
73
|
+
query_string_map['SignatureMethod'] = 'HmacSHA1'
|
|
74
|
+
query_string_map['Timestamp'] = time.to_s
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def sort(hash)
|
|
78
|
+
hash.sort { |a,b| a[0].downcase <=> b[0].downcase }
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'base64'
|
|
6
|
+
require 'time'
|
|
7
|
+
require 'amazon/coral/handler'
|
|
8
|
+
require 'amazon/coral/v1signaturehelper'
|
|
9
|
+
|
|
10
|
+
module Amazon
|
|
11
|
+
module Coral
|
|
12
|
+
|
|
13
|
+
# Applies an AWS version 1 signature to the outgoing request.
|
|
14
|
+
class V1SignatureHandler < Handler
|
|
15
|
+
|
|
16
|
+
def before(job)
|
|
17
|
+
request = job.request
|
|
18
|
+
identity = request[:identity]
|
|
19
|
+
aws_access_key = identity[:aws_access_key]
|
|
20
|
+
aws_secret_key = identity[:aws_secret_key]
|
|
21
|
+
|
|
22
|
+
query_string_map = request[:query_string_map]
|
|
23
|
+
|
|
24
|
+
return if aws_access_key.nil? || aws_secret_key.nil? || query_string_map.nil?;
|
|
25
|
+
|
|
26
|
+
V1SignatureHelper.new(aws_access_key, aws_secret_key).sign({:query_string_map => query_string_map})
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'base64'
|
|
6
|
+
require 'time'
|
|
7
|
+
|
|
8
|
+
module Amazon
|
|
9
|
+
module Coral
|
|
10
|
+
class V1SignatureHelper
|
|
11
|
+
def initialize(aws_access_key_id, aws_secret_key)
|
|
12
|
+
@aws_access_key_id = aws_access_key_id.to_s
|
|
13
|
+
@aws_secret_key = aws_secret_key.to_s
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def sign(args)
|
|
17
|
+
signT(Time.now.iso8601, args)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def signT(time, args)
|
|
21
|
+
query_string_map = args[:query_string_map]
|
|
22
|
+
add_fields(query_string_map, time)
|
|
23
|
+
query_string_map['Signature'] = compute_signature(canonicalize(args))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def canonicalize(args)
|
|
27
|
+
query_string_map = args[:query_string_map]
|
|
28
|
+
|
|
29
|
+
# exclude any existing Signature parameter from the canonical string
|
|
30
|
+
sorted = sort(query_string_map.reject { |k, v| k == 'Signature' })
|
|
31
|
+
|
|
32
|
+
canonical = ''
|
|
33
|
+
sorted.each do |v|
|
|
34
|
+
canonical << v[0]
|
|
35
|
+
canonical << v[1] unless(v[1].nil?)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
return canonical
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def compute_signature(canonical)
|
|
42
|
+
digest = OpenSSL::Digest::Digest.new('sha1')
|
|
43
|
+
return Base64.encode64(OpenSSL::HMAC.digest(digest, @aws_secret_key, canonical)).strip
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def add_fields(query_string_map, time)
|
|
47
|
+
query_string_map['AWSAccessKeyId'] = @aws_access_key_id
|
|
48
|
+
query_string_map['SignatureVersion'] = '1'
|
|
49
|
+
query_string_map['SignatureMethod'] = 'HmacSHA1'
|
|
50
|
+
query_string_map['Timestamp'] = time.to_s
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def sort(hash)
|
|
54
|
+
hash.sort { |a,b| a[0].downcase <=> b[0].downcase }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'base64'
|
|
6
|
+
require 'time'
|
|
7
|
+
require 'amazon/coral/handler'
|
|
8
|
+
require 'amazon/coral/v2signaturehelper'
|
|
9
|
+
require 'amazon/coral/logfactory'
|
|
10
|
+
|
|
11
|
+
module Amazon
|
|
12
|
+
module Coral
|
|
13
|
+
class V2SignatureHandler < Handler
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@log = LogFactory.getLog('Amazon::Coral::V2SignatureHandler')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def before(job)
|
|
20
|
+
request = job.request
|
|
21
|
+
identity = request[:identity]
|
|
22
|
+
aws_access_key = identity[:aws_access_key]
|
|
23
|
+
aws_secret_key = identity[:aws_secret_key]
|
|
24
|
+
|
|
25
|
+
query_string_map = request[:query_string_map]
|
|
26
|
+
http_uri = request[:http_uri]
|
|
27
|
+
uri = http_uri.path
|
|
28
|
+
verb = request[:http_verb]
|
|
29
|
+
|
|
30
|
+
host = "#{http_uri.host}"
|
|
31
|
+
host << ":#{http_uri.port}" unless http_uri.port.nil?
|
|
32
|
+
|
|
33
|
+
@log.debug("uri: #{uri} verb: #{verb} host: #{host}")
|
|
34
|
+
|
|
35
|
+
return if aws_access_key.nil? || aws_secret_key.nil? || query_string_map.nil? ||
|
|
36
|
+
uri.nil? || verb.nil? || host.nil?;
|
|
37
|
+
|
|
38
|
+
V2SignatureHelper.new(aws_access_key, aws_secret_key).sign({
|
|
39
|
+
:query_string_map => query_string_map, :uri => uri, :verb => verb, :host => host
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
request[:http_host] = host
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright 2008-2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
require 'openssl'
|
|
5
|
+
require 'base64'
|
|
6
|
+
require 'time'
|
|
7
|
+
|
|
8
|
+
module Amazon
|
|
9
|
+
module Coral
|
|
10
|
+
|
|
11
|
+
# Performs AWS V2 signatures on QueryStringMap objects.
|
|
12
|
+
class V2SignatureHelper
|
|
13
|
+
def initialize(aws_access_key_id, aws_secret_key)
|
|
14
|
+
@aws_access_key_id = aws_access_key_id.to_s
|
|
15
|
+
@aws_secret_key = aws_secret_key.to_s
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def sign(args)
|
|
19
|
+
signT(Time.now.iso8601, args)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def signT(time, args)
|
|
23
|
+
query_string_map = args[:query_string_map]
|
|
24
|
+
add_fields(query_string_map, time)
|
|
25
|
+
query_string_map['Signature'] = compute_signature(canonicalize(args))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def canonicalize(args)
|
|
29
|
+
query_string_map = args[:query_string_map]
|
|
30
|
+
uri = args[:uri]
|
|
31
|
+
verb = args[:verb]
|
|
32
|
+
host = args[:host].downcase
|
|
33
|
+
|
|
34
|
+
# exclude any existing Signature parameter from the canonical string
|
|
35
|
+
sorted = sort(query_string_map.reject { |k, v| k == 'Signature' })
|
|
36
|
+
|
|
37
|
+
canonical = "#{verb}\n#{host}\n#{uri}\n"
|
|
38
|
+
isFirst = true
|
|
39
|
+
|
|
40
|
+
sorted.each { |v|
|
|
41
|
+
if(isFirst) then
|
|
42
|
+
isFirst = false
|
|
43
|
+
else
|
|
44
|
+
canonical << '&'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
canonical << UrlEncoding.encode(v[0])
|
|
48
|
+
unless(v[1].nil?) then
|
|
49
|
+
canonical << '='
|
|
50
|
+
canonical << UrlEncoding.encode(v[1])
|
|
51
|
+
end
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return canonical
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def compute_signature(canonical)
|
|
58
|
+
digest = OpenSSL::Digest::Digest.new('sha256')
|
|
59
|
+
return Base64.encode64(OpenSSL::HMAC.digest(digest, @aws_secret_key, canonical)).strip
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def add_fields(query_string_map, time)
|
|
63
|
+
query_string_map['AWSAccessKeyId'] = @aws_access_key_id
|
|
64
|
+
query_string_map['SignatureVersion'] = '2'
|
|
65
|
+
query_string_map['SignatureMethod'] = 'HmacSHA256'
|
|
66
|
+
query_string_map['Timestamp'] = time.to_s
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def sort(hash)
|
|
70
|
+
hash.sort
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|