aaf-mdqt 0.8.0
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.
- checksums.yaml +7 -0
- data/.github/workflows/codeql-analysis.yml +70 -0
- data/.github/workflows/ruby.yml +41 -0
- data/.gitignore +25 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +296 -0
- data/.ruby-version +1 -0
- data/.tool-versions +1 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +168 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +21 -0
- data/Makefile +4 -0
- data/README.md +268 -0
- data/Rakefile +5 -0
- data/aaf-mdqt.gemspec +46 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/cucumber.yml +2 -0
- data/exe/mdqt +174 -0
- data/lib/mdqt/cli/base.rb +190 -0
- data/lib/mdqt/cli/cache_control.rb +25 -0
- data/lib/mdqt/cli/check.rb +78 -0
- data/lib/mdqt/cli/compliance.rb +0 -0
- data/lib/mdqt/cli/defaults.rb +70 -0
- data/lib/mdqt/cli/entities.rb +47 -0
- data/lib/mdqt/cli/exists.rb +0 -0
- data/lib/mdqt/cli/get.rb +130 -0
- data/lib/mdqt/cli/list.rb +65 -0
- data/lib/mdqt/cli/ln.rb +81 -0
- data/lib/mdqt/cli/ls.rb +54 -0
- data/lib/mdqt/cli/rename.rb +75 -0
- data/lib/mdqt/cli/reset.rb +27 -0
- data/lib/mdqt/cli/services.rb +25 -0
- data/lib/mdqt/cli/transform.rb +33 -0
- data/lib/mdqt/cli/url.rb +37 -0
- data/lib/mdqt/cli/version.rb +17 -0
- data/lib/mdqt/cli.rb +24 -0
- data/lib/mdqt/client/identifier_utils.rb +51 -0
- data/lib/mdqt/client/metadata_file.rb +144 -0
- data/lib/mdqt/client/metadata_response.rb +182 -0
- data/lib/mdqt/client/metadata_service.rb +194 -0
- data/lib/mdqt/client/metadata_validator.rb +81 -0
- data/lib/mdqt/client.rb +83 -0
- data/lib/mdqt/schema/MetadataExchange.xsd +112 -0
- data/lib/mdqt/schema/mdqt_check_schema.xsd +5 -0
- data/lib/mdqt/schema/oasis-200401-wss-wssecurity-secext-1.0.xsd +195 -0
- data/lib/mdqt/schema/oasis-200401-wss-wssecurity-utility-1.0.xsd +108 -0
- data/lib/mdqt/schema/saml-schema-assertion-2.0.xsd +283 -0
- data/lib/mdqt/schema/saml-schema-metadata-2.0.xsd +337 -0
- data/lib/mdqt/schema/ws-addr.xsd +137 -0
- data/lib/mdqt/schema/ws-authorization.xsd +145 -0
- data/lib/mdqt/schema/ws-federation.xsd +471 -0
- data/lib/mdqt/schema/ws-securitypolicy-1.2.xsd +1205 -0
- data/lib/mdqt/schema/xenc-schema.xsd +136 -0
- data/lib/mdqt/schema/xml.xsd +287 -0
- data/lib/mdqt/schema/xmldsig-core-schema.xsd +309 -0
- data/lib/mdqt/version.rb +3 -0
- data/lib/mdqt.rb +5 -0
- data/lib/tasks/cucumber.rake +8 -0
- data/lib/tasks/spec.rake +5 -0
- data/lib/tasks/tests.rake +6 -0
- data/lib/tasks/yard.rake +6 -0
- metadata +332 -0
data/lib/mdqt/cli/ls.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module MDQT
|
2
|
+
|
3
|
+
class CLI
|
4
|
+
|
5
|
+
require 'mdqt/cli/base'
|
6
|
+
|
7
|
+
class Ls < Base
|
8
|
+
|
9
|
+
def run
|
10
|
+
|
11
|
+
options.validate = true
|
12
|
+
|
13
|
+
advise_on_xml_signing_support
|
14
|
+
halt!("Cannot check a metadata file without XML support: please install additional gems") unless MDQT::Client.verification_available?
|
15
|
+
|
16
|
+
client = MDQT::Client.new(
|
17
|
+
options.service,
|
18
|
+
verbose: options.verbose,
|
19
|
+
explain: options.explain ? true : false,
|
20
|
+
)
|
21
|
+
|
22
|
+
results = []
|
23
|
+
|
24
|
+
p_args = args.empty? ? Dir.glob("*.xml") : args
|
25
|
+
|
26
|
+
p_args.each do |filename|
|
27
|
+
|
28
|
+
file = client.open_metadata(filename)
|
29
|
+
|
30
|
+
halt!("Cannot access file #{filename}") unless file.readable?
|
31
|
+
|
32
|
+
#halt!("File #{filename} is a metadata aggregate, cannot create entityID hashed link!") if file.aggregate?
|
33
|
+
next if file.aggregate?
|
34
|
+
halt!("XML validation failed for #{filename}:\n#{file.validation_error}") unless file.valid?
|
35
|
+
|
36
|
+
halt!("Cannot find entityID for #{filename}") unless file.entity_id
|
37
|
+
|
38
|
+
results << {id: file.entity_id, type: file.type, filename: file.basename}
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
results.sort_by { | r | [r[:id], r[:type]] }.each {|r| puts "#{r[:id]}, #{r[:type]}, #{r[:filename]}" }
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module MDQT
|
2
|
+
|
3
|
+
class CLI
|
4
|
+
|
5
|
+
require 'mdqt/cli/base'
|
6
|
+
|
7
|
+
class Rename < Base
|
8
|
+
|
9
|
+
def run
|
10
|
+
|
11
|
+
options.validate = true
|
12
|
+
|
13
|
+
advise_on_xml_signing_support
|
14
|
+
halt!("Cannot check a metadata file without XML support: please install additional gems") unless MDQT::Client.verification_available?
|
15
|
+
|
16
|
+
client = MDQT::Client.new(
|
17
|
+
options.service,
|
18
|
+
verbose: options.verbose,
|
19
|
+
explain: options.explain ? true : false,
|
20
|
+
)
|
21
|
+
|
22
|
+
halt!("Please specify a file to rename!") if args.empty?
|
23
|
+
|
24
|
+
args.each do |filename|
|
25
|
+
|
26
|
+
next if File.symlink?(filename)
|
27
|
+
|
28
|
+
file = client.open_metadata(filename)
|
29
|
+
|
30
|
+
halt!("Cannot access file #{filename}") unless file.readable?
|
31
|
+
halt!("File #{filename} is a metadata aggregate, cannot rename to hashed entityID!") if file.aggregate?
|
32
|
+
halt!("XML validation failed for #{filename}:\n#{file.validation_error}") unless file.valid?
|
33
|
+
|
34
|
+
halt!("Cannot find entityID for #{filename}") unless file.entity_id
|
35
|
+
|
36
|
+
newname = file.linkname # Using the same name as the link, not super-obvious
|
37
|
+
next if filename == newname
|
38
|
+
|
39
|
+
if file.turd?
|
40
|
+
hey "Warning: will not process backup/turd files"
|
41
|
+
next
|
42
|
+
end
|
43
|
+
|
44
|
+
message = ""
|
45
|
+
|
46
|
+
if File.exist?(newname)
|
47
|
+
if options.force
|
48
|
+
File.delete(newname)
|
49
|
+
else
|
50
|
+
halt!("Cannot rename #{filename} to #{newname} - File exists! Use --force to override")
|
51
|
+
next
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
File.rename(filename, newname)
|
56
|
+
|
57
|
+
if options.link
|
58
|
+
File.delete(filename) if options.force && File.exist?(filename)
|
59
|
+
File.symlink(newname, filename) unless newname == filename
|
60
|
+
end
|
61
|
+
|
62
|
+
hey("#{filename} renamed to #{newname} [#{file.entity_id}] #{message}") if options.verbose
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module MDQT
|
2
|
+
|
3
|
+
class CLI
|
4
|
+
|
5
|
+
require 'mdqt/cli/base'
|
6
|
+
|
7
|
+
class Reset < Base
|
8
|
+
|
9
|
+
def run
|
10
|
+
|
11
|
+
client = MDQT::Client.new(
|
12
|
+
:not_required,
|
13
|
+
verbose: false,
|
14
|
+
cache_type: :file
|
15
|
+
)
|
16
|
+
|
17
|
+
print "Removing all cached files... "
|
18
|
+
client.cache_reset!
|
19
|
+
yay "done."
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MDQT
|
2
|
+
|
3
|
+
class CLI
|
4
|
+
|
5
|
+
require 'mdqt/cli/base'
|
6
|
+
|
7
|
+
class Services < Base
|
8
|
+
|
9
|
+
def run
|
10
|
+
|
11
|
+
puts "\nKnown services:"
|
12
|
+
puts
|
13
|
+
MDQT::CLI::Defaults.services.each do |service|
|
14
|
+
puts "#{service[:alias]}: #{service[:url]}"
|
15
|
+
end
|
16
|
+
puts
|
17
|
+
puts "Specify these in commands using the --service option or MDQ_BASE_URL environment variable"
|
18
|
+
puts
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module MDQT
|
2
|
+
|
3
|
+
class CLI
|
4
|
+
|
5
|
+
require 'mdqt/cli/base'
|
6
|
+
|
7
|
+
class Transform < Base
|
8
|
+
|
9
|
+
IdentifierUtils = MDQT::Client::IdentifierUtils
|
10
|
+
|
11
|
+
def run
|
12
|
+
|
13
|
+
halt!("No entityIDs have been specified!") if args.empty?
|
14
|
+
|
15
|
+
args.each do |arg|
|
16
|
+
puts transform(arg)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def transform(arg)
|
22
|
+
arg = arg.strip
|
23
|
+
return arg if IdentifierUtils.valid_transformed?(arg)
|
24
|
+
return IdentifierUtils.correct_lazy_transformed(arg) if IdentifierUtils.lazy_transformed?(arg)
|
25
|
+
return IdentifierUtils.correct_fish_transformed(arg) if IdentifierUtils.fish_transformed?(arg)
|
26
|
+
IdentifierUtils.transform_uri(arg)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
data/lib/mdqt/cli/url.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module MDQT
|
2
|
+
|
3
|
+
class CLI
|
4
|
+
|
5
|
+
require 'mdqt/cli/base'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
class URL < Base
|
9
|
+
|
10
|
+
def run
|
11
|
+
|
12
|
+
mds = MDQT::Client::MetadataService.new(service_url(options),
|
13
|
+
verbose:false,
|
14
|
+
cache_type: :none,
|
15
|
+
explain: false,
|
16
|
+
tls_cert_check: false)
|
17
|
+
|
18
|
+
if args.empty?
|
19
|
+
puts service_url(options)
|
20
|
+
else
|
21
|
+
args.each do |arg|
|
22
|
+
puts build_url(mds, arg)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_url(mds, entity_id)
|
29
|
+
|
30
|
+
URI.join(service_url(options), "entities/#{mds.prepare_id(entity_id)}")
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
data/lib/mdqt/cli.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module MDQT
|
2
|
+
class CLI
|
3
|
+
|
4
|
+
require 'mdqt/client'
|
5
|
+
|
6
|
+
require 'mdqt/cli/defaults'
|
7
|
+
require 'mdqt/cli/cache_control'
|
8
|
+
|
9
|
+
require 'mdqt/cli/get'
|
10
|
+
require 'mdqt/cli/reset'
|
11
|
+
require 'mdqt/cli/version'
|
12
|
+
require 'mdqt/cli/transform'
|
13
|
+
require 'mdqt/cli/check'
|
14
|
+
require 'mdqt/cli/entities'
|
15
|
+
require 'mdqt/cli/ln'
|
16
|
+
require 'mdqt/cli/ls'
|
17
|
+
require 'mdqt/cli/list'
|
18
|
+
require 'mdqt/cli/services'
|
19
|
+
require 'mdqt/cli/rename'
|
20
|
+
require 'mdqt/cli/url'
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module MDQT
|
2
|
+
class Client
|
3
|
+
|
4
|
+
module IdentifierUtils
|
5
|
+
|
6
|
+
require 'digest'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def uri_to_sha1(uri)
|
11
|
+
raise "An empty string cannot be transformed" if uri.empty?
|
12
|
+
Digest::SHA1.hexdigest(uri.to_s.strip)
|
13
|
+
end
|
14
|
+
|
15
|
+
def transform_uri(uri)
|
16
|
+
"{sha1}#{uri_to_sha1(uri)}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def normalize_to_sha1(identifier)
|
20
|
+
identifier.start_with?("{sha1}") ?
|
21
|
+
identifier.gsub("{sha1}", "") :
|
22
|
+
uri_to_sha1(identifier)
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid_transformed?(string)
|
26
|
+
(string =~ /^[{]sha1[}][0-9a-f]{40}$/i).nil? ? false : true
|
27
|
+
end
|
28
|
+
|
29
|
+
def lazy_transformed?(string)
|
30
|
+
(string =~ /^[\[]sha1[\]][0-9a-f]{40}$/i).nil? ? false : true
|
31
|
+
end
|
32
|
+
|
33
|
+
def fish_transformed?(string)
|
34
|
+
(string =~ /^sha1[0-9a-f]{40}$/i).nil? ? false : true
|
35
|
+
end
|
36
|
+
|
37
|
+
def correct_lazy_transformed(lazy)
|
38
|
+
lazy.gsub("[sha1]", "{sha1}").downcase
|
39
|
+
end
|
40
|
+
|
41
|
+
def correct_fish_transformed(lazy)
|
42
|
+
lazy.gsub("sha1", "{sha1}").downcase
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
module MDQT
|
2
|
+
class Client
|
3
|
+
|
4
|
+
class MetadataFile
|
5
|
+
|
6
|
+
require 'digest'
|
7
|
+
|
8
|
+
def initialize(filename, options = {})
|
9
|
+
@filename = File.absolute_path(filename)
|
10
|
+
@data = nil
|
11
|
+
@expires = nil
|
12
|
+
@etag = nil
|
13
|
+
@last_modified = nil
|
14
|
+
@explanation = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def filename
|
18
|
+
@filename
|
19
|
+
end
|
20
|
+
|
21
|
+
def basename
|
22
|
+
File.basename(filename)
|
23
|
+
end
|
24
|
+
|
25
|
+
def identifier
|
26
|
+
entity_id
|
27
|
+
end
|
28
|
+
|
29
|
+
def entity_id
|
30
|
+
raise "Incorrect metadata file type - aggregate" if aggregate?
|
31
|
+
@entity_id ||= extract_entity_id
|
32
|
+
end
|
33
|
+
|
34
|
+
def entity_ids
|
35
|
+
@entity_ids ||= extract_entity_ids
|
36
|
+
end
|
37
|
+
|
38
|
+
def data
|
39
|
+
@data ||= File.read(filename)
|
40
|
+
end
|
41
|
+
|
42
|
+
def readable?
|
43
|
+
File.readable?(filename)
|
44
|
+
end
|
45
|
+
|
46
|
+
def turd?
|
47
|
+
return true if basename.end_with?("~")
|
48
|
+
return true if basename.end_with?(".bak")
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
def type
|
53
|
+
@type ||= calculate_type
|
54
|
+
end
|
55
|
+
|
56
|
+
def aggregate?
|
57
|
+
type == :aggregate
|
58
|
+
end
|
59
|
+
|
60
|
+
def expires
|
61
|
+
@expires
|
62
|
+
end
|
63
|
+
|
64
|
+
def etag
|
65
|
+
@etag
|
66
|
+
end
|
67
|
+
|
68
|
+
def last_modified
|
69
|
+
@last_modified
|
70
|
+
end
|
71
|
+
|
72
|
+
def ok?
|
73
|
+
@ok
|
74
|
+
end
|
75
|
+
|
76
|
+
def signed?
|
77
|
+
@data.include? "Signature" # This is... not great
|
78
|
+
end
|
79
|
+
|
80
|
+
def verified_signature?(certs = [], _ = {})
|
81
|
+
validator = MetadataValidator.new(certs: [certs].flatten)
|
82
|
+
validator.verified_signature?(self)
|
83
|
+
end
|
84
|
+
|
85
|
+
def valid?
|
86
|
+
validator = MetadataValidator.new
|
87
|
+
validator.valid?(self)
|
88
|
+
end
|
89
|
+
|
90
|
+
def validation_error
|
91
|
+
validator = MetadataValidator.new
|
92
|
+
validator.validation_error(self)
|
93
|
+
end
|
94
|
+
|
95
|
+
def canonical_filename
|
96
|
+
if identifier.empty?
|
97
|
+
@filename = "aggregate-#{Digest::SHA1.hexdigest(@service)}.xml"
|
98
|
+
else
|
99
|
+
@filename ||= identifier.start_with?("{sha1}") ?
|
100
|
+
"#{@identifier.gsub("{sha1}", "")}.xml" :
|
101
|
+
"#{Digest::SHA1.hexdigest(@identifier)}.xml"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def linkname
|
106
|
+
if aggregate?
|
107
|
+
raise "Not supported for aggregates"
|
108
|
+
else
|
109
|
+
"#{Digest::SHA1.hexdigest(entity_id)}.xml"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def symlink?
|
114
|
+
File.symlink?(filename)
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def calculate_type
|
120
|
+
return :aggregate if data.include?("<EntitiesDescriptor")
|
121
|
+
if data.include?("EntityDescriptor")
|
122
|
+
return :alias if symlink?
|
123
|
+
return :entity
|
124
|
+
end
|
125
|
+
:unknown
|
126
|
+
end
|
127
|
+
|
128
|
+
def xml_doc
|
129
|
+
Nokogiri::XML.parse(data).remove_namespaces!
|
130
|
+
end
|
131
|
+
|
132
|
+
def extract_entity_id
|
133
|
+
xml_doc.xpath("/EntityDescriptor/@entityID").text
|
134
|
+
end
|
135
|
+
|
136
|
+
def extract_entity_ids
|
137
|
+
xml_doc.xpath("//EntityDescriptor/@entityID").map(&:text)
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module MDQT
|
2
|
+
class Client
|
3
|
+
|
4
|
+
class MetadataResponse
|
5
|
+
|
6
|
+
require 'digest'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
def initialize(identifier, service, http_response, options = {})
|
10
|
+
|
11
|
+
@requested_identitier = identifier
|
12
|
+
@identifier = URI.decode_www_form_component(identifier)
|
13
|
+
@service = service
|
14
|
+
@code = http_response.status || 500
|
15
|
+
@data = http_response.body || ""
|
16
|
+
@type = nil
|
17
|
+
@content_type = http_response.headers['Content-Type']
|
18
|
+
@expires = http_response.headers['Expires']
|
19
|
+
@etag = http_response.headers['ETag']
|
20
|
+
@last_modified = http_response.headers['Last-Modified']
|
21
|
+
@ok = http_response.success?
|
22
|
+
@explanation = {}
|
23
|
+
|
24
|
+
if options[:explain]
|
25
|
+
@explanation[:url] = http_response.env.url.to_s
|
26
|
+
@explanation[:method] = http_response.env.method.to_s.upcase
|
27
|
+
@explanation[:status] = http_response.status
|
28
|
+
@explanation[:response_headers] = http_response.headers
|
29
|
+
@explanation[:request_headers] = http_response.env.request_headers
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def identifier
|
35
|
+
@identifier
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def requested_identifier
|
40
|
+
@identifier
|
41
|
+
end
|
42
|
+
|
43
|
+
def entity_id
|
44
|
+
raise "Incorrect metadata file type - aggregate" if aggregate?
|
45
|
+
@entity_id ||= extract_entity_id
|
46
|
+
end
|
47
|
+
|
48
|
+
def entity_ids
|
49
|
+
@entity_ids ||= extract_entity_ids
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def service
|
54
|
+
@service
|
55
|
+
end
|
56
|
+
|
57
|
+
def code
|
58
|
+
@code
|
59
|
+
end
|
60
|
+
|
61
|
+
def data
|
62
|
+
@data || ""
|
63
|
+
end
|
64
|
+
|
65
|
+
def type
|
66
|
+
@type ||= calculate_type
|
67
|
+
end
|
68
|
+
|
69
|
+
def content_type
|
70
|
+
@content_type
|
71
|
+
end
|
72
|
+
|
73
|
+
def expires
|
74
|
+
@expires
|
75
|
+
end
|
76
|
+
|
77
|
+
def etag
|
78
|
+
@etag
|
79
|
+
end
|
80
|
+
|
81
|
+
def last_modified
|
82
|
+
@last_modified
|
83
|
+
end
|
84
|
+
|
85
|
+
def ok?
|
86
|
+
@ok
|
87
|
+
end
|
88
|
+
|
89
|
+
def signed?
|
90
|
+
@data.include? "Signature" # This is... not great
|
91
|
+
end
|
92
|
+
|
93
|
+
def verified_signature?(certs = [], _ = {})
|
94
|
+
return true unless ok? # CHECK ?
|
95
|
+
validator = MetadataValidator.new(certs: [certs].flatten)
|
96
|
+
validator.verified_signature?(self)
|
97
|
+
end
|
98
|
+
|
99
|
+
def valid?
|
100
|
+
validator = MetadataValidator.new
|
101
|
+
validator.valid?(self)
|
102
|
+
end
|
103
|
+
|
104
|
+
def validation_error
|
105
|
+
validator = MetadataValidator.new
|
106
|
+
validator.validation_error(self)
|
107
|
+
end
|
108
|
+
|
109
|
+
def filename
|
110
|
+
if identifier.empty?
|
111
|
+
@filename = "aggregate-#{Digest::SHA1.hexdigest(@service)}.xml"
|
112
|
+
else
|
113
|
+
@filename ||= identifier.start_with?("{sha1}") ?
|
114
|
+
"#{@identifier.gsub("{sha1}","")}.xml" :
|
115
|
+
"#{Digest::SHA1.hexdigest(@identifier)}.xml"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def message
|
120
|
+
case code
|
121
|
+
when 200
|
122
|
+
identifier.empty? ? "[200] OK! Data for aggregate has been downloaded from #{service}" :
|
123
|
+
"[200] OK! Data for '#{identifier}' has been downloaded from #{service}"
|
124
|
+
when 304
|
125
|
+
"[304] OK! Data for '#{identifier}' is already available in a local cache"
|
126
|
+
when 400
|
127
|
+
"[400] The identifier '#{identifier}' ('#{requested_identifier}') is malformed or service URL #{service} is incorrect"
|
128
|
+
when 401
|
129
|
+
"[401] Credentials are incorrect or missing for '#{identifier}'"
|
130
|
+
when 403
|
131
|
+
identifier.empty? ? "[403] The MDQ service at #{service} does not support aggregate downloads" :
|
132
|
+
"[403] You do not have access rights to '#{identifier}' at #{service}"
|
133
|
+
when 404
|
134
|
+
identifier.empty? ? "[404] The MDQ service at #{service} is not responding with aggregated metadata or the correct status" :
|
135
|
+
"[404] Entity metadata for '#{identifier}' was not found at #{service}"
|
136
|
+
when 405
|
137
|
+
"[405] The service at #{service} believes the wrong HTTP method was used. We should have used HTTP GET..."
|
138
|
+
when 406
|
139
|
+
"[406] The requested content type is not available at #{service}"
|
140
|
+
when 500
|
141
|
+
"[500] An error has occurred at #{service}"
|
142
|
+
when 505
|
143
|
+
"[505] The service at #{service} claims our request was using pre-1999 web protocols, not HTTP 1.1 or later"
|
144
|
+
else
|
145
|
+
"[#{code}] Sorry - an unknown error has occurred requesting '#{identifier}' from #{service}.\nPlease report this bug!"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def explanation
|
150
|
+
@explanation
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def calculate_type
|
156
|
+
|
157
|
+
return :html if data[0,1000].include?('<!doctype html>')
|
158
|
+
return :aggregate if data[0,5000].include?("EntitiesDescriptor")
|
159
|
+
if data[0,5000].include?("EntityDescriptor")
|
160
|
+
return :alias if symlink?
|
161
|
+
return :entity
|
162
|
+
end
|
163
|
+
:unknown
|
164
|
+
end
|
165
|
+
|
166
|
+
def xml_doc
|
167
|
+
Nokogiri::XML.parse(data).remove_namespaces!
|
168
|
+
end
|
169
|
+
|
170
|
+
def extract_entity_id
|
171
|
+
xml_doc.xpath("/EntityDescriptor/@entityID").text
|
172
|
+
end
|
173
|
+
|
174
|
+
def extract_entity_ids
|
175
|
+
xml_doc.xpath("//EntityDescriptor/@entityID").map(&:text)
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|