nexpose 0.0.98 → 0.1.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.
@@ -1,108 +1,108 @@
1
- module Nexpose
2
- module NexposeAPI
3
- include XMLUtils
4
-
5
- #
6
- # Create a NeXpose ticket
7
- #
8
- # ticket_info: A hash of the data to be used to create a ticket in NeXpose:
9
- # :name => The name of the ticket (Required)
10
- # :device_id => The NeXpose device ID for the device being ticketed (Required)
11
- # :assigned_to => The NeXpose user to whom this ticket is assigned (Required)
12
- # :priority => "low,moderate,normal,high,critical" (Required)
13
- #
14
- # :vulnerabilities => An array of NeXpose vuln IDs. This is NOT the same as vuln ID. (Required)
15
- # :comments => An array of comments to accompany this ticket
16
- #
17
- # @return The ticket ID if the ticket creation was successful, {@code false} otherwise
18
- #
19
- def create_ticket ticket_info
20
- ticket_name = ticket_info[:name]
21
- unless ticket_name
22
- raise ArgumentError.new 'Ticket name is required'
23
- end
24
-
25
- device_id = ticket_info[:device_id]
26
- unless device_id
27
- raise ArgumentError.new 'Device ID is required'
28
- end
29
-
30
- assigned_to = ticket_info[:assigned_to]
31
- unless assigned_to
32
- raise ArgumentError.new 'Assignee name is required'
33
- end
34
-
35
- priority = ticket_info[:priority]
36
- unless priority
37
- raise ArgumentError.new 'Ticket priority is required'
38
- end
39
-
40
- vulnerabilities = ticket_info[:vulnerabilities]
41
- if not vulnerabilities or vulnerabilities.count < 1
42
- raise ArgumentError.new 'Vulnerabilities are required'
43
- end
44
-
45
- comments = ticket_info[:comments]
46
- base_xml = make_xml 'TicketCreateRequest'
47
-
48
- required_attributes = {
49
- 'name' => ticket_name,
50
- 'priority' => priority,
51
- 'device-id' => device_id,
52
- 'assigned-to' => assigned_to
53
- }
54
-
55
- create_request_xml = REXML::Element.new 'TicketCreate'
56
- create_request_xml.add_attributes required_attributes
57
-
58
- # Add vulnerabilities
59
- vulnerabilities_xml = REXML::Element.new 'Vulnerabilities'
60
- vulnerabilities.each do |vuln_id|
61
- vulnerabilities_xml.add_element 'Vulnerability', {'id' => vuln_id}
62
- end
63
- create_request_xml.add_element vulnerabilities_xml
64
-
65
- # Add comments
66
- if comments and comments.count > 0
67
- comments_xml = REXML::Element.new 'Comments'
68
- comments.each do |comment|
69
- comment_xml = REXML::Element.new 'Comment'
70
- comment_xml.add_text comment
71
- comments_xml.add_element comment_xml
72
- end
73
-
74
- create_request_xml.add_element comments_xml
75
- end
76
-
77
- base_xml.add_element create_request_xml
78
- r = execute base_xml, '1.2'
79
- if r.success
80
- r.res.elements.each('TicketCreateResponse') do |group|
81
- return group.attributes['id'].to_i
82
- end
83
- else
84
- false
85
- end
86
- end
87
-
88
- #
89
- # Deletes a NeXpose ticket.
90
- #
91
- # ticket_ids: An array of ticket IDs to be deleted.
92
- #
93
- # @returns {@code true} iff the call was successfull. {@code false} otherwise.
94
- #
95
- def delete_ticket ticket_ids
96
- if not ticket_ids or ticket_ids.count < 1
97
- raise ArgumentError.new 'The tickets to delete should not be null or empty'
98
- end
99
-
100
- base_xml = make_xml 'TicketDeleteRequest'
101
- ticket_ids.each do |id|
102
- base_xml.add_element 'Ticket', {'id' => id}
103
- end
104
-
105
- (execute base_xml, '1.2').success
106
- end
107
- end
108
- end
1
+ module Nexpose
2
+ module NexposeAPI
3
+ include XMLUtils
4
+
5
+ #
6
+ # Create a Nexpose ticket
7
+ #
8
+ # ticket_info: A hash of the data to be used to create a ticket in Nexpose:
9
+ # :name => The name of the ticket (Required)
10
+ # :device_id => The Nexpose device ID for the device being ticketed (Required)
11
+ # :assigned_to => The Nexpose user to whom this ticket is assigned (Required)
12
+ # :priority => "low,moderate,normal,high,critical" (Required)
13
+ #
14
+ # :vulnerabilities => An array of Nexpose vuln IDs. This is NOT the same as vuln ID. (Required)
15
+ # :comments => An array of comments to accompany this ticket
16
+ #
17
+ # @return The ticket ID if the ticket creation was successful, {@code false} otherwise
18
+ #
19
+ def create_ticket ticket_info
20
+ ticket_name = ticket_info[:name]
21
+ unless ticket_name
22
+ raise ArgumentError.new 'Ticket name is required'
23
+ end
24
+
25
+ device_id = ticket_info[:device_id]
26
+ unless device_id
27
+ raise ArgumentError.new 'Device ID is required'
28
+ end
29
+
30
+ assigned_to = ticket_info[:assigned_to]
31
+ unless assigned_to
32
+ raise ArgumentError.new 'Assignee name is required'
33
+ end
34
+
35
+ priority = ticket_info[:priority]
36
+ unless priority
37
+ raise ArgumentError.new 'Ticket priority is required'
38
+ end
39
+
40
+ vulnerabilities = ticket_info[:vulnerabilities]
41
+ if not vulnerabilities or vulnerabilities.count < 1
42
+ raise ArgumentError.new 'Vulnerabilities are required'
43
+ end
44
+
45
+ comments = ticket_info[:comments]
46
+ base_xml = make_xml 'TicketCreateRequest'
47
+
48
+ required_attributes = {
49
+ 'name' => ticket_name,
50
+ 'priority' => priority,
51
+ 'device-id' => device_id,
52
+ 'assigned-to' => assigned_to
53
+ }
54
+
55
+ create_request_xml = REXML::Element.new 'TicketCreate'
56
+ create_request_xml.add_attributes required_attributes
57
+
58
+ # Add vulnerabilities
59
+ vulnerabilities_xml = REXML::Element.new 'Vulnerabilities'
60
+ vulnerabilities.each do |vuln_id|
61
+ vulnerabilities_xml.add_element 'Vulnerability', {'id' => vuln_id}
62
+ end
63
+ create_request_xml.add_element vulnerabilities_xml
64
+
65
+ # Add comments
66
+ if comments and comments.count > 0
67
+ comments_xml = REXML::Element.new 'Comments'
68
+ comments.each do |comment|
69
+ comment_xml = REXML::Element.new 'Comment'
70
+ comment_xml.add_text comment
71
+ comments_xml.add_element comment_xml
72
+ end
73
+
74
+ create_request_xml.add_element comments_xml
75
+ end
76
+
77
+ base_xml.add_element create_request_xml
78
+ r = execute base_xml, '1.2'
79
+ if r.success
80
+ r.res.elements.each('TicketCreateResponse') do |group|
81
+ return group.attributes['id'].to_i
82
+ end
83
+ else
84
+ false
85
+ end
86
+ end
87
+
88
+ #
89
+ # Deletes a Nexpose ticket.
90
+ #
91
+ # ticket_ids: An array of ticket IDs to be deleted.
92
+ #
93
+ # @returns {@code true} iff the call was successfull. {@code false} otherwise.
94
+ #
95
+ def delete_ticket ticket_ids
96
+ if not ticket_ids or ticket_ids.count < 1
97
+ raise ArgumentError.new 'The tickets to delete should not be null or empty'
98
+ end
99
+
100
+ base_xml = make_xml 'TicketDeleteRequest'
101
+ ticket_ids.each do |id|
102
+ base_xml.add_element 'Ticket', {'id' => id}
103
+ end
104
+
105
+ (execute base_xml, '1.2').success
106
+ end
107
+ end
108
+ end
@@ -1,221 +1,223 @@
1
- module Nexpose
2
-
3
- # Summary only returned by API when issuing a listing request.
4
- class UserSummary
5
- attr_reader :id, :auth_source, :auth_module, :user_name, :full_name, :email
6
- attr_reader :is_admin, :is_disabled, :is_locked, :site_count, :group_count
7
-
8
- def initialize(id, auth_source, auth_module, user_name, full_name, email, is_admin, is_disabled, is_locked, site_count, group_count)
9
- @id = id
10
- @auth_source = auth_source
11
- @auth_module = auth_module
12
- @user_name = user_name
13
- @full_name = full_name
14
- @email = email
15
- @is_admin = is_admin
16
- @is_disabled = is_disabled
17
- @is_locked = is_locked
18
- @site_count = site_count
19
- @group_count = group_count
20
- end
21
-
22
- def to_s
23
- out = "#{@user_name} (#{@full_name}) [ID: #{@id}]"
24
- out << " e-mail: #{@email}" unless @email.empty?
25
- out << " Administrator" if @is_admin
26
- out << " Disabled" if @is_disabled
27
- out << " Locked" if @is_locked
28
- out << ", sites: #{@site_count}"
29
- out << ", groups: #{@group_count}"
30
- end
31
-
32
- # Provide a list of user accounts and information about those accounts.
33
- def self.listing(connection)
34
- xml = '<UserListingRequest session-id="' + connection.session_id + '" />'
35
- r = connection.execute(xml, '1.1')
36
- if r.success
37
- res = []
38
- r.res.elements.each('UserListingResponse/UserSummary') do |summary|
39
- res << UserSummary.new(
40
- summary.attributes['id'].to_i,
41
- summary.attributes['authSource'],
42
- summary.attributes['authModule'],
43
- summary.attributes['userName'],
44
- summary.attributes['fullName'],
45
- summary.attributes['email'],
46
- summary.attributes['administrator'].to_s.chomp.eql?('1'),
47
- summary.attributes['disabled'].to_s.chomp.eql?('1'),
48
- summary.attributes['locked'].to_s.chomp.eql?('1'),
49
- summary.attributes['siteCount'].to_i,
50
- summary.attributes['groupCount'].to_i)
51
- end
52
- res
53
- else
54
- false
55
- end
56
- end
57
-
58
- # Retrieve the User ID based upon the user's login name.
59
- def self.get_user_id(connection, user_name)
60
- xml = '<UserListingRequest session-id="' + connection.session_id + '" />'
61
- r = connection.execute(xml, '1.1')
62
- if r.success
63
- r.res.elements.each('UserListingResponse/UserSummary') do |user|
64
- return user.attributes['id'] if user_name.eql? user.attributes['userName']
65
- end
66
- end
67
- return -1
68
- end
69
- end
70
-
71
- class UserConfig
72
- # user id, set to -1 to create a new user
73
- attr_reader :id
74
- # valid roles: global-admin|security-manager|site-admin|system-admin|user|custom
75
- attr_accessor :role_name
76
- # Required fields
77
- attr_reader :name
78
- attr_accessor :full_name
79
- # Will default to XML (1) for global-admin, Data Source (2) otherwise,
80
- # but caller can override (e.g., using LDAP authenticator).
81
- attr_accessor :authsrcid
82
- # Optional fields
83
- attr_accessor :email, :password, :sites, :groups
84
- # 1 to enable this user, 0 to disable
85
- attr_accessor :enabled
86
- # Boolean values
87
- attr_accessor :all_sites, :all_groups
88
-
89
- def initialize(name, full_name, password, role_name = 'user', id = -1, enabled = 1, email = nil, all_sites = false, all_groups = false)
90
- @name = name
91
- @password = password
92
- @role_name = role_name
93
- @authsrcid = ('global-admin'.eql? @role_name) ? '1' : '2'
94
- @id = id
95
- @enabled = enabled
96
- @full_name = full_name
97
- @email = email
98
- @all_sites = all_sites || role_name == 'global-admin'
99
- @all_groups = all_groups || role_name == 'global-admin'
100
- @sites = []
101
- @groups = []
102
- end
103
-
104
- def to_s
105
- out = "#{@user_name} (#{@full_name}) [ID: #{@id}, Role: #{@role_name}]"
106
- out << " Disabled" unless @enabled
107
- out << " All-Sites" if @all_sites
108
- out << " All-Groups" if @all_groups
109
- out << " e-mail: #{@email}" unless @email.nil? || @email.empty?
110
- out
111
- end
112
-
113
- def to_xml
114
- xml = "<UserConfig"
115
- xml << %Q{ id="#{@id}"}
116
- xml << %Q{ authsrcid="#{@authsrcid}"}
117
- xml << %Q{ name="#{@name}"}
118
- xml << %Q{ fullname="#{@full_name}"}
119
- xml << %Q{ role-name="#{@role_name}"}
120
- xml << %Q{ password="#{@password}"} if @password
121
- xml << %Q{ email="#{@email}"} if @email
122
- xml << %Q{ enabled="#{@enabled}"}
123
- # These two fields are keying off role_name to work around a defect.
124
- xml << %Q{ allGroups="#{@all_groups || @role_name == 'global-admin'}"}
125
- xml << %Q{ allSites="#{@all_sites || @role_name == 'global-admin'}"}
126
- xml << ">"
127
- @sites.each do |site|
128
- xml << %Q{<site id="#{site}" />}
129
- end
130
- @groups.each do |group|
131
- xml << %Q{<group id="#{group}" />}
132
- end
133
- xml << '</UserConfig>'
134
- end
135
-
136
- # Save a user configuration. Returns the (new) user ID if successful.
137
- def save(connection)
138
- xml = '<UserSaveRequest session-id="' + connection.session_id + '">'
139
- xml << to_xml
140
- xml << '</UserSaveRequest>'
141
- r = connection.execute(xml, '1.1')
142
- if r.success
143
- res = []
144
- r.res.elements.each('UserSaveResponse') do |attr|
145
- @id = attr.attributes['id'].to_i
146
- end
147
- @id
148
- else
149
- -1
150
- end
151
- end
152
-
153
- # Issue a UserConfigRequest to load an existing UserConfig from Nexpose.
154
- def self.load(connection, user_id)
155
- xml = '<UserConfigRequest session-id="' + connection.session_id + '"'
156
- xml << %Q{ id="#{user_id}"}
157
- xml << ' />'
158
- r = connection.execute(xml, '1.1')
159
- if r.success
160
- r.res.elements.each('UserConfigResponse/UserConfig') do |config|
161
- id = config.attributes['id']
162
- role_name = config.attributes['role-name']
163
- authsrcid = config.attributes['authsrcid']
164
- name = config.attributes['name']
165
- fullname = config.attributes['fullname']
166
-
167
- email = config.attributes['email']
168
- password = config.attributes['password']
169
- enabled = config.attributes['enabled'].to_i
170
- all_sites = config.attributes['allSites'] == 'true' ? true : false
171
- all_groups = config.attributes['allGroups'] == 'true' ? true : false
172
- # Not trying to load sites and groups.
173
- # Looks like API currently doesn't return that info to load.
174
- return UserConfig.new(name, fullname, password, role_name, id, enabled, email, all_sites, all_groups)
175
- end
176
- end
177
- end
178
-
179
- # Delete a user account.
180
- def self.delete(connection, user_id)
181
- xml = '<UserDeleteRequest session-id="' + connection.session_id + '"'
182
- xml << %Q{ id="#{user_id}"}
183
- xml << ' />'
184
- r = connection.execute(xml, '1.1')
185
- if r.success
186
- r.res.elements.each('UserConfigResponse/UserConfig') do |config|
187
- '1'.eql? config.attributes['id']
188
- end
189
- end
190
- end
191
-
192
- # Delete the user account associated with this object.
193
- def delete(connection)
194
- UserConfig.delete(connection, @id)
195
- end
196
- end
197
-
198
- class UserAuthenticator
199
- attr_reader :id, :auth_source, :auth_module, :external
200
-
201
- def initialize(id, auth_module, auth_source, external = false)
202
- @id = id
203
- @auth_source = auth_source
204
- @auth_module = auth_module
205
- @external = external
206
- end
207
-
208
- # Provide a list of user authentication sources.
209
- # * *Returns* : An array of known user authenticator sources.
210
- def self.list(connection)
211
- r = connection.execute('<UserAuthenticatorListingRequest session-id="' + connection.session_id + '" />', '1.1')
212
- if r.success
213
- modules = []
214
- r.res.elements.each('UserAuthenticatorListingResponse/AuthenticatorSummary') do |summary|
215
- modules << UserAuthenticator.new(summary.attributes['id'], summary.attributes['authModule'], summary.attributes['authSource'], ('1'.eql? summary.attributes['external']))
216
- end
217
- modules
218
- end
219
- end
220
- end
221
- end
1
+ module Nexpose
2
+
3
+ # Summary only returned by API when issuing a listing request.
4
+ class UserSummary
5
+ attr_reader :id, :auth_source, :auth_module, :user_name, :full_name, :email
6
+ attr_reader :is_admin, :is_disabled, :is_locked, :site_count, :group_count
7
+
8
+ def initialize(id, auth_source, auth_module, user_name, full_name, email, is_admin, is_disabled, is_locked, site_count, group_count)
9
+ @id = id
10
+ @auth_source = auth_source
11
+ @auth_module = auth_module
12
+ @user_name = user_name
13
+ @full_name = full_name
14
+ @email = email
15
+ @is_admin = is_admin
16
+ @is_disabled = is_disabled
17
+ @is_locked = is_locked
18
+ @site_count = site_count
19
+ @group_count = group_count
20
+ end
21
+
22
+ def to_s
23
+ out = "#{@user_name} (#{@full_name}) [ID: #{@id}]"
24
+ out << " e-mail: #{@email}" unless @email.empty?
25
+ out << " Administrator" if @is_admin
26
+ out << " Disabled" if @is_disabled
27
+ out << " Locked" if @is_locked
28
+ out << ", sites: #{@site_count}"
29
+ out << ", groups: #{@group_count}"
30
+ end
31
+
32
+ # Provide a list of user accounts and information about those accounts.
33
+ def self.listing(connection)
34
+ xml = '<UserListingRequest session-id="' + connection.session_id + '" />'
35
+ r = connection.execute(xml, '1.1')
36
+ if r.success
37
+ res = []
38
+ r.res.elements.each('UserListingResponse/UserSummary') do |summary|
39
+ res << UserSummary.new(
40
+ summary.attributes['id'].to_i,
41
+ summary.attributes['authSource'],
42
+ summary.attributes['authModule'],
43
+ summary.attributes['userName'],
44
+ summary.attributes['fullName'],
45
+ summary.attributes['email'],
46
+ summary.attributes['administrator'].to_s.chomp.eql?('1'),
47
+ summary.attributes['disabled'].to_s.chomp.eql?('1'),
48
+ summary.attributes['locked'].to_s.chomp.eql?('1'),
49
+ summary.attributes['siteCount'].to_i,
50
+ summary.attributes['groupCount'].to_i)
51
+ end
52
+ res
53
+ else
54
+ false
55
+ end
56
+ end
57
+
58
+ # Retrieve the User ID based upon the user's login name.
59
+ def self.get_user_id(connection, user_name)
60
+ xml = '<UserListingRequest session-id="' + connection.session_id + '" />'
61
+ r = connection.execute(xml, '1.1')
62
+ if r.success
63
+ r.res.elements.each('UserListingResponse/UserSummary') do |user|
64
+ return user.attributes['id'] if user_name.eql? user.attributes['userName']
65
+ end
66
+ end
67
+ return -1
68
+ end
69
+ end
70
+
71
+ class UserConfig
72
+ include Sanitize
73
+
74
+ # user id, set to -1 to create a new user
75
+ attr_reader :id
76
+ # valid roles: global-admin|security-manager|site-admin|system-admin|user|custom
77
+ attr_accessor :role_name
78
+ # Required fields
79
+ attr_reader :name
80
+ attr_accessor :full_name
81
+ # Will default to XML (1) for global-admin, Data Source (2) otherwise,
82
+ # but caller can override (e.g., using LDAP authenticator).
83
+ attr_accessor :authsrcid
84
+ # Optional fields
85
+ attr_accessor :email, :password, :sites, :groups
86
+ # 1 to enable this user, 0 to disable
87
+ attr_accessor :enabled
88
+ # Boolean values
89
+ attr_accessor :all_sites, :all_groups
90
+
91
+ def initialize(name, full_name, password, role_name = 'user', id = -1, enabled = 1, email = nil, all_sites = false, all_groups = false)
92
+ @name = name
93
+ @password = password
94
+ @role_name = role_name
95
+ @authsrcid = ('global-admin'.eql? @role_name) ? '1' : '2'
96
+ @id = id
97
+ @enabled = enabled
98
+ @full_name = full_name
99
+ @email = email
100
+ @all_sites = all_sites || role_name == 'global-admin'
101
+ @all_groups = all_groups || role_name == 'global-admin'
102
+ @sites = []
103
+ @groups = []
104
+ end
105
+
106
+ def to_s
107
+ out = "#{@user_name} (#{@full_name}) [ID: #{@id}, Role: #{@role_name}]"
108
+ out << " Disabled" unless @enabled
109
+ out << " All-Sites" if @all_sites
110
+ out << " All-Groups" if @all_groups
111
+ out << " e-mail: #{@email}" unless @email.nil? || @email.empty?
112
+ out
113
+ end
114
+
115
+ def to_xml
116
+ xml = "<UserConfig"
117
+ xml << %Q{ id="#{@id}"}
118
+ xml << %Q{ authsrcid="#{@authsrcid}"}
119
+ xml << %Q{ name="#{@name}"}
120
+ xml << %Q{ fullname="#{@full_name}"}
121
+ xml << %Q{ role-name="#{@role_name}"}
122
+ xml << %Q{ password="#{replace_entities(@password)}"} if @password
123
+ xml << %Q{ email="#{@email}"} if @email
124
+ xml << %Q{ enabled="#{@enabled}"}
125
+ # These two fields are keying off role_name to work around a defect.
126
+ xml << %Q{ allGroups="#{@all_groups || @role_name == 'global-admin'}"}
127
+ xml << %Q{ allSites="#{@all_sites || @role_name == 'global-admin'}"}
128
+ xml << ">"
129
+ @sites.each do |site|
130
+ xml << %Q{<site id="#{site}" />}
131
+ end
132
+ @groups.each do |group|
133
+ xml << %Q{<group id="#{group}" />}
134
+ end
135
+ xml << '</UserConfig>'
136
+ end
137
+
138
+ # Save a user configuration. Returns the (new) user ID if successful.
139
+ def save(connection)
140
+ xml = '<UserSaveRequest session-id="' + connection.session_id + '">'
141
+ xml << to_xml
142
+ xml << '</UserSaveRequest>'
143
+ r = connection.execute(xml, '1.1')
144
+ if r.success
145
+ res = []
146
+ r.res.elements.each('UserSaveResponse') do |attr|
147
+ @id = attr.attributes['id'].to_i
148
+ end
149
+ @id
150
+ else
151
+ -1
152
+ end
153
+ end
154
+
155
+ # Issue a UserConfigRequest to load an existing UserConfig from Nexpose.
156
+ def self.load(connection, user_id)
157
+ xml = '<UserConfigRequest session-id="' + connection.session_id + '"'
158
+ xml << %Q{ id="#{user_id}"}
159
+ xml << ' />'
160
+ r = connection.execute(xml, '1.1')
161
+ if r.success
162
+ r.res.elements.each('UserConfigResponse/UserConfig') do |config|
163
+ id = config.attributes['id']
164
+ role_name = config.attributes['role-name']
165
+ authsrcid = config.attributes['authsrcid']
166
+ name = config.attributes['name']
167
+ fullname = config.attributes['fullname']
168
+
169
+ email = config.attributes['email']
170
+ password = config.attributes['password']
171
+ enabled = config.attributes['enabled'].to_i
172
+ all_sites = config.attributes['allSites'] == 'true' ? true : false
173
+ all_groups = config.attributes['allGroups'] == 'true' ? true : false
174
+ # Not trying to load sites and groups.
175
+ # Looks like API currently doesn't return that info to load.
176
+ return UserConfig.new(name, fullname, password, role_name, id, enabled, email, all_sites, all_groups)
177
+ end
178
+ end
179
+ end
180
+
181
+ # Delete a user account.
182
+ def self.delete(connection, user_id)
183
+ xml = '<UserDeleteRequest session-id="' + connection.session_id + '"'
184
+ xml << %Q{ id="#{user_id}"}
185
+ xml << ' />'
186
+ r = connection.execute(xml, '1.1')
187
+ if r.success
188
+ r.res.elements.each('UserConfigResponse/UserConfig') do |config|
189
+ '1'.eql? config.attributes['id']
190
+ end
191
+ end
192
+ end
193
+
194
+ # Delete the user account associated with this object.
195
+ def delete(connection)
196
+ UserConfig.delete(connection, @id)
197
+ end
198
+ end
199
+
200
+ class UserAuthenticator
201
+ attr_reader :id, :auth_source, :auth_module, :external
202
+
203
+ def initialize(id, auth_module, auth_source, external = false)
204
+ @id = id
205
+ @auth_source = auth_source
206
+ @auth_module = auth_module
207
+ @external = external
208
+ end
209
+
210
+ # Provide a list of user authentication sources.
211
+ # * *Returns* : An array of known user authenticator sources.
212
+ def self.list(connection)
213
+ r = connection.execute('<UserAuthenticatorListingRequest session-id="' + connection.session_id + '" />', '1.1')
214
+ if r.success
215
+ modules = []
216
+ r.res.elements.each('UserAuthenticatorListingResponse/AuthenticatorSummary') do |summary|
217
+ modules << UserAuthenticator.new(summary.attributes['id'], summary.attributes['authModule'], summary.attributes['authSource'], ('1'.eql? summary.attributes['external']))
218
+ end
219
+ modules
220
+ end
221
+ end
222
+ end
223
+ end