line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::Cisco::ISE; |
2
|
1
|
|
|
1
|
|
59621
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
29
|
|
3
|
1
|
|
|
1
|
|
382
|
use Moose; |
|
1
|
|
|
|
|
398573
|
|
|
1
|
|
|
|
|
5
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# REST IO stuff here |
6
|
1
|
|
|
1
|
|
6639
|
use IO::Socket::SSL qw( SSL_VERIFY_NONE ); |
|
1
|
|
|
|
|
100552
|
|
|
1
|
|
|
|
|
12
|
|
7
|
1
|
|
|
1
|
|
698
|
use LWP::UserAgent; |
|
1
|
|
|
|
|
57344
|
|
|
1
|
|
|
|
|
58
|
|
8
|
1
|
|
|
1
|
|
826
|
use XML::Simple; |
|
1
|
|
|
|
|
7479
|
|
|
1
|
|
|
|
|
7
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# Generics |
11
|
1
|
|
|
1
|
|
409
|
use MIME::Base64; |
|
1
|
|
|
|
|
532
|
|
|
1
|
|
|
|
|
48
|
|
12
|
1
|
|
|
1
|
|
6
|
use URI::Escape; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
43
|
|
13
|
1
|
|
|
1
|
|
346
|
use Data::Dumper; |
|
1
|
|
|
|
|
4360
|
|
|
1
|
|
|
|
|
60
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# Net::Cisco::ISE::* |
16
|
1
|
|
|
1
|
|
359
|
use lib qw(.); |
|
1
|
|
|
|
|
474
|
|
|
1
|
|
|
|
|
5
|
|
17
|
1
|
|
|
1
|
|
376
|
use Net::Cisco::ISE::InternalUser; |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
87
|
|
18
|
1
|
|
|
1
|
|
536
|
use Net::Cisco::ISE::IdentityGroup; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
52
|
|
19
|
1
|
|
|
1
|
|
376
|
use Net::Cisco::ISE::NetworkDevice; |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
87
|
|
20
|
1
|
|
|
1
|
|
551
|
use Net::Cisco::ISE::NetworkDeviceGroup; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
60
|
|
21
|
|
|
|
|
|
|
#use Net::Cisco::ISE::Endpoint; |
22
|
|
|
|
|
|
|
#use Net::Cisco::ISE::EndpointCertificate; |
23
|
|
|
|
|
|
|
#use Net::Cisco::ISE::EndpointIdentityGroup; |
24
|
|
|
|
|
|
|
#use Net::Cisco::ISE::Portal; |
25
|
|
|
|
|
|
|
#use Net::Cisco::ISE::Profile; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
BEGIN { |
28
|
1
|
|
|
1
|
|
11
|
use Exporter (); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
33
|
|
29
|
1
|
|
|
1
|
|
9
|
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $ERROR %actions); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
156
|
|
30
|
1
|
|
|
1
|
|
5
|
$VERSION = '0.05'; |
31
|
1
|
|
|
|
|
24
|
@ISA = qw(Exporter); |
32
|
1
|
|
|
|
|
4
|
@EXPORT = qw(); |
33
|
1
|
|
|
|
|
3
|
@EXPORT_OK = qw(); |
34
|
1
|
|
|
|
|
2
|
%EXPORT_TAGS = (); |
35
|
|
|
|
|
|
|
|
36
|
1
|
|
|
|
|
3258
|
$ERROR = ""; # TODO: Document error properly! |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# Moose! |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
has 'ssl_options' => ( |
42
|
|
|
|
|
|
|
is => 'rw', |
43
|
|
|
|
|
|
|
isa => 'HashRef', |
44
|
|
|
|
|
|
|
default => sub { { 'SSL_verify_mode' => SSL_VERIFY_NONE, 'verify_hostname' => '0' } } |
45
|
|
|
|
|
|
|
); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
has 'ssl' => ( |
48
|
|
|
|
|
|
|
is => 'rw', |
49
|
|
|
|
|
|
|
isa => 'Str', |
50
|
|
|
|
|
|
|
default => '1', |
51
|
|
|
|
|
|
|
); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
has 'hostname' => ( |
54
|
|
|
|
|
|
|
is => 'rw', |
55
|
|
|
|
|
|
|
isa => 'Str', |
56
|
|
|
|
|
|
|
required => '1', |
57
|
|
|
|
|
|
|
); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
has 'port' => ( |
60
|
|
|
|
|
|
|
is => 'rw', |
61
|
|
|
|
|
|
|
isa => 'Str', |
62
|
|
|
|
|
|
|
default => '9060' |
63
|
|
|
|
|
|
|
); |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
has 'mock' => ( |
66
|
|
|
|
|
|
|
is => 'rw', |
67
|
|
|
|
|
|
|
isa => 'Str', |
68
|
|
|
|
|
|
|
default => '0', |
69
|
|
|
|
|
|
|
); |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
has 'debug' => ( |
72
|
|
|
|
|
|
|
is => 'rw', |
73
|
|
|
|
|
|
|
isa => 'Str', |
74
|
|
|
|
|
|
|
default => '0', |
75
|
|
|
|
|
|
|
); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub internalusers # No Moose here :( |
78
|
0
|
|
|
0
|
0
|
|
{ my $self = shift; |
79
|
0
|
|
|
|
|
|
$ERROR = ""; |
80
|
0
|
0
|
|
|
|
|
if (@_) |
81
|
0
|
|
|
|
|
|
{ my %args = @_; |
82
|
0
|
|
|
|
|
|
$self->{"InternalUsers"} = $args{"internalusers"}; |
83
|
0
|
0
|
|
|
|
|
if ($self->mock()) |
84
|
0
|
|
|
|
|
|
{ return $self->{"InternalUsers"}; } |
85
|
0
|
0
|
|
|
|
|
if ($args{"id"}) |
86
|
0
|
|
|
|
|
|
{ $self->{"InternalUsers"} = $self->query("InternalUser","id",$args{"id"}); } |
87
|
|
|
|
|
|
|
} else |
88
|
0
|
|
|
|
|
|
{ $self->{"InternalUsers"} = $self->query("InternalUser"); |
89
|
|
|
|
|
|
|
} |
90
|
0
|
|
|
|
|
|
return $self->{"InternalUsers"}; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub identitygroups # No Moose here :( |
94
|
0
|
|
|
0
|
1
|
|
{ my $self = shift; |
95
|
0
|
|
|
|
|
|
$ERROR = ""; |
96
|
0
|
0
|
|
|
|
|
if (@_) |
97
|
0
|
|
|
|
|
|
{ my %args = @_; |
98
|
0
|
|
|
|
|
|
$self->{"IdentityGroups"} = $args{"identitygroups"}; |
99
|
0
|
0
|
|
|
|
|
if ($self->mock()) |
100
|
0
|
|
|
|
|
|
{ return $self->{"IdentityGroups"}; } |
101
|
0
|
0
|
|
|
|
|
if ($args{"id"}) |
102
|
0
|
|
|
|
|
|
{ $self->{"IdentityGroups"} = $self->query("IdentityGroup","id",$args{"id"}); } |
103
|
|
|
|
|
|
|
} else |
104
|
0
|
|
|
|
|
|
{ $self->{"IdentityGroups"} = $self->query("IdentityGroup"); |
105
|
|
|
|
|
|
|
} |
106
|
0
|
|
|
|
|
|
return $self->{"IdentityGroups"}; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub endpointidentitygroups # No Moose here :( |
110
|
0
|
|
|
0
|
0
|
|
{ my $self = shift; |
111
|
0
|
|
|
|
|
|
$ERROR = ""; |
112
|
0
|
0
|
|
|
|
|
if (@_) |
113
|
0
|
|
|
|
|
|
{ my %args = @_; |
114
|
0
|
|
|
|
|
|
$self->{"EndpointIdentityGroups"} = $args{"endpointidentitygroups"}; |
115
|
0
|
0
|
|
|
|
|
if ($self->mock()) |
116
|
0
|
|
|
|
|
|
{ return $self->{"EndpointIdentityGroups"}; } |
117
|
0
|
0
|
|
|
|
|
if ($args{"id"}) |
118
|
0
|
|
|
|
|
|
{ $self->{"EndpointIdentityGroups"} = $self->query("EndpointIdentityGroup","id",$args{"id"}); } |
119
|
|
|
|
|
|
|
} else |
120
|
0
|
|
|
|
|
|
{ $self->{"EndpointIdentityGroups"} = $self->query("EndpointIdentityGroup"); |
121
|
|
|
|
|
|
|
} |
122
|
0
|
|
|
|
|
|
return $self->{"EndpointIdentityGroups"}; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub networkdevices # No Moose here :( |
126
|
0
|
|
|
0
|
0
|
|
{ my $self = shift; |
127
|
0
|
|
|
|
|
|
$ERROR = ""; |
128
|
0
|
0
|
|
|
|
|
if (@_) |
129
|
0
|
|
|
|
|
|
{ my %args = @_; |
130
|
0
|
|
|
|
|
|
$self->{"NetworkDevices"} = $args{"networkdevices"}; |
131
|
0
|
0
|
|
|
|
|
if ($self->mock()) |
132
|
0
|
|
|
|
|
|
{ return $self->{"NetworkDevices"}; } |
133
|
0
|
0
|
|
|
|
|
if ($args{"id"}) |
134
|
0
|
|
|
|
|
|
{ $self->{"NetworkDevices"} = $self->query("NetworkDevice","id",$args{"id"}); } |
135
|
|
|
|
|
|
|
} else |
136
|
0
|
|
|
|
|
|
{ $self->{"NetworkDevices"} = $self->query("NetworkDevice"); |
137
|
|
|
|
|
|
|
} |
138
|
0
|
|
|
|
|
|
return $self->{"NetworkDevices"}; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
sub networkdevicegroups # No Moose here :( |
142
|
0
|
|
|
0
|
0
|
|
{ my $self = shift; |
143
|
0
|
|
|
|
|
|
$ERROR = ""; |
144
|
0
|
0
|
|
|
|
|
if (@_) |
145
|
0
|
|
|
|
|
|
{ my %args = @_; |
146
|
0
|
|
|
|
|
|
$self->{"NetworkDeviceGroups"} = $args{"networkdevicegroups"}; |
147
|
0
|
0
|
|
|
|
|
if ($self->mock()) |
148
|
0
|
|
|
|
|
|
{ return $self->{"NetworkDeviceGroups"}; } |
149
|
0
|
0
|
|
|
|
|
if ($args{"id"}) |
150
|
0
|
|
|
|
|
|
{ $self->{"NetworkDeviceGroups"} = $self->query("NetworkDeviceGroup","id",$args{"id"}); } |
151
|
|
|
|
|
|
|
} else |
152
|
0
|
|
|
|
|
|
{ $self->{"NetworkDeviceGroups"} = $self->query("NetworkDeviceGroup"); |
153
|
|
|
|
|
|
|
} |
154
|
0
|
|
|
|
|
|
return $self->{"NetworkDeviceGroups"}; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
sub endpoints # No Moose here :( |
158
|
0
|
|
|
0
|
0
|
|
{ my $self = shift; |
159
|
0
|
|
|
|
|
|
$ERROR = ""; |
160
|
0
|
0
|
|
|
|
|
if (@_) |
161
|
0
|
|
|
|
|
|
{ my %args = @_; |
162
|
0
|
|
|
|
|
|
$self->{"Endpoints"} = $args{"endpoints"}; |
163
|
0
|
0
|
|
|
|
|
if ($self->mock()) |
164
|
0
|
|
|
|
|
|
{ return $self->{"Endpoints"}; } |
165
|
0
|
0
|
|
|
|
|
if ($args{"id"}) |
166
|
0
|
|
|
|
|
|
{ $self->{"Endpoints"} = $self->query("Endpoint","id",$args{"id"}); } |
167
|
|
|
|
|
|
|
} else |
168
|
0
|
|
|
|
|
|
{ $self->{"Endpoints"} = $self->query("Endpoint"); |
169
|
|
|
|
|
|
|
} |
170
|
0
|
|
|
|
|
|
return $self->{"Endpoints"}; |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub endpointcertificates # No Moose here :( |
174
|
0
|
|
|
0
|
0
|
|
{ my $self = shift; |
175
|
0
|
|
|
|
|
|
$ERROR = ""; |
176
|
0
|
0
|
|
|
|
|
if (@_) |
177
|
0
|
|
|
|
|
|
{ my %args = @_; |
178
|
0
|
|
|
|
|
|
$self->{"EndpointCertificates"} = $args{"endpointcertificates"}; |
179
|
0
|
0
|
|
|
|
|
if ($self->mock()) |
180
|
0
|
|
|
|
|
|
{ return $self->{"EndpointCertificates"}; } |
181
|
0
|
0
|
|
|
|
|
if ($args{"id"}) |
182
|
0
|
|
|
|
|
|
{ $self->{"EndpointCertificates"} = $self->query("EndpointCertificate","id",$args{"id"}); } |
183
|
|
|
|
|
|
|
} else |
184
|
0
|
|
|
|
|
|
{ $self->{"EndpointCertificates"} = $self->query("EndpointCertificate"); |
185
|
|
|
|
|
|
|
} |
186
|
0
|
|
|
|
|
|
return $self->{"EndpointCertificates"}; |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub portals # No Moose here :( |
190
|
0
|
|
|
0
|
0
|
|
{ my $self = shift; |
191
|
0
|
|
|
|
|
|
$ERROR = ""; |
192
|
0
|
0
|
|
|
|
|
if (@_) |
193
|
0
|
|
|
|
|
|
{ my %args = @_; |
194
|
0
|
|
|
|
|
|
$self->{"Portals"} = $args{"portals"}; |
195
|
0
|
0
|
|
|
|
|
if ($self->mock()) |
196
|
0
|
|
|
|
|
|
{ return $self->{"Portals"}; } |
197
|
0
|
0
|
|
|
|
|
if ($args{"id"}) |
198
|
0
|
|
|
|
|
|
{ $self->{"Portals"} = $self->query("Portal","id",$args{"id"}); } |
199
|
|
|
|
|
|
|
} else |
200
|
0
|
|
|
|
|
|
{ $self->{"Portals"} = $self->query("Portal"); |
201
|
|
|
|
|
|
|
} |
202
|
0
|
|
|
|
|
|
return $self->{"Portals"}; |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
sub profiles # No Moose here :( |
206
|
0
|
|
|
0
|
0
|
|
{ my $self = shift; |
207
|
0
|
|
|
|
|
|
$ERROR = ""; |
208
|
0
|
0
|
|
|
|
|
if (@_) |
209
|
0
|
|
|
|
|
|
{ my %args = @_; |
210
|
0
|
|
|
|
|
|
$self->{"Profiles"} = $args{"profiles"}; |
211
|
0
|
0
|
|
|
|
|
if ($self->mock()) |
212
|
0
|
|
|
|
|
|
{ return $self->{"Profiles"}; } |
213
|
0
|
0
|
|
|
|
|
if ($args{"id"}) |
214
|
0
|
|
|
|
|
|
{ $self->{"Profiles"} = $self->query("Profile","id",$args{"id"}); } |
215
|
|
|
|
|
|
|
} else |
216
|
0
|
|
|
|
|
|
{ $self->{"Profiles"} = $self->query("Profile"); |
217
|
|
|
|
|
|
|
} |
218
|
0
|
|
|
|
|
|
return $self->{"Profiles"}; |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
has 'username' => ( |
223
|
|
|
|
|
|
|
is => 'rw', |
224
|
|
|
|
|
|
|
isa => 'Str', |
225
|
|
|
|
|
|
|
required => '1', |
226
|
|
|
|
|
|
|
); |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
has 'password' => ( |
229
|
|
|
|
|
|
|
is => 'rw', |
230
|
|
|
|
|
|
|
isa => 'Str', |
231
|
|
|
|
|
|
|
required => '1', |
232
|
|
|
|
|
|
|
); |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# Non-Moose |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub query |
237
|
0
|
|
|
0
|
0
|
|
{ my ($self, $type, $key, $value) = @_; |
238
|
0
|
|
|
|
|
|
my $hostname = $self->hostname; |
239
|
0
|
|
|
|
|
|
my $credentials = encode_base64($self->username.":".$self->password); |
240
|
0
|
0
|
|
|
|
|
if ($self->ssl) |
241
|
0
|
|
|
|
|
|
{ $hostname = "https://$hostname"; } else |
242
|
0
|
|
|
|
|
|
{ $hostname = "http://$hostname"; } |
243
|
0
|
0
|
|
|
|
|
$hostname .= ":".$self->port if $self->port; |
244
|
0
|
|
|
|
|
|
my $action = ""; |
245
|
0
|
|
|
|
|
|
my $mode = ""; |
246
|
0
|
|
|
|
|
|
my $accepttype =""; |
247
|
0
|
|
0
|
|
|
|
$key ||= ""; |
248
|
0
|
0
|
|
|
|
|
if ($type eq "InternalUser") |
249
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::InternalUser::actions{"query"}; |
250
|
0
|
|
|
|
|
|
$mode = "InternalUsers"; |
251
|
0
|
|
|
|
|
|
$accepttype = "identity.internaluser.1.0"; |
252
|
0
|
0
|
|
|
|
|
if ($key eq "id") |
253
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::InternalUser::actions{"getById"}.$value; |
254
|
0
|
|
|
|
|
|
$mode = "InternalUser"; |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
} |
257
|
0
|
0
|
|
|
|
|
if ($type eq "IdentityGroup") |
258
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::IdentityGroup::actions{"query"}; |
259
|
0
|
|
|
|
|
|
$mode = "IdentityGroups"; |
260
|
0
|
|
|
|
|
|
$accepttype = "identity.identitygroup.1.0"; |
261
|
0
|
0
|
|
|
|
|
if ($key eq "id") |
262
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::IdentityGroup::actions{"getById"}.$value; |
263
|
0
|
|
|
|
|
|
$mode = "IdentityGroup"; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
0
|
0
|
|
|
|
|
if ($type eq "EndpointIdentityGroup") |
268
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointIdentityGroup::actions{"query"}; |
269
|
0
|
|
|
|
|
|
$mode = "EndpointIdentityGroups"; |
270
|
0
|
|
|
|
|
|
$accepttype = "identity.endpointgroup.1.0"; |
271
|
0
|
0
|
|
|
|
|
if ($key eq "id") |
272
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointIdentityGroup::actions{"getById"}.$value; |
273
|
0
|
|
|
|
|
|
$mode = "EndpointIdentityGroup"; |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
} |
276
|
0
|
0
|
|
|
|
|
if ($type eq "NetworkDevice") |
277
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDevice::actions{"query"}; |
278
|
0
|
|
|
|
|
|
$mode = "NetworkDevices"; |
279
|
0
|
|
|
|
|
|
$accepttype = "network.networkdevice.1.1"; |
280
|
0
|
0
|
|
|
|
|
if ($key eq "id") |
281
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDevice::actions{"getById"}.$value; |
282
|
0
|
|
|
|
|
|
$mode = "NetworkDevice"; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
} |
285
|
0
|
0
|
|
|
|
|
if ($type eq "NetworkDeviceGroup") |
286
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDeviceGroup::actions{"query"}; |
287
|
0
|
|
|
|
|
|
$mode = "NetworkDeviceGroups"; |
288
|
0
|
|
|
|
|
|
$accepttype = "network.networkdevicegroup.1.1"; |
289
|
0
|
0
|
|
|
|
|
if ($key eq "id") |
290
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDeviceGroup::actions{"getById"}.$value; |
291
|
0
|
|
|
|
|
|
$mode = "NetworkDeviceGroup"; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
} |
294
|
0
|
0
|
|
|
|
|
if ($type eq "Endpoint") |
295
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Endpoint::actions{"query"}; |
296
|
0
|
|
|
|
|
|
$mode = "Endpoints"; |
297
|
0
|
|
|
|
|
|
$accepttype = "identity.endpoint.1.0"; |
298
|
0
|
0
|
|
|
|
|
if ($key eq "id") |
299
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Endpoint::actions{"getById"}.$value; |
300
|
0
|
|
|
|
|
|
$mode = "Endpoint"; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
} |
303
|
0
|
0
|
|
|
|
|
if ($type eq "EndpointCertificate") |
304
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointCertificate::actions{"query"}; |
305
|
0
|
|
|
|
|
|
$mode = "EndpointCertificates"; |
306
|
0
|
|
|
|
|
|
$accepttype = "ca.endpointcert.1.0"; |
307
|
0
|
0
|
|
|
|
|
if ($key eq "id") |
308
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointCertificate::actions{"getById"}.$value; |
309
|
0
|
|
|
|
|
|
$mode = "EndpointCertificate"; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
0
|
0
|
|
|
|
|
if ($type eq "Portal") |
314
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Portal::actions{"query"}; |
315
|
0
|
|
|
|
|
|
$mode = "Portals"; |
316
|
0
|
|
|
|
|
|
$accepttype = "identity.portal.1.0"; |
317
|
0
|
0
|
|
|
|
|
if ($key eq "id") |
318
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Portal::actions{"getById"}.$value; |
319
|
0
|
|
|
|
|
|
$mode = "Portal"; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
} |
322
|
0
|
0
|
|
|
|
|
if ($type eq "Profile") |
323
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Profile::actions{"query"}; |
324
|
0
|
|
|
|
|
|
$mode = "Profiles"; |
325
|
0
|
|
|
|
|
|
$accepttype = "identity.profilerprofile.1.0"; |
326
|
0
|
0
|
|
|
|
|
if ($key eq "id") |
327
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Profile::actions{"getById"}.$value; |
328
|
0
|
|
|
|
|
|
$mode = "Profile"; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
0
|
|
|
|
|
|
$hostname = $hostname . $action; |
333
|
0
|
|
|
|
|
|
my $useragent = LWP::UserAgent->new (ssl_opts => $self->ssl_options); |
334
|
0
|
|
|
|
|
|
my $request = HTTP::Request->new(GET => $hostname ); |
335
|
0
|
|
|
|
|
|
$request->header('Authorization' => "Basic $credentials", Accept => "application/vnd.com.cisco.ise.$accepttype+xml"); |
336
|
0
|
|
|
|
|
|
my $result = $useragent->request($request); |
337
|
0
|
0
|
|
|
|
|
if ($result->code eq "400") { $ERROR = "Bad Request - HTTP Status: 400"; } |
|
0
|
|
|
|
|
|
|
338
|
0
|
0
|
|
|
|
|
if ($result->code eq "410") { $ERROR = "Unknown $type queried by name or ID - HTTP Status: 410"; } |
|
0
|
|
|
|
|
|
|
339
|
0
|
0
|
|
|
|
|
warn Dumper $result->content if $self->debug; |
340
|
0
|
|
|
|
|
|
$result = $self->parse_xml($mode, $result->content); |
341
|
0
|
0
|
|
|
|
|
warn Dumper $result if $self->debug; |
342
|
0
|
|
|
|
|
|
return $result; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
sub create |
346
|
0
|
|
|
0
|
1
|
|
{ my $self = shift; |
347
|
0
|
|
|
|
|
|
my $record = shift; |
348
|
0
|
0
|
|
|
|
|
return unless $record; |
349
|
0
|
|
|
|
|
|
my $hostname = $self->hostname; |
350
|
0
|
|
|
|
|
|
my $credentials = encode_base64($self->username.":".$self->password); |
351
|
0
|
0
|
|
|
|
|
if ($self->ssl) |
352
|
0
|
|
|
|
|
|
{ $hostname = "https://$hostname"; } else |
353
|
0
|
|
|
|
|
|
{ $hostname = "http://$hostname"; } |
354
|
0
|
0
|
|
|
|
|
$hostname .= ":".$self->port if $self->port; |
355
|
0
|
|
|
|
|
|
my $action = ""; |
356
|
0
|
|
|
|
|
|
my $data = ""; |
357
|
0
|
|
|
|
|
|
my $accepttype = ""; |
358
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::InternalUser") |
359
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::InternalUser::actions{"create"}; |
360
|
0
|
|
|
|
|
|
$accepttype = "identity.internaluser.1.0"; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::IdentityGroup") |
364
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::IdentityGroup::actions{"create"}; |
365
|
|
|
|
|
|
|
#$accepttype = "identity.identitygroup.1.0"; |
366
|
|
|
|
|
|
|
# ISE does not support creating Identity Groups through the API. No idea why this is! |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::NetworkDevice") |
370
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDevice::actions{"create"}; |
371
|
0
|
|
|
|
|
|
$accepttype = "network.networkdevice.1.1"; |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::NetworkDeviceGroup") |
375
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDeviceGroup::actions{"create"}; |
376
|
0
|
|
|
|
|
|
$accepttype = "network.networkdevicegroup.1.1"; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::Endpoint") |
380
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Endpoint::actions{"create"}; |
381
|
0
|
|
|
|
|
|
$accepttype = "identity.endpoint.1.0"; |
382
|
|
|
|
|
|
|
} |
383
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::EndpointCertificate") |
384
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointCertificate::actions{"create"}; |
385
|
0
|
|
|
|
|
|
$accepttype = "ca.endpointcert.1.0"; |
386
|
|
|
|
|
|
|
} |
387
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::EndpointIdentityGroup") |
388
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointIdentityGroup::actions{"create"}; |
389
|
0
|
|
|
|
|
|
$accepttype = "identity.endpointgroup.1.0"; |
390
|
|
|
|
|
|
|
} |
391
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::Portal") |
392
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Portal::actions{"create"}; |
393
|
0
|
|
|
|
|
|
$accepttype = "identity.portal.1.0"; |
394
|
|
|
|
|
|
|
} |
395
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::Profile") |
396
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Profile::actions{"create"}; |
397
|
0
|
|
|
|
|
|
$accepttype = "identity.profilerprofile.1.0"; |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
0
|
|
|
|
|
|
$data .= $record->toXML; |
401
|
0
|
|
|
|
|
|
$data = $record->header($data,$record); |
402
|
0
|
|
|
|
|
|
$hostname = $hostname . $action; |
403
|
0
|
|
|
|
|
|
my $useragent = LWP::UserAgent->new (ssl_opts => $self->ssl_options); |
404
|
0
|
|
|
|
|
|
my $request = HTTP::Request->new(POST => $hostname ); |
405
|
0
|
|
|
|
|
|
$request->content_type("application/xml"); |
406
|
0
|
|
|
|
|
|
$request->header("Authorization" => "Basic $credentials", "Content-Type" => "application/vnd.com.cisco.ise.$accepttype+xml; charset=utf-8", Accept => "application/vnd.com.cisco.ise.$accepttype+xml"); |
407
|
0
|
|
|
|
|
|
$request->content($data); |
408
|
0
|
|
|
|
|
|
my $result = $useragent->request($request); |
409
|
0
|
|
|
|
|
|
my $id = ""; |
410
|
0
|
0
|
|
|
|
|
if ($result->code ne "201") |
411
|
0
|
|
|
|
|
|
{ my $result_ref = $self->parse_xml("messages", $result->content); |
412
|
0
|
|
|
|
|
|
$ERROR = $result_ref->{"messages"}{"message"}{"type"}.":".$result_ref->{"messages"}{"message"}{"code"}." - ".$result_ref->{"messages"}{"message"}{"title"}." "." - HTTP Status: ".$result->code; |
413
|
|
|
|
|
|
|
} else |
414
|
0
|
|
|
|
|
|
{ my $location = $result->header("location"); |
415
|
0
|
|
|
|
|
|
($id) = $location =~ /^.*\/([^\/]*)$/; |
416
|
|
|
|
|
|
|
} |
417
|
0
|
|
|
|
|
|
return $id; |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
sub update |
421
|
0
|
|
|
0
|
1
|
|
{ my $self = shift; |
422
|
0
|
|
|
|
|
|
my $record = shift; |
423
|
0
|
0
|
|
|
|
|
return unless $record; |
424
|
0
|
|
|
|
|
|
my $hostname = $self->hostname; |
425
|
0
|
|
|
|
|
|
my $credentials = encode_base64($self->username.":".$self->password); |
426
|
0
|
0
|
|
|
|
|
if ($self->ssl) |
427
|
0
|
|
|
|
|
|
{ $hostname = "https://$hostname"; } else |
428
|
0
|
|
|
|
|
|
{ $hostname = "http://$hostname"; } |
429
|
0
|
0
|
|
|
|
|
$hostname .= ":".$self->port if $self->port; |
430
|
0
|
|
|
|
|
|
my $action = ""; |
431
|
0
|
|
|
|
|
|
my $data = ""; |
432
|
0
|
|
|
|
|
|
my $accepttype = ""; |
433
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::InternalUser") |
434
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::InternalUser::actions{"update"}; |
435
|
0
|
|
|
|
|
|
$accepttype = "identity.internaluser.1.0"; |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
|
438
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::IdentityGroup") |
439
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::IdentityGroup::actions{"update"}; |
440
|
0
|
|
|
|
|
|
$accepttype = "identity.identitygroup.1.0"; |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::NetworkDevice") |
444
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDevice::actions{"update"}; |
445
|
0
|
|
|
|
|
|
$accepttype = "network.networkdevice.1.1"; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::NetworkDeviceGroup") |
449
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDeviceGroup::actions{"update"}; |
450
|
0
|
|
|
|
|
|
$accepttype = "network.networkdevicegroup.1.1"; |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
|
453
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::Endpoint") |
454
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Endpoint::actions{"update"}; |
455
|
0
|
|
|
|
|
|
$accepttype = "identity.endpoint.1.0"; |
456
|
|
|
|
|
|
|
} |
457
|
|
|
|
|
|
|
|
458
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::EndpointCertificate") |
459
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointCertificate::actions{"update"}; |
460
|
0
|
|
|
|
|
|
$accepttype = "ca.endpointcert.1.0"; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
|
463
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::EndpointIdentityGroup") |
464
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointIdentityGroup::actions{"update"}; |
465
|
0
|
|
|
|
|
|
$accepttype = "identity.endpointgroup.1.0"; |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::Portal") |
469
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Portal::actions{"update"}; |
470
|
0
|
|
|
|
|
|
$accepttype = "identity.portal.1.0"; |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
|
473
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::Profile") |
474
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Profile::actions{"update"}; |
475
|
0
|
|
|
|
|
|
$accepttype = "identity.profilerprofile.1.0"; |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
|
478
|
0
|
|
|
|
|
|
$data .= $record->toXML; |
479
|
|
|
|
|
|
|
|
480
|
0
|
|
|
|
|
|
$data = $record->header($data, $record); |
481
|
0
|
|
|
|
|
|
$hostname = $hostname . $action.$record->id; |
482
|
0
|
|
|
|
|
|
my $useragent = LWP::UserAgent->new (ssl_opts => $self->ssl_options); |
483
|
0
|
|
|
|
|
|
my $request = HTTP::Request->new(PUT => $hostname ); |
484
|
0
|
|
|
|
|
|
$request->content_type("application/xml"); |
485
|
0
|
|
|
|
|
|
$request->header("Authorization" => "Basic $credentials", "Content-Type" => "application/vnd.com.cisco.ise.$accepttype+xml"); |
486
|
0
|
|
|
|
|
|
$request->content($data); |
487
|
0
|
0
|
|
|
|
|
warn Dumper $request if $self->debug; |
488
|
0
|
|
|
|
|
|
my $result = $useragent->request($request); |
489
|
0
|
|
|
|
|
|
my $id = ""; |
490
|
0
|
0
|
|
|
|
|
if ($result->code ne "200") |
491
|
0
|
|
|
|
|
|
{ my $result_ref = $self->parse_xml("messages", $result->content); |
492
|
0
|
|
|
|
|
|
$ERROR = $result_ref->{"messages"}{"message"}{"type"}.":".$result_ref->{"messages"}{"message"}{"code"}." - ".$result_ref->{"messages"}{"message"}{"title"}." "." - HTTP Status: ".$result->code; |
493
|
|
|
|
|
|
|
} else |
494
|
0
|
|
|
|
|
|
{ my $location = $result->header("location"); |
495
|
0
|
|
|
|
|
|
($id) = $location =~ /^.*\/([^\/]*)$/; |
496
|
|
|
|
|
|
|
} |
497
|
0
|
|
|
|
|
|
return $id; |
498
|
|
|
|
|
|
|
} |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
sub delete |
501
|
0
|
|
|
0
|
1
|
|
{ my $self = shift; |
502
|
0
|
|
|
|
|
|
my $record = shift; |
503
|
0
|
|
|
|
|
|
my $hostname = $self->hostname; |
504
|
0
|
|
|
|
|
|
my $credentials = encode_base64($self->username.":".$self->password); |
505
|
0
|
0
|
|
|
|
|
if ($self->ssl) |
506
|
0
|
|
|
|
|
|
{ $hostname = "https://$hostname"; } else |
507
|
0
|
|
|
|
|
|
{ $hostname = "http://$hostname"; } |
508
|
0
|
0
|
|
|
|
|
$hostname .= ":".$self->port if $self->port; |
509
|
0
|
|
|
|
|
|
my $action = ""; |
510
|
0
|
|
|
|
|
|
my $type = ""; |
511
|
0
|
|
|
|
|
|
my $accepttype = ""; |
512
|
|
|
|
|
|
|
|
513
|
0
|
0
|
|
|
|
|
if (ref($record) eq "ARRAY") { $record = $record->[0]; } |
|
0
|
|
|
|
|
|
|
514
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::InternalUser") |
515
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::InternalUser::actions{"getById"}; |
516
|
0
|
|
|
|
|
|
$type = "InternalUser"; |
517
|
0
|
|
|
|
|
|
$accepttype = "identity.internaluser.1.0"; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::IdentityGroup") |
521
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::IdentityGroup::actions{"getById"}; |
522
|
0
|
|
|
|
|
|
$type = "IdentityGroup"; |
523
|
0
|
|
|
|
|
|
$accepttype = "identity.identitygroup.1.0"; |
524
|
|
|
|
|
|
|
} |
525
|
|
|
|
|
|
|
|
526
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::NetworkDevice") |
527
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDevice::actions{"getById"}; |
528
|
0
|
|
|
|
|
|
$type = "NetworkDevice"; |
529
|
0
|
|
|
|
|
|
$accepttype = "network.networkdevice.1.1"; |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
|
532
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::NetworkDeviceGroup") |
533
|
0
|
|
|
|
|
|
{ $action = $Net::Cisco::ISE::NetworkDeviceGroup::actions{"getById"}; |
534
|
0
|
|
|
|
|
|
$type = "NetworkDeviceGroup"; |
535
|
0
|
|
|
|
|
|
$accepttype = "network.networkdevicegroup.1.1"; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
|
538
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::Endpoint") |
539
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Endpoint::actions{"getById"}; |
540
|
0
|
|
|
|
|
|
$type = "Endpoint"; |
541
|
0
|
|
|
|
|
|
$accepttype = "identity.endpoint.1.0"; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
# Not sure Endpoint Certificates can be deleted |
545
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::EndpointCertificate") |
546
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointCertificate::actions{"getById"}; |
547
|
0
|
|
|
|
|
|
$type = "EndpointCertificate"; |
548
|
0
|
|
|
|
|
|
$accepttype = "ca.endpointcert.1.0"; |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
|
551
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::EndpointIdentityGroup") |
552
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::EndpointIdentityGroup::actions{"getById"}; |
553
|
0
|
|
|
|
|
|
$type = "EndpointIdentityGroup"; |
554
|
0
|
|
|
|
|
|
$accepttype = "identity.endpointgroup.1.0"; |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
|
557
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::Portal") |
558
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Portal::actions{"getById"}; |
559
|
0
|
|
|
|
|
|
$type = "Portal"; |
560
|
0
|
|
|
|
|
|
$accepttype = "identity.portal.1.0"; |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
|
563
|
0
|
0
|
|
|
|
|
if (ref($record) eq "Net::Cisco::ISE::Profile") |
564
|
|
|
|
|
|
|
{ #$action = $Net::Cisco::ISE::Profile::actions{"getById"}; |
565
|
0
|
|
|
|
|
|
$type = "Profile"; |
566
|
0
|
|
|
|
|
|
$accepttype = "identity.profilerprofile.1.0"; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
|
570
|
0
|
|
|
|
|
|
$hostname = $hostname . $action.$record->id; |
571
|
0
|
|
|
|
|
|
my $useragent = LWP::UserAgent->new (ssl_opts => $self->ssl_options); |
572
|
0
|
|
|
|
|
|
my $request = HTTP::Request->new(DELETE => $hostname ); |
573
|
0
|
|
|
|
|
|
$request->content_type("application/xml"); |
574
|
0
|
|
|
|
|
|
$request->header("Authorization" => "Basic $credentials", Accept => "application/vnd.com.cisco.ise.$accepttype+xml"); |
575
|
0
|
|
|
|
|
|
my $result = $useragent->request($request); |
576
|
0
|
|
|
|
|
|
my $id = ""; |
577
|
0
|
0
|
|
|
|
|
if ($result->code ne "204") |
578
|
0
|
|
|
|
|
|
{ $ERROR = $result->{"code"}; |
579
|
|
|
|
|
|
|
} |
580
|
|
|
|
|
|
|
} |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
sub parse_xml |
583
|
0
|
|
|
0
|
0
|
|
{ my $self = shift; |
584
|
0
|
|
|
|
|
|
my $type = shift; |
585
|
0
|
|
|
|
|
|
my $xml_ref = shift; |
586
|
0
|
|
|
|
|
|
my $xmlsimple = XML::Simple->new(SuppressEmpty => 1); |
587
|
0
|
|
|
|
|
|
my $xmlout = $xmlsimple->XMLin($xml_ref); |
588
|
0
|
0
|
|
|
|
|
if ($type eq "InternalUsers") |
589
|
|
|
|
|
|
|
{ #my $users_ref = $xmlout->{"InternalUser"}; |
590
|
0
|
|
|
|
|
|
my $users_ref = $xmlout->{"resources"}{"resource"}; |
591
|
0
|
|
|
|
|
|
my %users = (); |
592
|
0
|
|
|
|
|
|
for my $key (keys % {$users_ref}) |
|
0
|
|
|
|
|
|
|
593
|
0
|
|
|
|
|
|
{ my $user = Net::Cisco::ISE::InternalUser->new( name => $key, %{ $users_ref->{$key} } ); |
|
0
|
|
|
|
|
|
|
594
|
0
|
|
|
|
|
|
$users{$key} = $user; |
595
|
|
|
|
|
|
|
} |
596
|
0
|
|
|
|
|
|
$self->{"InternalUsers"} = \%users; |
597
|
0
|
|
|
|
|
|
return $self->{"InternalUsers"}; |
598
|
|
|
|
|
|
|
} |
599
|
0
|
0
|
|
|
|
|
if ($type eq "InternalUser") # userByName and userById DO NOT return hash but a single instance of Net::Cisco::ISE::InternalUser |
600
|
0
|
|
|
|
|
|
{ my %user_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
601
|
0
|
|
|
|
|
|
my $user = Net::Cisco::ISE::InternalUser->new( %user_hash ); |
602
|
0
|
|
|
|
|
|
$self->{"InternalUsers"} = $user ; |
603
|
0
|
|
|
|
|
|
return $self->{"InternalUsers"}; |
604
|
|
|
|
|
|
|
} |
605
|
|
|
|
|
|
|
|
606
|
0
|
0
|
|
|
|
|
if ($type eq "IdentityGroups") |
607
|
0
|
|
|
|
|
|
{ my $identitygroups_ref = $xmlout->{"resources"}{"resource"}; |
608
|
0
|
|
|
|
|
|
my %identitygroups = (); |
609
|
|
|
|
|
|
|
# With Single entry, this approach will break!!! |
610
|
|
|
|
|
|
|
# !!BUG!! |
611
|
0
|
|
|
|
|
|
for my $key (keys % {$identitygroups_ref}) |
|
0
|
|
|
|
|
|
|
612
|
0
|
|
|
|
|
|
{ my $identitygroup = Net::Cisco::ISE::IdentityGroup->new( name => $key, %{ $identitygroups_ref->{$key} } ); |
|
0
|
|
|
|
|
|
|
613
|
0
|
|
|
|
|
|
$identitygroups{$key} = $identitygroup; |
614
|
|
|
|
|
|
|
} |
615
|
0
|
|
|
|
|
|
$self->{"IdentityGroups"} = \%identitygroups; |
616
|
0
|
|
|
|
|
|
return $self->{"IdentityGroups"}; |
617
|
|
|
|
|
|
|
} |
618
|
0
|
0
|
|
|
|
|
if ($type eq "IdentityGroup") # ByName and ById DO NOT return hash but a single instance of Net::Cisco::ISE::IdentityGroup |
619
|
0
|
|
|
|
|
|
{ my %identitygroup_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
620
|
0
|
|
|
|
|
|
my $identitygroup = Net::Cisco::ISE::IdentityGroup->new( %identitygroup_hash ); |
621
|
0
|
|
|
|
|
|
$self->{"IdentityGroups"} = $identitygroup; |
622
|
0
|
|
|
|
|
|
return $self->{"IdentityGroups"}; |
623
|
|
|
|
|
|
|
} |
624
|
|
|
|
|
|
|
|
625
|
0
|
0
|
|
|
|
|
if ($type eq "NetworkDevices") |
626
|
0
|
|
|
|
|
|
{ my $device_ref = $xmlout->{"resources"}{"resource"}; |
627
|
0
|
|
|
|
|
|
my %devices = (); |
628
|
0
|
|
|
|
|
|
for my $key (keys % {$device_ref}) |
|
0
|
|
|
|
|
|
|
629
|
0
|
|
|
|
|
|
{ my $device = Net::Cisco::ISE::NetworkDevice->new( name => $key, id => $device_ref->{$key}{"id"} ); |
630
|
0
|
|
|
|
|
|
$devices{$key} = $device; |
631
|
|
|
|
|
|
|
} |
632
|
0
|
|
|
|
|
|
$self->{"NetworkDevices"} = \%devices; |
633
|
0
|
|
|
|
|
|
return $self->{"NetworkDevices"}; |
634
|
|
|
|
|
|
|
} |
635
|
0
|
0
|
|
|
|
|
if ($type eq "NetworkDevice") # deviceByName and deviceById DO NOT return hash but a single instance of Net::Cisco::ISE::NetworkDevice |
636
|
0
|
|
|
|
|
|
{ my %device_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
637
|
0
|
|
|
|
|
|
my $device = Net::Cisco::ISE::NetworkDevice->new( %device_hash ); |
638
|
0
|
|
|
|
|
|
$self->{"NetworkDevices"} = $device; |
639
|
0
|
|
|
|
|
|
return $self->{"NetworkDevices"}; |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
|
642
|
0
|
0
|
|
|
|
|
if ($type eq "NetworkDeviceGroups") |
643
|
0
|
|
|
|
|
|
{ my $devicegroup_ref = $xmlout->{"resources"}{"resource"}; |
644
|
0
|
|
|
|
|
|
my %devicegroups = (); |
645
|
0
|
|
|
|
|
|
for my $key (keys % {$devicegroup_ref}) |
|
0
|
|
|
|
|
|
|
646
|
0
|
|
|
|
|
|
{ my $devicegroup = Net::Cisco::ISE::NetworkDeviceGroup->new( name => $key, %{ $devicegroup_ref->{$key} } ); |
|
0
|
|
|
|
|
|
|
647
|
0
|
|
|
|
|
|
$devicegroups{$key} = $devicegroup; |
648
|
|
|
|
|
|
|
} |
649
|
0
|
|
|
|
|
|
$self->{"NetworkDeviceGroups"} = \%devicegroups; |
650
|
0
|
|
|
|
|
|
return $self->{"NetworkDeviceGroups"}; |
651
|
|
|
|
|
|
|
} |
652
|
0
|
0
|
|
|
|
|
if ($type eq "NetworkDeviceGroup") # deviceGroupByName and deviceGroupById DO NOT return hash but a single instance of Net::Cisco::ISE::NetworkDeviceGroup |
653
|
0
|
|
|
|
|
|
{ my %devicegroup_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
654
|
0
|
|
|
|
|
|
my $devicegroup = Net::Cisco::ISE::NetworkDeviceGroup->new( %devicegroup_hash ); |
655
|
0
|
|
|
|
|
|
$self->{"NetworkDeviceGroups"} = $devicegroup; |
656
|
0
|
|
|
|
|
|
return $self->{"NetworkDeviceGroups"}; |
657
|
|
|
|
|
|
|
} |
658
|
|
|
|
|
|
|
|
659
|
0
|
0
|
|
|
|
|
if ($type eq "Endpoints") |
660
|
0
|
|
|
|
|
|
{ my $host_ref = $xmlout->{"resources"}{"resource"}; |
661
|
0
|
|
|
|
|
|
my %hosts = (); |
662
|
0
|
|
|
|
|
|
for my $key (keys % {$host_ref}) |
|
0
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
{ #my $host = Net::Cisco::ISE::Endpoint->new( macAddress => $key, %{ $host_ref->{$key} } ); |
664
|
|
|
|
|
|
|
#$hosts{$key} = $host; |
665
|
|
|
|
|
|
|
} |
666
|
0
|
|
|
|
|
|
$self->{"Endpoints"} = \%hosts; |
667
|
0
|
|
|
|
|
|
return $self->{"Endpoints"}; |
668
|
|
|
|
|
|
|
} |
669
|
0
|
0
|
|
|
|
|
if ($type eq "Endpoint") # ByName and ById DO NOT return hash but a single instance of Net::Cisco::ISE::Endpoint |
670
|
0
|
|
|
|
|
|
{ my %host_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
#my $host = Net::Cisco::ISE::Endpoint->new( %host_hash ); |
672
|
|
|
|
|
|
|
#$self->{"Endpoints"} = $host; |
673
|
0
|
|
|
|
|
|
return $self->{"Endpoints"}; |
674
|
|
|
|
|
|
|
} |
675
|
|
|
|
|
|
|
|
676
|
0
|
0
|
|
|
|
|
if ($type eq "EndpointCertificates") |
677
|
0
|
|
|
|
|
|
{ my $host_ref = $xmlout->{"resources"}{"resource"}; |
678
|
0
|
|
|
|
|
|
my %hosts = (); |
679
|
0
|
|
|
|
|
|
for my $key (keys % {$host_ref}) |
|
0
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
{ #my $host = Net::Cisco::ISE::EndpointCertificate->new( name => $key, %{ $host_ref->{$key} } ); |
681
|
|
|
|
|
|
|
#$hosts{$key} = $host; |
682
|
|
|
|
|
|
|
} |
683
|
0
|
|
|
|
|
|
$self->{"EndpointCertificates"} = \%hosts; |
684
|
0
|
|
|
|
|
|
return $self->{"EndpointCertificates"}; |
685
|
|
|
|
|
|
|
} |
686
|
0
|
0
|
|
|
|
|
if ($type eq "EndpointCertificate") # ByName and ById DO NOT return hash but a single instance of Net::Cisco::ISE::Endpoint |
687
|
0
|
|
|
|
|
|
{ my %host_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
#my $host = Net::Cisco::ISE::EndpointCertificate->new( %host_hash ); |
689
|
|
|
|
|
|
|
#$self->{"EndpointCertificates"} = $host; |
690
|
0
|
|
|
|
|
|
return $self->{"EndpointCertificates"}; |
691
|
|
|
|
|
|
|
} |
692
|
|
|
|
|
|
|
|
693
|
0
|
0
|
|
|
|
|
if ($type eq "EndpointIdentityGroups") |
694
|
0
|
|
|
|
|
|
{ my $host_ref = $xmlout->{"resources"}{"resource"}; |
695
|
0
|
|
|
|
|
|
my %hosts = (); |
696
|
0
|
|
|
|
|
|
for my $key (keys % {$host_ref}) |
|
0
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
{ #my $host = Net::Cisco::ISE::EndpointIdentityGroup->new( name => $key, %{ $host_ref->{$key} } ); |
698
|
|
|
|
|
|
|
#$hosts{$key} = $host; |
699
|
|
|
|
|
|
|
} |
700
|
0
|
|
|
|
|
|
$self->{"EndpointIdentityGroups"} = \%hosts; |
701
|
0
|
|
|
|
|
|
return $self->{"EndpointIdentityGroups"}; |
702
|
|
|
|
|
|
|
} |
703
|
0
|
0
|
|
|
|
|
if ($type eq "EndpointIdentityGroup") # ByName and ById DO NOT return hash but a single instance of Net::Cisco::ISE::Endpoint |
704
|
0
|
|
|
|
|
|
{ my %host_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
#my $host = Net::Cisco::ISE::EndpointIdentityGroup->new( %host_hash ); |
706
|
|
|
|
|
|
|
#$self->{"EndpointIdentityGroups"} = $host; |
707
|
0
|
|
|
|
|
|
return $self->{"EndpointIdentityGroups"}; |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
|
710
|
0
|
0
|
|
|
|
|
if ($type eq "Portals") |
711
|
0
|
|
|
|
|
|
{ my $host_ref = $xmlout->{"resources"}{"resource"}; |
712
|
0
|
|
|
|
|
|
my %hosts = (); |
713
|
0
|
|
|
|
|
|
for my $key (keys % {$host_ref}) |
|
0
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
{ #my $host = Net::Cisco::ISE::Portal->new( name => $key, %{ $host_ref->{$key} } ); |
715
|
|
|
|
|
|
|
#$hosts{$key} = $host; |
716
|
|
|
|
|
|
|
} |
717
|
0
|
|
|
|
|
|
$self->{"Portals"} = \%hosts; |
718
|
0
|
|
|
|
|
|
return $self->{"Portals"}; |
719
|
|
|
|
|
|
|
} |
720
|
0
|
0
|
|
|
|
|
if ($type eq "Portal") # ByName and ById DO NOT return hash but a single instance of Net::Cisco::ISE::Endpoint |
721
|
0
|
|
|
|
|
|
{ my %host_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
#my $host = Net::Cisco::ISE::Portal->new( %host_hash ); |
723
|
|
|
|
|
|
|
#$self->{"Portals"} = $host; |
724
|
0
|
|
|
|
|
|
return $self->{"Portals"}; |
725
|
|
|
|
|
|
|
} |
726
|
|
|
|
|
|
|
|
727
|
0
|
0
|
|
|
|
|
if ($type eq "Profiles") |
728
|
0
|
|
|
|
|
|
{ my $host_ref = $xmlout->{"resources"}{"resource"}; |
729
|
0
|
|
|
|
|
|
my %hosts = (); |
730
|
0
|
|
|
|
|
|
for my $key (keys % {$host_ref}) |
|
0
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
{ #my $host = Net::Cisco::ISE::Profile->new( name => $key, %{ $host_ref->{$key} } ); |
732
|
|
|
|
|
|
|
#$hosts{$key} = $host; |
733
|
|
|
|
|
|
|
} |
734
|
0
|
|
|
|
|
|
$self->{"Profiles"} = \%hosts; |
735
|
0
|
|
|
|
|
|
return $self->{"Profiles"}; |
736
|
|
|
|
|
|
|
} |
737
|
0
|
0
|
|
|
|
|
if ($type eq "Profile") # ByName and ById DO NOT return hash but a single instance of Net::Cisco::ISE::Endpoint |
738
|
0
|
|
|
|
|
|
{ my %host_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
#my $host = Net::Cisco::ISE::Profile->new( %host_hash ); |
740
|
|
|
|
|
|
|
#$self->{"Profiles"} = $host; |
741
|
0
|
|
|
|
|
|
return $self->{"Profiles"}; |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
|
744
|
0
|
0
|
|
|
|
|
if ($type eq "result") |
745
|
0
|
|
|
|
|
|
{ my %result_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
746
|
0
|
|
|
|
|
|
return \%result_hash; |
747
|
|
|
|
|
|
|
} |
748
|
0
|
0
|
|
|
|
|
if ($type eq "messages") |
749
|
0
|
|
|
|
|
|
{ my %result_hash = %{ $xmlout }; |
|
0
|
|
|
|
|
|
|
750
|
0
|
|
|
|
|
|
return \%result_hash; |
751
|
|
|
|
|
|
|
} |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
=head1 NAME |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
Net::Cisco::ISE - Access Cisco ISE functionality through REST API |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
=head1 SYNOPSIS |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
use Net::Cisco::ISE; |
761
|
|
|
|
|
|
|
my $ise = Net::Cisco::ISE->new(hostname => '10.0.0.1', username => 'admin', password => 'testPassword'); |
762
|
|
|
|
|
|
|
# Options: |
763
|
|
|
|
|
|
|
# hostname - IP or hostname of Cisco ISE 5.x server |
764
|
|
|
|
|
|
|
# username - Username of Administrator user |
765
|
|
|
|
|
|
|
# password - Password of user |
766
|
|
|
|
|
|
|
# port - TCP port 9060 by default |
767
|
|
|
|
|
|
|
# ssl - SSL enabled (1 - default) or disabled (0) |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
my %users = $ise->internalusers; |
770
|
|
|
|
|
|
|
# Retrieve all users from ISE |
771
|
|
|
|
|
|
|
# Returns hash with username / Net::Cisco::ISE::InternalUser pairs |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
print $ise->internalusers->{"admin"}->toXML; |
774
|
|
|
|
|
|
|
# Dump in XML format (used by ISE for API calls) |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
my $user = $ise->internalusers("name","admin"); |
777
|
|
|
|
|
|
|
# Faster call to request specific user information by name |
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
my $user = $ise->internalusers("id","b74a0ef2-b29c-40e3-a0d1-4c0dfb51ace9"); |
780
|
|
|
|
|
|
|
# Faster call to request specific user information by ID (assigned by ISE, present in Net::Cisco::ISE::InternalUser) |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
my %identitygroups = $ise->identitygroups; |
783
|
|
|
|
|
|
|
# Retrieve all identitygroups from ISE |
784
|
|
|
|
|
|
|
# Returns hash with name / Net::Cisco::ISE::IdentityGroup pairs |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
print $ise->identitygroups->{"All Groups"}->toXML; |
787
|
|
|
|
|
|
|
# Dump in XML format (used by ISE for API calls) |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
my $identitygroup = $ise->identitygroups("name","All Groups"); |
790
|
|
|
|
|
|
|
# Faster call to request specific identity group information by name |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
my $identitygroup = $ise->identitygroups("id","4fffc260-9b96-11e6-93fb-005056ad1454"); |
793
|
|
|
|
|
|
|
# Faster call to request specific identity group information by ID (assigned by ISE, present in Net::Cisco::ISE::IdentityGroup) |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
my $device = $acs->networkdevices("name","MAIN_Router"); |
796
|
|
|
|
|
|
|
# Faster call to request specific device information by name |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
my $device = $acs->networkdevices("id","250"); |
799
|
|
|
|
|
|
|
# Faster call to request specific device information by ID (assigned by ISE, present in Net::Cisco::ISE::NetworkDevice) |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
$user->id(0); # Required for new user! |
802
|
|
|
|
|
|
|
my $id = $ise->create($user); |
803
|
|
|
|
|
|
|
# Create new user based on Net::Cisco::ISE::InternalUser instance |
804
|
|
|
|
|
|
|
# Return value is ID generated by ISE |
805
|
|
|
|
|
|
|
print "Record ID is $id" if $id; |
806
|
|
|
|
|
|
|
print $Net::Cisco::ISE::ERROR unless $id; |
807
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
808
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
my $id = $ise->create(@users); # Still requires nullified ID! |
810
|
|
|
|
|
|
|
# Create new users based on Net::Cisco::ISE::InternalUser instances in arguments |
811
|
|
|
|
|
|
|
# Return value is not guaranteed in this case! |
812
|
|
|
|
|
|
|
# print "Record ID is $id" if $id; |
813
|
|
|
|
|
|
|
# print $Net::Cisco::ISE::ERROR unless $id; |
814
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
$identitygroup->id(0); # Required for new record! |
817
|
|
|
|
|
|
|
my $id = $ise->create($identitygroup); |
818
|
|
|
|
|
|
|
# Create new identity group based on Net::Cisco::ISE::IdentityGroup instance |
819
|
|
|
|
|
|
|
# Return value is ID generated by ISE |
820
|
|
|
|
|
|
|
print "Record ID is $id" if $id; |
821
|
|
|
|
|
|
|
print $Net::Cisco::ISE::ERROR unless $id; |
822
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
# Cisco ISE does not support modifying an identity group through the API |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
my $id = $ise->update($user); |
827
|
|
|
|
|
|
|
# Update existing user based on Net::Cisco::ISE::InternalUser instance |
828
|
|
|
|
|
|
|
# Return value is ID generated by ISE |
829
|
|
|
|
|
|
|
print "Record ID is $id" if $id; |
830
|
|
|
|
|
|
|
print $Net::Cisco::ISE::ERROR unless $id; |
831
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
my $id = $ise->update(@users); |
834
|
|
|
|
|
|
|
# Update existing users based on Net::Cisco::ISE::InternalUser instances in arguments |
835
|
|
|
|
|
|
|
# Return value is not guaranteed in this case! |
836
|
|
|
|
|
|
|
# print "Record ID is $id" if $id; |
837
|
|
|
|
|
|
|
# print $Net::Cisco::ISE::ERROR unless $id; |
838
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
$ise->delete($user); |
841
|
|
|
|
|
|
|
# Delete existing user based on Net::Cisco::ISE::InternalUser instance |
842
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
=head1 DESCRIPTION |
844
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
Net::Cisco::ISE is an implementation of the Cisco Identity Services Engine (ISE) REST API. Cisco ISE is a application / appliance that can be used for network access policy control. In short, it allows configuration of access policies for specific users onto specific devices and applications (either using RADIUS or TACACS+ authentication). Net::Cisco::ISE currently supports InternalUser and IdentityGroup. |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
=head1 USAGE |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
All calls are handled through an instance of the L<Net::Cisco::ISE> class. |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
use Net::Cisco::ISE; |
852
|
|
|
|
|
|
|
my $ise = Net::Cisco::ISE->new(hostname => '10.0.0.1', username => 'admin', password => 'testPassword'); |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
=over 3 |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
=item new |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
Class constructor. Returns object of Net::Cisco::ISE on succes. Required fields are: |
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
=over 5 |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
=item hostname |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
=item username |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
=item password |
867
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
=back |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
Optional fields are |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
=over 5 |
873
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
=item ssl |
875
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
=item ssl_options |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
=back |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
=item hostname |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
IP or hostname of Cisco ISE 2.x server. This is a required value in the constructor but can be redefined afterwards. |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
=item username |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
Username of Administrator user. This is a required value in the constructor but can be redefined afterwards. |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
=item password |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
Password of user. This is a required value in the constructor but can be redefined afterwards. |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
=item ssl |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
SSL enabled (1 - default) or disabled (0). |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
=item ssl_options |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
Value is passed directly to LWP::UserAGent as ssl_opt. Default value (hash-ref) is |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
{ 'SSL_verify_mode' => SSL_VERIFY_NONE, 'verify_hostname' => '0' } |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
=back |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
From the class instance, call the different methods for retrieving values. |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
=over 3 |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
=item users |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
Returns hash or single instance, depending on context. |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
my %users = $ise->internalusers(); # Slow |
913
|
|
|
|
|
|
|
my $user = $ise->internalusers()->{"admin"}; |
914
|
|
|
|
|
|
|
print $user->name; |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
The returned hash contains instances of L<Net::Cisco::ISE::InternalUser>, using name (typically the username) as the hash key. Using a call to C<users> with no arguments will retrieve all users and can take quite a few seconds (depending on the size of your database). When you know the username or ID, use the L<users> call with arguments as listed below. |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
my $user = $ise->internalusers("name","admin"); # Faster |
919
|
|
|
|
|
|
|
# or |
920
|
|
|
|
|
|
|
my $user = $ise->internalusers("id","b74a0ef2-b29c-40e3-a0d1-4c0dfb51ace9"); # Faster |
921
|
|
|
|
|
|
|
print $user->name; |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
The ID is typically generated by Cisco ISE when the entry is created. It can be retrieved by calling the C<id> method on the object. |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
print $user->id; |
926
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
=item identitygroups |
928
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
Returns hash or single instance, depending on context. |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
my %identitygroups = $ise->identitygroups(); # Slow |
932
|
|
|
|
|
|
|
my $identitygroup = $ise->identitygroups()->{"All Groups"}; |
933
|
|
|
|
|
|
|
print $identitgroup->name; |
934
|
|
|
|
|
|
|
|
935
|
|
|
|
|
|
|
The returned hash contains instances of L<Net::Cisco::ISE::IdentityGroup>, using name (typically the username) as the hash key. Using a call to C<identitygroup> with no arguments will retrieve all identitygroups and can take quite a few seconds (depending on the size of your database). When you know the group name or ID, use the L<identitygroups> call with arguments as listed below. |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
my $identitygroup = $ise->identitygroups("name","All Groups"); # Faster |
938
|
|
|
|
|
|
|
# or |
939
|
|
|
|
|
|
|
my $identitygroup = $ise->identitygroups("id","4fffc260-9b96-11e6-93fb-005056ad1454"); # Faster |
940
|
|
|
|
|
|
|
print $identitygroup->name; |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
The ID is typically generated by Cisco ISE when the entry is created. It can be retrieved by calling the C<id> method on the object. |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
print $identitygroup->id; |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
=item devices |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
Returns hash or single instance, depending on context. |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
my %devices = $acs->networkdevices(); # Slow |
951
|
|
|
|
|
|
|
my $device = $acs->networkdevices()->{"Main_Router"}; |
952
|
|
|
|
|
|
|
print $device->name; |
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
The returned hash contains instances of L<Net::Cisco::ISE::NetworkDevice>, using name (typically the sysname) as the hash key. Using a call to C<device> with no arguments will retrieve all devices and can take quite a few seconds (depending on the size of your database). When you know the hostname or ID, use the L<devices> call with arguments as listed below. |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
my $device = $acs->device("name","Main_Router"); # Faster |
957
|
|
|
|
|
|
|
# or |
958
|
|
|
|
|
|
|
my $device = $acs->device("id","123"); # Faster |
959
|
|
|
|
|
|
|
print $device->name; |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
The ID is typically generated by Cisco ISE when the entry is created. It can be retrieved by calling the C<id> method on the object. |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
print $device->id; |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
=item devicegroups |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
Returns hash or single instance, depending on context. |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
my %devicegroups = $acs->networkdevicegroups(); # Slow |
970
|
|
|
|
|
|
|
my $devicegroup = $acs->networkdevicegroups()->{"All Locations:Main Site"}; |
971
|
|
|
|
|
|
|
print $devicegroup->name; |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
The returned hash contains instances of L<Net::Cisco::ISE::NetworkDeviceGroup>, using name (typically the device group name) as the hash key. Using a call to C<devicegroups> with no arguments will retrieve all device groups and can take quite a few seconds (depending on the size of your database). When you know the device group or ID, use the L<devicegroups> call with arguments as listed below. |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
my $devicegroup = $acs->networkdevicegroups("name","All Locations::Main Site"); # Faster |
976
|
|
|
|
|
|
|
# or |
977
|
|
|
|
|
|
|
my $devicegroup = $acs->networkdevicegroups("id","123"); # Faster |
978
|
|
|
|
|
|
|
print $devicegroup->name; |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
The ID is typically generated by Cisco ISE when the entry is created. It can be retrieved by calling the C<id> method on the object. |
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
print $devicegroup->id; |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
=item create |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
This method created a new entry in Cisco ISE, depending on the argument passed. Record type is detected automatically. For all record types, the ID value must be set to 0. |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
my $user = $ise->internalusers("name","admin"); |
989
|
|
|
|
|
|
|
$user->id(0); # Required for new user! |
990
|
|
|
|
|
|
|
$user->name("altadmin"); # Required field |
991
|
|
|
|
|
|
|
$user->password("TopSecret"); # Password policies will be enforced! |
992
|
|
|
|
|
|
|
$user->description("Alternate Admin"); |
993
|
|
|
|
|
|
|
my $id = $ise->create($user); |
994
|
|
|
|
|
|
|
# Create new user based on Net::Cisco::ISE::InternalUser instance |
995
|
|
|
|
|
|
|
# Return value is ID generated by ISE |
996
|
|
|
|
|
|
|
print "Record ID is $id" if $id; |
997
|
|
|
|
|
|
|
print $Net::Cisco::ISE::ERROR unless $id; |
998
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
my $device = $acs->networkdevices("name","Main_Router"); |
1001
|
|
|
|
|
|
|
$device->name("AltRouter"); # Required field |
1002
|
|
|
|
|
|
|
$device->description("Standby Router"); |
1003
|
|
|
|
|
|
|
$device->ips([{netMask => "32", ipAddress=>"10.0.0.2"}]); # Change IP address! Overlap check is enforced! |
1004
|
|
|
|
|
|
|
$device->id(0); # Required for new device! |
1005
|
|
|
|
|
|
|
my $id = $acs->create($device); |
1006
|
|
|
|
|
|
|
# Create new device based on Net::Cisco::ISE::NetworkDevice instance |
1007
|
|
|
|
|
|
|
# Return value is ID generated by ISE |
1008
|
|
|
|
|
|
|
print "Record ID is $id" if $id; |
1009
|
|
|
|
|
|
|
print $Net::Cisco::ISE::ERROR unless $id; |
1010
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
Multiple instances can be passed as an argument. Objects will be created in bulk (one transaction). The returned ID is not guaranteed to be the IDs of the created objects. |
1013
|
|
|
|
|
|
|
|
1014
|
|
|
|
|
|
|
my $user = $ise->internalusers("name","admin"); |
1015
|
|
|
|
|
|
|
$user->id(0); # Required for new user! |
1016
|
|
|
|
|
|
|
$user->name("altadmin"); # Required field |
1017
|
|
|
|
|
|
|
$user->password("TopSecret"); # Password policies will be enforced! |
1018
|
|
|
|
|
|
|
$user->description("Alternate Admin"); |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
my $user2 = $ise->internalusers("name","admin"); |
1021
|
|
|
|
|
|
|
$user2->id(0); # Required for new user! |
1022
|
|
|
|
|
|
|
$user2->name("altadmin"); # Required field |
1023
|
|
|
|
|
|
|
$user2->password("TopSecret"); # Password policies will be enforced! |
1024
|
|
|
|
|
|
|
$user2->description("Alternate Admin"); |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
my $id = $ise->create($user,$user2); |
1027
|
|
|
|
|
|
|
# Create new users based on Net::Cisco::ISE::InternalUser instances in argument. |
1028
|
|
|
|
|
|
|
# Return value is ID generated by ISE but not guaranteed. |
1029
|
|
|
|
|
|
|
# print "Record ID is $id" if $id; |
1030
|
|
|
|
|
|
|
# print $Net::Cisco::ISE::ERROR unless $id; |
1031
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
1032
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
=item update |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
This method updates an existing entry in Cisco ISE, depending on the argument passed. Record type is detected automatically. |
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
my $user = $ise->internalusers("name","admin"); |
1038
|
|
|
|
|
|
|
$user->password("TopSecret"); # Change password. Password policies will be enforced! |
1039
|
|
|
|
|
|
|
my $id = $ise->update($user); |
1040
|
|
|
|
|
|
|
# Update user based on Net::Cisco::ISE::InternalUser instance |
1041
|
|
|
|
|
|
|
# Return value is ID generated by ISE |
1042
|
|
|
|
|
|
|
print "Record ID is $id" if $id; |
1043
|
|
|
|
|
|
|
print $Net::Cisco::ISE::ERROR unless $id; |
1044
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
my $device = $acs->networkdevices("name","Main_Router"); |
1047
|
|
|
|
|
|
|
$user->description("To be ceased"); # Change description |
1048
|
|
|
|
|
|
|
$device->ips([{netMask => "32", ipAddress=>"10.0.0.2"}]); # or Change IP address. Overlap check is enforced! |
1049
|
|
|
|
|
|
|
my $id = $acs->update($device); |
1050
|
|
|
|
|
|
|
# Create new device based on Net::Cisco::ISE::NetworkDevice instance |
1051
|
|
|
|
|
|
|
# Return value is ID generated by ISE |
1052
|
|
|
|
|
|
|
print "Record ID is $id" if $id; |
1053
|
|
|
|
|
|
|
print $Net::Cisco::ISE::ERROR unless $id; |
1054
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
Multiple instances can be passed as an argument. Objects will be updated in bulk (one transaction). The returned ID is not guaranteed to be the IDs of the created objects. |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
my $user = $ise->internalusers("name","admin"); |
1059
|
|
|
|
|
|
|
$user->id(0); # Required for new user! |
1060
|
|
|
|
|
|
|
$user->password("TopSecret"); # Password policies will be enforced! |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
my $user2 = $ise->internalusers("name","admin2"); |
1063
|
|
|
|
|
|
|
$user2->password("TopSecret"); # Password policies will be enforced! |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
my $id = $ise->update($user,$user2); |
1066
|
|
|
|
|
|
|
# Update users based on Net::Cisco::ISE::InternalUser instances in arguments |
1067
|
|
|
|
|
|
|
# Return value is ID generated by ISE but not guaranteed. |
1068
|
|
|
|
|
|
|
# print "Record ID is $id" if $id; |
1069
|
|
|
|
|
|
|
# print $Net::Cisco::ISE::ERROR unless $id; |
1070
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
my $device = $acs->networkdevices("name","Main_Router"); |
1073
|
|
|
|
|
|
|
$device->description("Main Router"); |
1074
|
|
|
|
|
|
|
$device->ips([{netMask => "32", ipAddress=>"10.0.0.1"}]); # Change IP address! Overlap check is enforced! |
1075
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
my $device2 = $acs->networkdevices("name","Alt_Router"); |
1077
|
|
|
|
|
|
|
$device2->description("Standby Router"); |
1078
|
|
|
|
|
|
|
$device2->ips([{netMask => "32", ipAddress=>"10.0.0.2"}]); # Change IP address! Overlap check is enforced! |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
my $id = $acs->create($device,$device2); |
1081
|
|
|
|
|
|
|
# Update devices based on Net::Cisco::ISE::NetworkDevice instances in arguments |
1082
|
|
|
|
|
|
|
# Return value is ID generated by ISE but not guaranteed. |
1083
|
|
|
|
|
|
|
# print "Record ID is $id" if $id; |
1084
|
|
|
|
|
|
|
# print $Net::Cisco::ISE::ERROR unless $id; |
1085
|
|
|
|
|
|
|
# $Net::Cisco::ISE::ERROR contains details about failure |
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
=item delete |
1088
|
|
|
|
|
|
|
|
1089
|
|
|
|
|
|
|
This method deletes an existing entry in Cisco ISE, depending on the argument passed. Record type is detected automatically. |
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
my $user = $ise->internalusers("name","admin"); |
1092
|
|
|
|
|
|
|
$ise->delete($user); |
1093
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
=item $ERROR |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
This variable will contain detailed error information, based on the REST API answer. This value is reset during every call to C<internalusers> and C<identitygroups>. |
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
=back |
1099
|
|
|
|
|
|
|
|
1100
|
|
|
|
|
|
|
=head1 REQUIREMENTS |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
For this library to work, you need an instance with Cisco ISE (obviously) or a simulator like L<Net::Cisco::ISE::Mock>. |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
Instructions on enabling Cisco ISE for API access will be added later. |
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
You will also need |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
=over 3 |
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
=item L<Moose> |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
=item L<IO::Socket::SSL> |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
=item L<LWP::UserAgent> |
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
=item L<XML::Simple> |
1117
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
=item L<MIME::Base64> |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
=item L<URI::Escape> |
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
=back |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
=head1 BUGS |
1125
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
None so far |
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
=head1 SUPPORT |
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
None so far :) |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
=head1 AUTHOR |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
Hendrik Van Belleghem |
1135
|
|
|
|
|
|
|
CPAN ID: BEATNIK |
1136
|
|
|
|
|
|
|
hendrik.vanbelleghem@gmail.com |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
=head1 COPYRIGHT |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
This program is free software licensed under the... |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
The General Public License (GPL) |
1143
|
|
|
|
|
|
|
Version 2, June 1991 |
1144
|
|
|
|
|
|
|
|
1145
|
|
|
|
|
|
|
The full text of the license can be found in the |
1146
|
|
|
|
|
|
|
LICENSE file included with this module. |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
=head1 COMPATIBILITY |
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
Certain API calls are not support from Cisco ISE 5.0 onwards. The current supported versions of Cisco ISE (by Cisco) are 5.6, 5.7 and 5.8 (Active). |
1151
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
=head1 SEE ALSO |
1153
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
=over 3 |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
See L<Net::Cisco::ISE::InternalUser> for more information on User management. |
1157
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
See L<Net::Cisco::ISE::IdentityGroup> for more information on User Group management. |
1159
|
|
|
|
|
|
|
|
1160
|
|
|
|
|
|
|
See L<Net::Cisco::ISE::NetworkDevice> for more information on Device management. |
1161
|
|
|
|
|
|
|
|
1162
|
|
|
|
|
|
|
See L<Net::Cisco::ISE::NetworkDeviceGroup> for more information on Device Group management. |
1163
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
See the L<Cisco ISE product page|http://www.cisco.com/c/en/us/products/security/identity-services-engine/index.html> for more information. |
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
L<Net::Cisco::ISE> relies on L<Moose>. |
1167
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
=back |
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
=cut |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
#################### main pod documentation end ################### |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable(); |
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
1; |
1177
|
|
|
|
|
|
|
# The preceding line will help the module return a true value |
1178
|
|
|
|
|
|
|
|
1179
|
|
|
|
|
|
|
|