lib/akami/wsse.rb in akami-1.0.0 vs lib/akami/wsse.rb in akami-1.1.0
- old
+ new
@@ -1,10 +1,16 @@
require "base64"
require "digest/sha1"
-require "akami/core_ext/time"
+require "akami/core_ext/hash"
+require "akami/xpath_helper"
+require "akami/c14n_helper"
+require "time"
require "gyoku"
+require "akami/wsse/verify_signature"
+require "akami/wsse/signature"
+
module Akami
# = Akami::WSSE
#
# Building Web Service Security.
@@ -38,12 +44,20 @@
self.username = username
self.password = password
self.digest = digest
end
- attr_accessor :username, :password, :created_at, :expires_at
+ attr_accessor :username, :password, :created_at, :expires_at, :signature, :verify_response
+ def sign_with=(klass)
+ @signature = klass
+ end
+
+ def signature?
+ !!@signature
+ end
+
# Returns whether to use WSSE digest. Defaults to +false+.
def digest?
!!@digest
end
@@ -62,13 +76,24 @@
# Sets whether to generate a wsu:Timestamp header.
def timestamp=(timestamp)
@wsu_timestamp = timestamp
end
+ # Hook for Soap::XML that allows us to add attributes to the env:Body tag
+ def body_attributes
+ if signature?
+ signature.body_attributes
+ else
+ {}
+ end
+ end
+
# Returns the XML for a WSSE header.
def to_xml
- if username_token? && timestamp?
+ if signature? and signature.have_document?
+ Gyoku.xml wsse_signature.merge!(hash)
+ elsif username_token? && timestamp?
Gyoku.xml wsse_username_token.merge!(wsu_timestamp) {
|key, v1, v2| v1.merge!(v2) {
|key, v1, v2| v1.merge!(v2)
}
}
@@ -98,27 +123,49 @@
"wsse:Password" => password,
:attributes! => { "wsse:Password" => { "Type" => PASSWORD_TEXT_URI } }
end
end
+ def wsse_signature
+ signature_hash = signature.to_token
+
+ # First key/value is tag/hash
+ tag, hash = signature_hash.shift
+
+ security_hash nil, tag, hash, signature_hash
+ end
+
# Returns a Hash containing wsu:Timestamp details.
def wsu_timestamp
security_hash :wsu, "Timestamp",
- "wsu:Created" => (created_at || Time.now).xs_datetime,
- "wsu:Expires" => (expires_at || (created_at || Time.now) + 60).xs_datetime
+ "wsu:Created" => (created_at || Time.now).utc.xmlschema,
+ "wsu:Expires" => (expires_at || (created_at || Time.now) + 60).utc.xmlschema
end
# Returns a Hash containing wsse/wsu Security details for a given
# +namespace+, +tag+ and +hash+.
- def security_hash(namespace, tag, hash)
- {
+ def security_hash(namespace, tag, hash, extra_info = {})
+ key = [namespace, tag].compact.join(":")
+
+ sec_hash = {
"wsse:Security" => {
- "#{namespace}:#{tag}" => hash,
- :attributes! => { "#{namespace}:#{tag}" => { "wsu:Id" => "#{tag}-#{count}", "xmlns:wsu" => WSU_NAMESPACE } }
+ key => hash
},
:attributes! => { "wsse:Security" => { "xmlns:wsse" => WSE_NAMESPACE } }
}
+
+ unless extra_info.empty?
+ sec_hash["wsse:Security"].merge!(extra_info)
+ end
+
+ if signature?
+ sec_hash[:attributes!].merge!("soapenv:mustUnderstand" => "1")
+ else
+ sec_hash["wsse:Security"].merge!(:attributes! => { key => { "wsu:Id" => "#{tag}-#{count}", "xmlns:wsu" => WSU_NAMESPACE } })
+ end
+
+ sec_hash
end
# Returns the WSSE password, encrypted for digest authentication.
def digest_password
token = nonce + timestamp + password
@@ -135,10 +182,10 @@
(0...100).map { ("a".."z").to_a[rand(26)] }.join
end
# Returns a WSSE timestamp.
def timestamp
- @timestamp ||= Time.now.xs_datetime
+ @timestamp ||= Time.now.xmlschema
end
# Returns a new number with every call.
def count
@count ||= 0