ruby-cleverdome 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ruby-cleverdome.rb +124 -0
- metadata +77 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'savon'
|
3
|
+
require 'uuid'
|
4
|
+
require 'signed_xml'
|
5
|
+
|
6
|
+
module RubyCleverdome
|
7
|
+
class Client
|
8
|
+
def initialize(sso_endpoint, widgets_wsdl)
|
9
|
+
@sso_client = Savon.client(
|
10
|
+
endpoint: sso_endpoint,
|
11
|
+
namespace: 'urn:up-us:sso-service:service:v1',
|
12
|
+
# proxy: 'http://127.0.0.1:8888',
|
13
|
+
# log_level: :debug
|
14
|
+
)
|
15
|
+
@widgets_client = Savon.client(
|
16
|
+
wsdl: widgets_wsdl,
|
17
|
+
# proxy: 'http://127.0.0.1:8888',
|
18
|
+
element_form_default: :unqualified,
|
19
|
+
# log_level: :debug
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def auth(provider, uid, private_key_file, certificate_file)
|
24
|
+
req = create_request(provider, uid)
|
25
|
+
|
26
|
+
req = sign_request(req, private_key_file, certificate_file)
|
27
|
+
|
28
|
+
resp = saml_call(req)
|
29
|
+
resp_doc = Nokogiri::XML::Document.parse(resp)
|
30
|
+
resp_doc.remove_namespaces!
|
31
|
+
check_resp(resp_doc)
|
32
|
+
|
33
|
+
session_id = resp_doc.xpath('//Assertion//AttributeStatement//Attribute[@Name="SessionID"]//AttributeValue')[0].content
|
34
|
+
session_id
|
35
|
+
end
|
36
|
+
|
37
|
+
def widgets_call(method, locals)
|
38
|
+
response = @widgets_client.call(
|
39
|
+
method,
|
40
|
+
:attributes => { 'xmlns' => 'http://tempuri.org/' },
|
41
|
+
message: { sessionID: 'EE282ABB-7BC3-42D3-BE98-9F8CE4217A12' } .merge(locals) )
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_request(provider, uid)
|
45
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
46
|
+
xml['s'].Envelope('xmlns:s' => 'http://schemas.xmlsoap.org/soap/envelope/') {
|
47
|
+
xml['s'].Header {
|
48
|
+
xml.ActivityId(
|
49
|
+
UUID.new.generate,
|
50
|
+
'CorrelationId' => UUID.new.generate,
|
51
|
+
:xmlns => 'http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics')
|
52
|
+
}
|
53
|
+
xml['s'].Body(
|
54
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
55
|
+
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema') {
|
56
|
+
xml.AuthnRequest(
|
57
|
+
'ID' => '_' + UUID.new.generate,
|
58
|
+
'Version' => '2.0',
|
59
|
+
'IssueInstant' => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
60
|
+
'IsPassive' => false,
|
61
|
+
'ProtocolBinding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
|
62
|
+
'ProviderName' => provider,
|
63
|
+
:xmlns => 'urn:oasis:names:tc:SAML:2.0:protocol') {
|
64
|
+
xml.Issuer(
|
65
|
+
@provider,
|
66
|
+
'Format' => 'urn:oasis:names:tc:SAML:2.0:nameidformat:transient',
|
67
|
+
:xmlns => 'urn:oasis:names:tc:SAML:2.0:assertion')
|
68
|
+
xml.Signature(:xmlns => 'http://www.w3.org/2000/09/xmldsig#') {
|
69
|
+
xml.SignedInfo {
|
70
|
+
xml.CanonicalizationMethod( 'Algorithm' => 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315' ) { xml.text '' }
|
71
|
+
xml.SignatureMethod( 'Algorithm' => 'http://www.w3.org/2000/09/xmldsig#rsa-sha1' ) { xml.text '' }
|
72
|
+
xml.Reference( 'URI' => '' ) {
|
73
|
+
xml.Transforms {
|
74
|
+
xml.Transform( 'Algorithm' => 'http://www.w3.org/2000/09/xmldsig#enveloped-signature' ) { xml.text '' }
|
75
|
+
xml.Transform( 'Algorithm' => 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315' ) { xml.text '' }
|
76
|
+
}
|
77
|
+
xml.DigestMethod( 'Algorithm' => 'http://www.w3.org/2000/09/xmldsig#sha1' ) { xml.text '' }
|
78
|
+
xml.DigestValue
|
79
|
+
}
|
80
|
+
}
|
81
|
+
xml.SignatureValue
|
82
|
+
xml.KeyInfo {
|
83
|
+
xml.X509Data {
|
84
|
+
xml.X509Certificate
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
xml.Subject( :xmlns => 'urn:oasis:names:tc:SAML:2.0:assertion' ) {
|
89
|
+
xml.NameID(
|
90
|
+
uid,
|
91
|
+
'Format'=>'urn:oasis:names:tc:SAML:2.0:nameid-format:transient')
|
92
|
+
}
|
93
|
+
xml.NameIDPolicy( 'AllowCreate' => true )
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
builder.to_xml
|
100
|
+
end
|
101
|
+
|
102
|
+
def sign_request(xml, private_key_file, certificate_file)
|
103
|
+
doc = SignedXml::Document(xml)
|
104
|
+
private_key = OpenSSL::PKey::RSA.new(File.new private_key_file)
|
105
|
+
certificate = OpenSSL::X509::Certificate.new(File.read certificate_file)
|
106
|
+
doc.sign(private_key, certificate)
|
107
|
+
doc.to_xml
|
108
|
+
end
|
109
|
+
|
110
|
+
def saml_call(req)
|
111
|
+
@sso_client.call( 'GetSSO', soap_action: 'urn:up-us:sso-service:service:v1/ISSOService/GetSSO', xml: req ).to_xml
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_resp(resp_doc)
|
115
|
+
status = resp_doc.xpath('//Status//StatusCode')[0]['Value']
|
116
|
+
|
117
|
+
if status.casecmp('urn:oasis:names:tc:SAML:2.0:status:Success') != 0
|
118
|
+
raise status
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private :create_request, :sign_request, :saml_call, :check_resp
|
123
|
+
end
|
124
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-cleverdome
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alex Gorbunov
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-04-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: savon
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: signed_xml
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Ruby client to access CleverDome.
|
47
|
+
email: sanyo.gorbunov@gmail.com
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- lib/ruby-cleverdome.rb
|
53
|
+
homepage: https://github.com/SanyoGorbunov/ruby-cleverdome/
|
54
|
+
licenses: []
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.8.28
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: RubyCleverdome
|
77
|
+
test_files: []
|