diff --git a/lib/akami/wsse.rb b/lib/akami/wsse.rb index 7212861..1a3f30c 100644 --- a/lib/akami/wsse.rb +++ b/lib/akami/wsse.rb @@ -91,23 +91,29 @@ def body_attributes # Returns the XML for a WSSE header. def to_xml + xml = hash + 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) - } - } + xml.merge!(wsse_signature) elsif username_token? - Gyoku.xml wsse_username_token.merge!(hash) - elsif timestamp? - Gyoku.xml wsu_timestamp.merge!(hash) - else - "" + xml.merge!(wsse_username_token) end - end + if timestamp? + xml.merge!(wsu_timestamp) do |key, v1, v2| + v1.merge!(v2) do |key, v1, v2| + if v1.is_a?(Hash) && v2.is_a?(Hash) + v1.merge!(v2) + end + end + end + unless xml['wsse:Security'][:order!].nil? + xml['wsse:Security'][:order!] << 'wsu:Timestamp' + end + end + + Gyoku.xml xml + end private # Returns a Hash containing wsse:UsernameToken details. diff --git a/spec/akami/wsse_spec.rb b/spec/akami/wsse_spec.rb index 2a6c1ec..6752988 100644 --- a/spec/akami/wsse_spec.rb +++ b/spec/akami/wsse_spec.rb @@ -29,8 +29,8 @@ ) end - it "contains the namespace for Base64 Encoding type" do - expect(Akami::WSSE::BASE64_URI).to eq( + it "contains the namespace for Base64 Encoding type" do + expect(Akami::WSSE::BASE64_URI).to eq( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ) end @@ -243,7 +243,7 @@ end end - context "whith credentials and timestamp" do + context "with credentials and timestamp" do before do wsse.credentials "username", "password" wsse.timestamp = true @@ -261,6 +261,60 @@ expect(wsse.to_xml).to include("username", "password") end end + + context 'with signature' do + let(:fixtures_path) { + File.join(Bundler.root, 'spec', 'fixtures', 'akami', 'wsse', 'signature') + } + let(:xml) { fixture('akami/wsse/sample.xml') } + let(:cert_path) { File.join(fixtures_path, 'cert.pem') } + let(:signature) { + Akami::WSSE::Signature.new( + Akami::WSSE::Certs.new( + cert_file: cert_path, + private_key_file: cert_path, + private_key_password: 'password' + ) + ) + } + + before do + signature.document = xml + wsse.signature = signature + end + + it 'contains SignedInfo node' do + expect(wsse.to_xml).to include('SignedInfo') + end + it 'contains SignatureValue node' do + expect(wsse.to_xml).to include('SignatureValue') + end + it 'contains KeyInfo node' do + expect(wsse.to_xml).to include('KeyInfo') + end + + context 'with timestamp' do + before do + wsse.timestamp = true + end + it 'contains SignedInfo node' do + expect(wsse.to_xml).to include('SignedInfo') + end + it 'contains SignatureValue node' do + expect(wsse.to_xml).to include('SignatureValue') + end + it 'contains KeyInfo node' do + expect(wsse.to_xml).to include('KeyInfo') + end + it "contains a wsu:Created node" do + expect(wsse.to_xml).to include("") + end + it "contains a wsu:Expires node" do + expect(wsse.to_xml).to include("") + end + end + end + end end diff --git a/spec/fixtures/akami/wsse/sample.xml b/spec/fixtures/akami/wsse/sample.xml new file mode 100644 index 0000000..b574102 --- /dev/null +++ b/spec/fixtures/akami/wsse/sample.xml @@ -0,0 +1 @@ +Example diff --git a/spec/fixtures/akami/wsse/signature/cert.pem b/spec/fixtures/akami/wsse/signature/cert.pem new file mode 100644 index 0000000..d6f6e41 --- /dev/null +++ b/spec/fixtures/akami/wsse/signature/cert.pem @@ -0,0 +1,37 @@ +-----BEGIN CERTIFICATE----- +MIIDIjCCAougAwIBAgIJAI53JnRgJIJwMA0GCSqGSIb3DQEBBQUAMGoxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp +c2NvMQ4wDAYDVQQKEwVTYXZvbjEOMAwGA1UECxMFU2F2b24xDjAMBgNVBAMTBVNh +dm9uMB4XDTE0MTIwMjAwMTMwMloXDTI0MTEyOTAwMTMwMlowajELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x +DjAMBgNVBAoTBVNhdm9uMQ4wDAYDVQQLEwVTYXZvbjEOMAwGA1UEAxMFU2F2b24w +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM56hKF3+4SSUu8msb5HWMvp322y +QL+luJ+Lt/r/ib7EPeb4UU68b+Wf3xIa3N1+w8tDQghCR4YuEIILKH/UGC785Old +VJfikD4kxiwF4jB0RgdRK/JEG/UthHKqJID+oyijW4ws4MgZ/bWMhSbSVRioqcwe +2JElg/m2TemKJkXDAgMBAAGjgc8wgcwwHQYDVR0OBBYEFKSd+UicrRDQS2NeLSEA +Zpipjk8EMIGcBgNVHSMEgZQwgZGAFKSd+UicrRDQS2NeLSEAZpipjk8EoW6kbDBq +MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2Fu +IEZyYW5jaXNjbzEOMAwGA1UEChMFU2F2b24xDjAMBgNVBAsTBVNhdm9uMQ4wDAYD +VQQDEwVTYXZvboIJAI53JnRgJIJwMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF +BQADgYEAWI27+cDx3U53zaJROXKfQutqUZzZz9B0NzQ0vlN2h5UbACGbXH9C1wLz +MBvNjgEiK+/jHSadSDgfvADv+2hCsFw8eNgbisWiV5yvDyTqttg3cSJHz8jRDeA+ +jnvaC9Y//AoRr/WGKKU3FY40J7pQKcQNczGUzCS+ag0IO64agTs= +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A0BF079E41C9A4C1 + +rEO5mWOWbnr8uyjtfIRwW9wRo2/y1wMON2c605BkgaNeAKH/++1UC9qEhNtHfE2Q +omQkXiHfV6yt3l3dWPcnA9ToT9PRNLyoRMMC+Ds5EuEk4ypihQ8SS2xt3wqCRkwm +3/AyrRZXUnBTVzZ9D35lz1HCFfJ61UpOMN9XOZy4yUqDZVG/ybMhXilfNKgTr8xJ +StTb7ruwV/8xTiEgmcxGKJbOcDKqwsd/mW3VbDN6zOqYC0TlFc/eiCbJxMd35l6a +oRfHWHbabumcfZplqoDcOwYpRb8ZiDbu74RrDogKnpH7nnJrp8jSYueCiXGDWGFG +ZXB6f2FhsbrLEM87L8cxJO6Hk6+c39qgiP2aRICeKjUNKPOfSiPr4yP4/g3tFY2z +sI9xur3nAXoqxXBrEkEdvXiH35UfJpqOTxbAN+Ozxnj1QeLWDDE8nkMW/XRRxdCk +jeUwR5PS3sM2S/fIn7rThQSKRMxznK//cEUsMwz514HekxnKyj8rZUETcFFySxmz +lmOzDOaPNejDOgNSrlT+IDqE9YlMxLObv5l960QOjk0qBaO8e33HkgfBqENzq7Uv +Wrj3FyBlNz4vfhCZHBY0+rSgdZHM64DV0HybE7yc+mMUwrV7ish1bGb/Bek/4JF+ +lrpRuxTEQFGNTGFYa0C5zDpz9UtiSUs2X4EX74GfxCUmn7kNND+4OVrndZiEONPz +/6QffS7YG1UtahDpDzI1wOCYD9Iwg/HnmTWMcXj2Yw7jRvlG0sArw/5dNJkrmuJY +6PvFoEeZSF4qrUCDlw/BUJMaGDlhSCyTWulZZU+wWuJRTWCiDxYO1g== +-----END RSA PRIVATE KEY-----