omf_sfa 0.1.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/.gitignore +24 -0
- data/Gemfile +6 -0
- data/README.md +211 -0
- data/Rakefile +23 -0
- data/bin/parse_rspec.rb +167 -0
- data/etc/omf-sfa/omf-sfa-am.yaml +12 -0
- data/examples/exogeni5nodemanifest.rspec +105 -0
- data/examples/instageni5nodemanifest.rspec +150 -0
- data/lib/omf-sfa/am/am-rest/REST_API.md +301 -0
- data/lib/omf-sfa/am/am-rest/account_handler.rb +145 -0
- data/lib/omf-sfa/am/am-rest/am_rest_server.rb +255 -0
- data/lib/omf-sfa/am/am-rest/api_template.html +48 -0
- data/lib/omf-sfa/am/am-rest/config.ru +110 -0
- data/lib/omf-sfa/am/am-rest/resource_handler.rb +178 -0
- data/lib/omf-sfa/am/am-rest/rest_handler.rb +573 -0
- data/lib/omf-sfa/am/am-rest/session_authenticator.rb +130 -0
- data/lib/omf-sfa/am/am-rpc/abstract_rpc_service.rb +60 -0
- data/lib/omf-sfa/am/am-rpc/am_authorizer.rb +161 -0
- data/lib/omf-sfa/am/am-rpc/am_rpc_api.rb +450 -0
- data/lib/omf-sfa/am/am-rpc/am_rpc_service.rb +402 -0
- data/lib/omf-sfa/am/am_liaison.rb +93 -0
- data/lib/omf-sfa/am/am_manager.rb +859 -0
- data/lib/omf-sfa/am/am_runner.rb +108 -0
- data/lib/omf-sfa/am/am_scheduler.rb +146 -0
- data/lib/omf-sfa/am/am_server.rb +194 -0
- data/lib/omf-sfa/am/config.ru +122 -0
- data/lib/omf-sfa/am/credential.rb +145 -0
- data/lib/omf-sfa/am/default_authorizer.rb +44 -0
- data/lib/omf-sfa/am/privilege_credential.rb +76 -0
- data/lib/omf-sfa/am/signature.rb +37 -0
- data/lib/omf-sfa/am/user_credential.rb +56 -0
- data/lib/omf-sfa/am.rb +7 -0
- data/lib/omf-sfa/model/abstract_prop_description.rb +87 -0
- data/lib/omf-sfa/model/model_class_description.rb +145 -0
- data/lib/omf-sfa/model/model_data_prop_description.rb +28 -0
- data/lib/omf-sfa/model/model_obj_prop_description.rb +49 -0
- data/lib/omf-sfa/model/ontology.rb +169 -0
- data/lib/omf-sfa/resource/README.md +24 -0
- data/lib/omf-sfa/resource/channel.rb +49 -0
- data/lib/omf-sfa/resource/comp_group.rb +41 -0
- data/lib/omf-sfa/resource/component_lease.rb +10 -0
- data/lib/omf-sfa/resource/constants.rb +24 -0
- data/lib/omf-sfa/resource/group_component.rb +35 -0
- data/lib/omf-sfa/resource/group_membership.rb +17 -0
- data/lib/omf-sfa/resource/gurn.rb +187 -0
- data/lib/omf-sfa/resource/interface.rb +78 -0
- data/lib/omf-sfa/resource/ip.rb +48 -0
- data/lib/omf-sfa/resource/link.rb +29 -0
- data/lib/omf-sfa/resource/node.rb +75 -0
- data/lib/omf-sfa/resource/oaccount.rb +94 -0
- data/lib/omf-sfa/resource/ocomponent.rb +134 -0
- data/lib/omf-sfa/resource/ogroup.rb +106 -0
- data/lib/omf-sfa/resource/olease.rb +61 -0
- data/lib/omf-sfa/resource/oproperty.rb +178 -0
- data/lib/omf-sfa/resource/oreference.rb +15 -0
- data/lib/omf-sfa/resource/oresource.rb +491 -0
- data/lib/omf-sfa/resource/project.rb +28 -0
- data/lib/omf-sfa/resource/project_membership.rb +13 -0
- data/lib/omf-sfa/resource/sfa_base.rb +544 -0
- data/lib/omf-sfa/resource/user.rb +25 -0
- data/lib/omf-sfa/resource.rb +20 -0
- data/lib/omf-sfa/util/create_sample_testbed.rb +68 -0
- data/lib/omf-sfa/util/load_from_sfa_xml.rb +65 -0
- data/lib/omf-sfa/version.rb +4 -0
- data/lib/omf_sfa.rb +5 -0
- data/omf_sfa.gemspec +46 -0
- data/owl/README +3 -0
- data/owl/ben-6509.rdf +1377 -0
- data/owl/ben-dell.rdf +586 -0
- data/owl/ben-dtn.rdf +1698 -0
- data/owl/ben.rdf +1335 -0
- data/owl/collections.owl +309 -0
- data/owl/compute.owl +1486 -0
- data/owl/domain.owl +444 -0
- data/owl/dtn.owl +1165 -0
- data/owl/ec2.owl +385 -0
- data/owl/ethernet.owl +466 -0
- data/owl/eucalyptus.owl +431 -0
- data/owl/id-mp-Request1.rdf +247 -0
- data/owl/itu-grid.owl +147 -0
- data/owl/kansei.owl +511 -0
- data/owl/layer.owl +645 -0
- data/owl/location.owl +117 -0
- data/owl/mass.rdf +608 -0
- data/owl/nlr.rdf +901 -0
- data/owl/orca.owl +181 -0
- data/owl/planetlab.owl +124 -0
- data/owl/protogeni.owl +467 -0
- data/owl/request-6509-2.rdf +150 -0
- data/owl/request-6509-3.rdf +158 -0
- data/owl/request-6509.rdf +199 -0
- data/owl/request.owl +222 -0
- data/owl/storage.owl +511 -0
- data/owl/topology.owl +608 -0
- data/schema/rspec-v3/ad-common.xsd +269 -0
- data/schema/rspec-v3/ad-reservation.rnc +12 -0
- data/schema/rspec-v3/ad-reservation.rng +28 -0
- data/schema/rspec-v3/ad-reservation.xsd +13 -0
- data/schema/rspec-v3/ad.rnc +151 -0
- data/schema/rspec-v3/ad.xsd +77 -0
- data/schema/rspec-v3/any-extension-schema.xsd +38 -0
- data/schema/rspec-v3/any-extension.rnc +30 -0
- data/schema/rspec-v3/common.rnc +185 -0
- data/schema/rspec-v3/manifest-common.xsd +244 -0
- data/schema/rspec-v3/manifest-request.xsd +95 -0
- data/schema/rspec-v3/manifest.rnc +62 -0
- data/schema/rspec-v3/manifest.xsd +34 -0
- data/schema/rspec-v3/request-common.xsd +219 -0
- data/schema/rspec-v3/request-reservation.rnc +12 -0
- data/schema/rspec-v3/request-reservation.xsd +13 -0
- data/schema/rspec-v3/request.rnc +118 -0
- data/schema/rspec-v3/request.xsd +94 -0
- data/share/assets/css/default.css +147 -0
- data/share/assets/css/rest_api.css +0 -0
- data/share/assets/network.html +28 -0
- data/share/assets/network.js +82 -0
- data/spec/am/am-rest/common.rb +29 -0
- data/spec/am/am-rest/resource_group_handler_XspecX.rb +97 -0
- data/spec/am/am-rest/resource_handler_spec.rb +204 -0
- data/spec/am/am-rpc/sfa_methods_spec.rb +150 -0
- data/spec/am/am_manager_spec.rb +307 -0
- data/spec/am/am_scheduler_spec.rb +57 -0
- data/spec/am/common.rb +24 -0
- data/spec/resource/common.rb +31 -0
- data/spec/resource/node_spec.rb +171 -0
- data/spec/resource/oaccount_spec.rb +92 -0
- data/spec/resource/ocomponent_spec.rb +225 -0
- data/spec/resource/ogroup_spec.rb +93 -0
- data/spec/resource/oresource_spec.rb +208 -0
- data/spec/resource_and_leases_spec.rb +377 -0
- data/test/OLD_FILES/assertion1.xml +117 -0
- data/test/OLD_FILES/greeter_spec.rb +15 -0
- data/test/OLD_FILES/mongo_test.rb +45 -0
- data/test/OLD_FILES/req-sfa-2.xml +6 -0
- data/test/OLD_FILES/req-sfa-g.xml +8 -0
- data/test/OLD_FILES/req-sfa-g2.xml +10 -0
- data/test/OLD_FILES/req-sfa-g3.xml +14 -0
- data/test/OLD_FILES/req-sfa.xml +6 -0
- data/test/OLD_FILES/req1.xml +22 -0
- data/test/OLD_FILES/req1b.xml +15 -0
- data/test/OLD_FILES/rspec-test.xml +1867 -0
- data/test/OLD_FILES/test.rb +67 -0
- data/test/OLD_FILES/test2.rb +32 -0
- data/test/am/am_manager_rspec_tests.rb +378 -0
- data/test/am/am_manager_tests.rb +518 -0
- data/test/am/am_scheduler_tests.rb +173 -0
- data/test/resource/olease_test.rb +74 -0
- data/test/sfa_requests/request.xml +5 -0
- data/test/sfa_requests/request1.xml +5 -0
- data/test/sfa_requests/request2.xml +5 -0
- data/test/sfa_requests/request3.xml +5 -0
- metadata +601 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
2
|
+
require 'omf_base/lobject'
|
|
3
|
+
|
|
4
|
+
module OMF::SFA::AM
|
|
5
|
+
class Credential < OMF::Base::LObject
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@config = OMF::Base::YAML.load('omf-sfa-am', :path => [File.dirname(__FILE__) + '/../../../etc/omf-sfa'])[:omf_sfa_am]
|
|
9
|
+
|
|
10
|
+
rpc = @config[:endpoints].select { |v| v[:type] == 'xmlrpc' }.first
|
|
11
|
+
trusted_roots = File.expand_path(rpc[:trusted_roots])
|
|
12
|
+
certs = Dir.entries(trusted_roots)
|
|
13
|
+
certs.delete("..")
|
|
14
|
+
certs.delete(".")
|
|
15
|
+
@@root_certs = certs.collect do |v|
|
|
16
|
+
v = File.join(trusted_roots, v)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
@@xmlsec = 'xmlsec1'
|
|
20
|
+
|
|
21
|
+
# <?xml version="1.0"?>
|
|
22
|
+
# <signed-credential>
|
|
23
|
+
# <credential xml:id="ref0">
|
|
24
|
+
# <type>privilege</type>
|
|
25
|
+
# <serial>8</serial>
|
|
26
|
+
# <owner_gid>-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----</owner_gid>
|
|
27
|
+
# <owner_urn>urn:publicid:IDN+geni:gpo:gcf+user+alice</owner_urn>
|
|
28
|
+
# <target_gid>-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----</target_gid>
|
|
29
|
+
# <target_urn>urn:publicid:IDN+geni:gpo:gcf+slice+2c93-4a3:127.0.0.1%3A8000</target_urn>
|
|
30
|
+
# <uuid/>
|
|
31
|
+
# <expires>2012-02-01T03:03:33</expires>
|
|
32
|
+
# <privileges>
|
|
33
|
+
# <privilege><name>refresh</name><can_delegate>true</can_delegate></privilege>
|
|
34
|
+
# <privilege><name>embed</name><can_delegate>true</can_delegate></privilege>
|
|
35
|
+
# <privilege><name>bind</name><can_delegate>true</can_delegate></privilege>
|
|
36
|
+
# <privilege><name>control</name><can_delegate>true</can_delegate></privilege>
|
|
37
|
+
# <privilege><name>info</name><can_delegate>true</can_delegate></privilege>
|
|
38
|
+
# </privileges>
|
|
39
|
+
# </credential>
|
|
40
|
+
# <signatures>
|
|
41
|
+
# <Signature xmlns="http://www.w3.org/2000/09/xmldsig#" xml:id="Sig_ref0">
|
|
42
|
+
# ...
|
|
43
|
+
# </Signature>
|
|
44
|
+
# </signatures>
|
|
45
|
+
# </signed-credential>
|
|
46
|
+
|
|
47
|
+
def self.unmarshall(xml_text)
|
|
48
|
+
signer_urn = verify_signed_xml(xml_text)
|
|
49
|
+
cred = Nokogiri::XML.parse(xml_text)
|
|
50
|
+
unless cred.root.name == 'signed-credential'
|
|
51
|
+
raise "Expected 'signed-credential' but got '#{cred.root}'"
|
|
52
|
+
end
|
|
53
|
+
#puts @doc.to_xml
|
|
54
|
+
unless (type_el = cred.xpath('//credential/type')[0])
|
|
55
|
+
raise "Credential doesn't contain 'type' element"
|
|
56
|
+
end
|
|
57
|
+
self.verify_type(type_el.content)
|
|
58
|
+
|
|
59
|
+
#<owner_urn>urn:publicid:IDN+geni:gpo:gcf+user+alice</owner_urn>
|
|
60
|
+
self.new(cred, signer_urn)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# The xml _content_ (provided as string) should
|
|
64
|
+
# contain a _Signature_ tag.
|
|
65
|
+
#
|
|
66
|
+
# Returns urn of signer if signature is valid, otherwise throw an exception
|
|
67
|
+
#
|
|
68
|
+
def self.verify_signed_xml(content)
|
|
69
|
+
tf = nil
|
|
70
|
+
begin
|
|
71
|
+
#debug "Verifying: ", content
|
|
72
|
+
tf = Tempfile.open('omf-am-rpc')
|
|
73
|
+
tf << content
|
|
74
|
+
tf.close
|
|
75
|
+
trusted_pems = @@root_certs.map do |r|
|
|
76
|
+
"--trusted-pem #{r}"
|
|
77
|
+
end.join(' ')
|
|
78
|
+
cmd = "#{@@xmlsec} verify --enabled-key-data 'x509' #{trusted_pems} --print-xml-debug #{tf.path} 2> /dev/null"
|
|
79
|
+
#cmd = "#{@@xmlsec} verify --trusted-pem #{@@root_certs} --print-xml-debug #{tf.path} 2> /dev/null"
|
|
80
|
+
out = []
|
|
81
|
+
result = nil
|
|
82
|
+
IO.popen(cmd) do |so|
|
|
83
|
+
result = Nokogiri::XML.parse(so)
|
|
84
|
+
#debug result
|
|
85
|
+
end
|
|
86
|
+
unless (result.xpath('/VerificationContext')[0]['status'] == 'succeeded')
|
|
87
|
+
raise OMF::SFA::AM::InsufficientPrivilegesException.new("Error: Signature doesn't verify")#\n#{@signature.to_xml}"
|
|
88
|
+
end
|
|
89
|
+
# <Certificate>
|
|
90
|
+
# <SubjectName>/CN=geni//gpo//gcf.authority.sa</SubjectName>
|
|
91
|
+
# <IssuerName>/CN=geni//gpo//gcf.authority.sa</IssuerName>
|
|
92
|
+
# <SerialNumber>3</SerialNumber>
|
|
93
|
+
# </Certificate>
|
|
94
|
+
signer = result.xpath('//Certificate/SubjectName')[0].content
|
|
95
|
+
debug "Signer of cert is '#{signer}'"
|
|
96
|
+
return signer
|
|
97
|
+
ensure
|
|
98
|
+
tf.close! if tf
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def self.verify_type(type)
|
|
103
|
+
raise "Implement 'verify_type' in '#{self}'"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
attr_reader :owner_urn
|
|
108
|
+
attr_reader :target_urn
|
|
109
|
+
attr_reader :signer_urn
|
|
110
|
+
attr_reader :valid_until
|
|
111
|
+
|
|
112
|
+
def valid_at?(time = Time.now)
|
|
113
|
+
#debug ">>>> #{valid_until}"
|
|
114
|
+
time <= @valid_until
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
protected
|
|
118
|
+
|
|
119
|
+
# Create a credential described in +description_doc+
|
|
120
|
+
#
|
|
121
|
+
def initialize(description_doc, signer_urn)
|
|
122
|
+
unless el = description_doc.xpath('//credential/owner_urn')[0]
|
|
123
|
+
raise "Missing element 'owner_urn' in credential"
|
|
124
|
+
end
|
|
125
|
+
#URI:urn:publicid:IDN+topdomain:subdomain+user+pi
|
|
126
|
+
#@owner_urn = el.content[el.content.index('+')+1..el.content.length]
|
|
127
|
+
@owner_urn = el.content
|
|
128
|
+
unless el = description_doc.xpath('//credential/target_urn')[0]
|
|
129
|
+
raise "Missing element 'target_urn' in credential"
|
|
130
|
+
end
|
|
131
|
+
#URI:urn:publicid:IDN+topdomain:subdomain+slice+test
|
|
132
|
+
#@target_urn = el.content[el.content.index('+')+1..el.content.length]
|
|
133
|
+
@target_urn = el.content
|
|
134
|
+
|
|
135
|
+
unless el = description_doc.xpath('//credential/expires')[0]
|
|
136
|
+
raise "Missing element 'expires' in credential"
|
|
137
|
+
end
|
|
138
|
+
@valid_until = Time.parse(el.content)
|
|
139
|
+
|
|
140
|
+
@signer_urn = signer_urn
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
end # Credential
|
|
145
|
+
end # OMF::GENI::AM
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
require 'omf_base/lobject'
|
|
4
|
+
|
|
5
|
+
module OMF::SFA::AM
|
|
6
|
+
|
|
7
|
+
include OMF::Base
|
|
8
|
+
|
|
9
|
+
class InsufficientPrivilegesException < AMManagerException; end
|
|
10
|
+
|
|
11
|
+
# This class implements an authorizer which
|
|
12
|
+
# only allows actions which have been enabled in a permission
|
|
13
|
+
# hash.
|
|
14
|
+
#
|
|
15
|
+
class DefaultAuthorizer < LObject
|
|
16
|
+
|
|
17
|
+
[
|
|
18
|
+
# ACCOUNT
|
|
19
|
+
:can_create_account?, # ()
|
|
20
|
+
:can_view_account?, # (account)
|
|
21
|
+
:can_renew_account?, # (account, until)
|
|
22
|
+
:can_close_account?, # (account)
|
|
23
|
+
# RESOURCE
|
|
24
|
+
:can_create_resource?, # (resource_descr, type)
|
|
25
|
+
:can_view_resource?, # (resource)
|
|
26
|
+
:can_release_resource?, # (resource)
|
|
27
|
+
# LEASE
|
|
28
|
+
:can_view_lease?, # (lease)
|
|
29
|
+
:can_modify_lease?, # (lease)
|
|
30
|
+
:can_release_lease?, # (lease)
|
|
31
|
+
].each do |m|
|
|
32
|
+
define_method(m) do |*args|
|
|
33
|
+
debug "Check permission '#{m}' (#{@permissions.inspect})"
|
|
34
|
+
unless @permissions[m]
|
|
35
|
+
raise InsufficientPrivilegesException.new
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def initialize(permissions = {})
|
|
41
|
+
@permissions = permissions
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'omf-sfa/am/credential'
|
|
2
|
+
|
|
3
|
+
module OMF::SFA::AM
|
|
4
|
+
|
|
5
|
+
# Throws exception if credentials XML encoded in +cred_string_a+
|
|
6
|
+
# are *not* sufficient for _action_
|
|
7
|
+
#
|
|
8
|
+
# GENI API Credentials
|
|
9
|
+
#
|
|
10
|
+
# The privileges are the rights that are assigned to the owner
|
|
11
|
+
# of the credential on the target resource. Different slice
|
|
12
|
+
# authorities use different permission names, but they have
|
|
13
|
+
# similar semantic meaning. If and only if a privilege can
|
|
14
|
+
# be delegated, then that means the owner of the credential
|
|
15
|
+
# can delegate that permission to another entity.
|
|
16
|
+
# Currently, the only credentials used in the GENI API are
|
|
17
|
+
# slice credentials and user credentials. Privileges have not
|
|
18
|
+
# yet been agreed upon between the control frameworks.
|
|
19
|
+
# Currently, SFA assigns ['refresh', 'resolve', and 'info']
|
|
20
|
+
# rights to user credentials.
|
|
21
|
+
# Slice credentials have "slice" rights. ProtoGENI defaults
|
|
22
|
+
# to the "*" privilege which means that the owner has rights
|
|
23
|
+
# to all methods associated with that credential type
|
|
24
|
+
# (user or slice).
|
|
25
|
+
# See https://www.protogeni.net/trac/protogeni/wiki/ReferenceImplementationPrivileges
|
|
26
|
+
# for more information on ProtoGENI privileges.
|
|
27
|
+
#
|
|
28
|
+
class PrivilegeCredential < Credential
|
|
29
|
+
#attr_reader :privileges
|
|
30
|
+
|
|
31
|
+
def self.verify_type(type)
|
|
32
|
+
raise "Expected type 'privilege' but got '#{type}'" unless type == 'privilege'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def privilege?(pname)
|
|
36
|
+
@privileges.has_key?(pname)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def user_urn
|
|
40
|
+
owner_urn
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def type
|
|
44
|
+
# urn:publicid:IDN+topdomain:subdomain+slice+test
|
|
45
|
+
target_urn.split('+')[2] # it should be one of "slice" or "user"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# Create a credential described in +description_doc+ .
|
|
50
|
+
#
|
|
51
|
+
def initialize(description_doc, signer_urn)
|
|
52
|
+
super
|
|
53
|
+
# @see http://groups.geni.net/geni/wiki/GeniApiCredentials
|
|
54
|
+
# <privileges>
|
|
55
|
+
# <privilege><name>refresh</name><can_delegate>true</can_delegate></privilege>
|
|
56
|
+
# <privilege><name>embed</name><can_delegate>true</can_delegate></privilege>
|
|
57
|
+
# <privilege><name>bind</name><can_delegate>true</can_delegate></privilege>
|
|
58
|
+
# <privilege><name>control</name><can_delegate>true</can_delegate></privilege>
|
|
59
|
+
# <privilege><name>info</name><can_delegate>true</can_delegate></privilege>
|
|
60
|
+
# </privileges>
|
|
61
|
+
unless el = description_doc.xpath('//credential/privileges')[0]
|
|
62
|
+
raise "Missing element 'privileges' in credential"
|
|
63
|
+
end
|
|
64
|
+
@privileges = {}
|
|
65
|
+
el.children.each do |pel|
|
|
66
|
+
p = {}
|
|
67
|
+
pel.children.each do |cel|
|
|
68
|
+
p[cel.name.to_sym] = cel.content
|
|
69
|
+
end
|
|
70
|
+
# example: @privileges={"refresh"=>{:can_delegate=>"true"}, "resolve"=>{:can_delegate=>"true"}, "info"=>{:can_delegate=>"true"}}
|
|
71
|
+
@privileges[p.delete(:name)] = p
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end # PrivilegeCredential
|
|
76
|
+
end # OMF::SFA::AM
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
module OMF::GENI::AM
|
|
3
|
+
class Signature
|
|
4
|
+
|
|
5
|
+
# The xml _content_ (provided as string) should
|
|
6
|
+
# contain a _Signature_ tag.
|
|
7
|
+
#
|
|
8
|
+
# Returns a _Signature_ object if valid.
|
|
9
|
+
# Raises exception if not valid
|
|
10
|
+
#
|
|
11
|
+
def self.verify_xml_string(content)
|
|
12
|
+
tf = sig = nil
|
|
13
|
+
begin
|
|
14
|
+
tf = Tempfile.open('omf-am-rpc')
|
|
15
|
+
tf << content
|
|
16
|
+
tf.close
|
|
17
|
+
cmd = "#{@@xmlsec} verify --trusted-pem #{@@root_certs} --print-xml-debug #{tf.path} 2> /dev/null"
|
|
18
|
+
out = []
|
|
19
|
+
#IO.popen("#{cmd} 2>&1") do |so|
|
|
20
|
+
IO.popen(cmd) do |so|
|
|
21
|
+
sig = Nokogiri::XML.parse(so)
|
|
22
|
+
end
|
|
23
|
+
unless (sig.xpath('/VerificationContext')[0]['status'] == 'succeeded')
|
|
24
|
+
raise "Error: Signature doesn't verify\n#{sig.to_xml}"
|
|
25
|
+
end
|
|
26
|
+
ensure
|
|
27
|
+
tf.close! if tf
|
|
28
|
+
end
|
|
29
|
+
return Signature.new(sig)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def initialize(sig_doc)
|
|
33
|
+
@sig_doc = sig_doc
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end # Signature
|
|
37
|
+
end # OMF::GENI::AM
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
|
|
2
|
+
require 'omf-sfa/am/credential'
|
|
3
|
+
|
|
4
|
+
module OMF::SFA::AM
|
|
5
|
+
class UserCredential < OMF::Base::LObject
|
|
6
|
+
|
|
7
|
+
include OMF::SFA::Resource
|
|
8
|
+
|
|
9
|
+
attr_reader :user_urn, :user_uuid
|
|
10
|
+
|
|
11
|
+
def self.unmarshall(cert_s)
|
|
12
|
+
cert = OpenSSL::X509::Certificate.new(cert_s)
|
|
13
|
+
#puts cert
|
|
14
|
+
unless OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE.verify(cert)
|
|
15
|
+
raise OMF::SFA::AM::InsufficientPrivilegesException.new("Non valid user cert")
|
|
16
|
+
end
|
|
17
|
+
self.new(cert)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def initialize(cert)
|
|
21
|
+
@cert = cert
|
|
22
|
+
|
|
23
|
+
@cert.extensions.each do |e|
|
|
24
|
+
if e.oid == 'subjectAltName'
|
|
25
|
+
#URI:urn:publicid:IDN+topdomain:subdomain+user+pi, URI:urn:uuid:759ae077-2fda-4d02-8921-ab0235a09920
|
|
26
|
+
e.value.split(',').each do |u|
|
|
27
|
+
u.slice!('URI:')
|
|
28
|
+
@user_urn = u.strip if u.start_with?('urn:publicid:IDN')
|
|
29
|
+
@user_uuid = u.match(/^urn:uuid:(.*)/)[1] if u.start_with?('urn:uuid')
|
|
30
|
+
end
|
|
31
|
+
#e.value.split('URI:urn:').each do |u|
|
|
32
|
+
# str = u.split('+')
|
|
33
|
+
# if str.include?('publicid:IDN')
|
|
34
|
+
# @user_urn = str[-3..-1].join('+').chomp(', ')
|
|
35
|
+
# end
|
|
36
|
+
# str = u.split(':')
|
|
37
|
+
# if str.include?('uuid')
|
|
38
|
+
# @user_uuid = str.last
|
|
39
|
+
# end
|
|
40
|
+
#end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def subject
|
|
46
|
+
@cert.subject
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def valid_at?(time = Time.now)
|
|
50
|
+
debug "valid? #{@cert.not_before} < #{time} < #{@cert.not_after}"
|
|
51
|
+
time >= @cert.not_before && time <= @cert.not_after
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end # UserCredential
|
|
55
|
+
end # OMF::SFA::AM
|
|
56
|
+
|
data/lib/omf-sfa/am.rb
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
# An +ModelDataPropertyDescription+ holds all the relevant information
|
|
4
|
+
# for describing properties of entities.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
module OMF::SFA
|
|
8
|
+
module Model
|
|
9
|
+
|
|
10
|
+
class AbstractPropertyDescription < OMF::Base::LObject
|
|
11
|
+
|
|
12
|
+
@@name2inst = {}
|
|
13
|
+
|
|
14
|
+
def self.create_from_xml(cel)
|
|
15
|
+
about = cel.attribute_with_ns('about', RDF_NS)
|
|
16
|
+
name = xml_full_name(about.value, cel)
|
|
17
|
+
klass = @@name2inst[name] ||= self.new(name)
|
|
18
|
+
klass.parse(cel)
|
|
19
|
+
klass
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.each(&block)
|
|
23
|
+
@@name2inst.values.each &block
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
attr_reader :name, :ns, :uri
|
|
27
|
+
|
|
28
|
+
def initialize(full_name)
|
|
29
|
+
@uri = full_name
|
|
30
|
+
@ns, @name = full_name.split('#')
|
|
31
|
+
super @name
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def validate()
|
|
35
|
+
if @domain
|
|
36
|
+
@domain = validate_class_reference(@domain)
|
|
37
|
+
@domain.add_property(self)
|
|
38
|
+
else
|
|
39
|
+
#warn "No domain reference for property '#{@name}'"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Return class description for +ref+
|
|
44
|
+
#
|
|
45
|
+
def validate_class_reference(ref)
|
|
46
|
+
unless ref.kind_of? ModelClassDescription
|
|
47
|
+
if ref
|
|
48
|
+
ref = ModelClassDescription[ref] || raise("Unknonw class '#{ref}'")
|
|
49
|
+
else
|
|
50
|
+
raise 'Empty class reference'
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
ref
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def parse(cel)
|
|
58
|
+
cel.children.each do |el|
|
|
59
|
+
node_name = el.node_name
|
|
60
|
+
next if node_name == 'comment'
|
|
61
|
+
|
|
62
|
+
attr = el.attribute_with_ns('resource', RDF_NS)
|
|
63
|
+
res_name = attr ? xml_full_name(attr.value, el) : nil
|
|
64
|
+
|
|
65
|
+
parse_el(node_name, res_name, el)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def parse_el(node_name, res_name, el)
|
|
70
|
+
case node_name
|
|
71
|
+
when 'range'
|
|
72
|
+
@range = res_name # ModelClassDescription[res] || raise("Unknonw class '#{res}'")
|
|
73
|
+
when 'domain'
|
|
74
|
+
@domain = res_name
|
|
75
|
+
else
|
|
76
|
+
warn "Unknown eleement '#{node_name}' in '#{self.class.name}'"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def to_s
|
|
82
|
+
"#{@name} (#{self.class.name})"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end # AbstractPropDescription
|
|
86
|
+
end # Model
|
|
87
|
+
end # OMF::SFA
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
|
|
2
|
+
# An +MClass+ holds all the releevant information relevant to the
|
|
3
|
+
# specific model class in an overal model or schema.
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
module OMF::SFA
|
|
7
|
+
module Model
|
|
8
|
+
|
|
9
|
+
class ModelClassDescription < OMF::Base::LObject
|
|
10
|
+
|
|
11
|
+
@@name2inst = {}
|
|
12
|
+
|
|
13
|
+
def self.[](uri)
|
|
14
|
+
@@name2inst[uri]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.each(&block)
|
|
18
|
+
if block
|
|
19
|
+
@@name2inst.values.each &block
|
|
20
|
+
else
|
|
21
|
+
@@name2inst.values
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.models()
|
|
26
|
+
@@name2inst.values
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.create_from_xml(cel)
|
|
30
|
+
about = cel.attribute_with_ns('about', RDF_NS)
|
|
31
|
+
name = xml_full_name(about.value, cel)
|
|
32
|
+
klass = @@name2inst[name] ||= self.new(name)
|
|
33
|
+
klass.parse(cel)
|
|
34
|
+
klass
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
attr_reader :name, :ns, :uri
|
|
39
|
+
|
|
40
|
+
def initialize(full_name)
|
|
41
|
+
@uri = full_name
|
|
42
|
+
@ns, @name = full_name.split('#')
|
|
43
|
+
super @name
|
|
44
|
+
@properties = {}
|
|
45
|
+
@children = []
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def add_property(prop_description)
|
|
49
|
+
name = prop_description.name
|
|
50
|
+
if p = @properties[name]
|
|
51
|
+
if p != prop_description
|
|
52
|
+
error "Trying to add additional property with smae name '#{name}'"
|
|
53
|
+
end
|
|
54
|
+
else
|
|
55
|
+
@properties[name] = prop_description
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def parse(cel)
|
|
61
|
+
cel.children.each do |el|
|
|
62
|
+
node_name = el.node_name
|
|
63
|
+
next if node_name == 'comment'
|
|
64
|
+
|
|
65
|
+
case el.node_name
|
|
66
|
+
when 'subClassOf'
|
|
67
|
+
parse_super(el)
|
|
68
|
+
when 'disjointWith'
|
|
69
|
+
# <owl:disjointWith rdf:resource="#Item"/>
|
|
70
|
+
when 'label'
|
|
71
|
+
@label = el.content
|
|
72
|
+
else
|
|
73
|
+
warn "Unknown eleement '#{el.node_name}' in '#{self.class.name}'"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# TODO: Parsing of 'Restriction'
|
|
79
|
+
#
|
|
80
|
+
# <rdfs:subClassOf rdf:resource="#NetworkElement"/>
|
|
81
|
+
# <rdfs:subClassOf>
|
|
82
|
+
# <owl:Restriction>
|
|
83
|
+
# <owl:onProperty rdf:resource="#hasSwitchMatrix"/>
|
|
84
|
+
# <owl:someValuesFrom rdf:resource="#SwitchMatrix"/>
|
|
85
|
+
# </owl:Restriction>
|
|
86
|
+
# </rdfs:subClassOf>
|
|
87
|
+
#
|
|
88
|
+
def parse_super(el)
|
|
89
|
+
res = el.attribute_with_ns('resource', RDF_NS)
|
|
90
|
+
if res
|
|
91
|
+
if @superklass
|
|
92
|
+
warn "Don't really know how to handle multiple inheritence in '#{@name}'"
|
|
93
|
+
end
|
|
94
|
+
@superklass = xml_full_name(res.value, el)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def superklass
|
|
100
|
+
unless @superklass.kind_of? self.class
|
|
101
|
+
if klass = self.class[@superklass]
|
|
102
|
+
@superklass = klass
|
|
103
|
+
klass.add_child_class(self)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
@superklass
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def add_child_class(class_model)
|
|
110
|
+
@children << class_model
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def describe(level = 0, max_level = 99)
|
|
114
|
+
if !@properties.empty? || level == 0
|
|
115
|
+
prefix = " " * level
|
|
116
|
+
puts "#{prefix}-------------------------"
|
|
117
|
+
puts "#{prefix}Class: #{name}"
|
|
118
|
+
describe_properties(prefix)
|
|
119
|
+
end
|
|
120
|
+
@children.each do |ch|
|
|
121
|
+
ch.describe level + 1, max_level
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def describe_properties(prefix)
|
|
126
|
+
# if superklass.kind_of? self.class
|
|
127
|
+
# superklass.describe_properties
|
|
128
|
+
# end
|
|
129
|
+
@properties.each do |n, p|
|
|
130
|
+
mark = p.kind_of?(ModelDataPropertyDescription) ? '=' : '>'
|
|
131
|
+
puts "#{prefix} #{mark} #{n}"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def validate()
|
|
136
|
+
superklass
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def to_s
|
|
140
|
+
"#{@name} (#{self.class.name}) - super: #{superklass || 'none'}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end # ModelClassDescription
|
|
144
|
+
end # Model
|
|
145
|
+
end # OMF::SFA
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
require 'omf-sfa/model/abstract_prop_description'
|
|
3
|
+
|
|
4
|
+
# An +ModelDataPropertyDescription+ holds all the relevant information
|
|
5
|
+
# for describing properties of entities.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
module OMF::SFA
|
|
9
|
+
module Model
|
|
10
|
+
|
|
11
|
+
class ModelDataPropertyDescription < AbstractPropertyDescription
|
|
12
|
+
|
|
13
|
+
# <owl:DatatypeProperty rdf:about="#numHop">
|
|
14
|
+
# <rdfs:domain rdf:resource="#NetworkTransportElement"/>
|
|
15
|
+
# <rdfs:range rdf:resource="&xsd;int"/>
|
|
16
|
+
# </owl:DatatypeProperty>
|
|
17
|
+
#
|
|
18
|
+
def parse_el(node_name, res_name, el)
|
|
19
|
+
case node_name
|
|
20
|
+
when 'XXX'
|
|
21
|
+
else
|
|
22
|
+
super
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end # ModelClassDescription
|
|
27
|
+
end # Model
|
|
28
|
+
end # OMF::SFA
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
require 'omf-sfa/model/abstract_prop_description'
|
|
3
|
+
|
|
4
|
+
# An +ModelObjectPropertyDescription+ holds all the relevant information
|
|
5
|
+
# for describing relationship between entities.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
module OMF::SFA
|
|
9
|
+
module Model
|
|
10
|
+
|
|
11
|
+
class ModelObjectPropertyDescription < AbstractPropertyDescription
|
|
12
|
+
|
|
13
|
+
@@types = {
|
|
14
|
+
'http://www.w3.org/2002/07/owl#TransitiveProperty' => :transitive,
|
|
15
|
+
'http://www.w3.org/2002/07/owl#FunctionalProperty' => :functional,
|
|
16
|
+
'http://www.w3.org/2002/07/owl#InverseFunctionalProperty' => :inverse_functional,
|
|
17
|
+
'http://www.w3.org/2002/07/owl#SymmetricProperty' => :symmetric,
|
|
18
|
+
'http://www.w3.org/2002/07/owl#AsymmetricProperty' => :asymmetric,
|
|
19
|
+
'http://www.w3.org/2002/07/owl#ReflexiveProperty' => :reflexive,
|
|
20
|
+
'http://www.w3.org/2002/07/owl#IrreflexiveProperty' => :irreflexive
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# <!-- http://geni-orca.renci.org/owl/topology.owl#connectedTo -->
|
|
25
|
+
#
|
|
26
|
+
# <owl:ObjectProperty rdf:about="#connectedTo">
|
|
27
|
+
# <rdf:type rdf:resource="&owl;TransitiveProperty"/>
|
|
28
|
+
# <rdfs:range rdf:resource="#NetworkElement"/>
|
|
29
|
+
# <rdfs:domain rdf:resource="#NetworkElement"/>
|
|
30
|
+
# <rdfs:subPropertyOf rdf:resource="&layer;feature"/>
|
|
31
|
+
# </owl:ObjectProperty>
|
|
32
|
+
#
|
|
33
|
+
def parse_el(node_name, res_name, el)
|
|
34
|
+
case node_name
|
|
35
|
+
when 'subPropertyOf'
|
|
36
|
+
@subPropertyOf = res_name
|
|
37
|
+
when 'type'
|
|
38
|
+
@type = @@types[res_name] || raise("Unknonw property type '#{res_name}'")
|
|
39
|
+
when 'inverseOf'
|
|
40
|
+
@inverseOf = res_name
|
|
41
|
+
else
|
|
42
|
+
super
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
end # ModelClassDescription
|
|
48
|
+
end # Model
|
|
49
|
+
end # OMF::SFA
|