idnio 2.3.2b
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/idnio.rb +295 -0
- data/lib/idnio/crypto.rb +34 -0
- data/lib/idnio/idnapi.rb +158 -0
- data/lib/idnio/markdown.rb +345 -0
- data/lib/idnio/program.rb +153 -0
- data/lib/idnio/timer.rb +57 -0
- data/lib/idnio/version.rb +4 -0
- data/lib/objects/access-profiles.rb +107 -0
- data/lib/objects/access-request-config.rb +90 -0
- data/lib/objects/account-profiles.rb +167 -0
- data/lib/objects/account-schemas.rb +341 -0
- data/lib/objects/applications.rb +145 -0
- data/lib/objects/attribute-sync-config.rb +122 -0
- data/lib/objects/branding.rb +49 -0
- data/lib/objects/campaign-filters.rb +61 -0
- data/lib/objects/connectors.rb +291 -0
- data/lib/objects/email-templates.rb +226 -0
- data/lib/objects/identity-attributes.rb +136 -0
- data/lib/objects/identity-profiles.rb +206 -0
- data/lib/objects/integrations.rb +149 -0
- data/lib/objects/lifecycle-states.rb +86 -0
- data/lib/objects/password-policies.rb +107 -0
- data/lib/objects/password-sync-groups.rb +100 -0
- data/lib/objects/public-identities-config.rb +78 -0
- data/lib/objects/reference-resolver.rb +137 -0
- data/lib/objects/roles.rb +117 -0
- data/lib/objects/rules.rb +198 -0
- data/lib/objects/sources.rb +217 -0
- data/lib/objects/system-settings.rb +185 -0
- data/lib/objects/transforms.rb +157 -0
- metadata +124 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,137 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "json"
|
3
|
+
require "idnio/idnapi"
|
4
|
+
require "idnio/program"
|
5
|
+
|
6
|
+
module ReferenceResolver
|
7
|
+
|
8
|
+
@@default_identity_ref = nil
|
9
|
+
|
10
|
+
@@default_cluster_ref = nil
|
11
|
+
|
12
|
+
def self.get_default_identity_ref
|
13
|
+
if @@default_identity_ref.nil?
|
14
|
+
@@default_identity_ref = ReferenceResolver.get_identity_ref( "slpt.services" )
|
15
|
+
end
|
16
|
+
return @@default_identity_ref
|
17
|
+
end #def self.get_default_identity_ref
|
18
|
+
|
19
|
+
def self.get_identity_ref( name )
|
20
|
+
|
21
|
+
query = {
|
22
|
+
"queryType": "SAILPOINT",
|
23
|
+
"query": {
|
24
|
+
"query": "name:#{name}"
|
25
|
+
}
|
26
|
+
}
|
27
|
+
response = IDNAPI.post_json( "#{$url}/beta/search/identities?count=true&offset=0&limit=1", $token, query )
|
28
|
+
|
29
|
+
unless response['X-Total-Count'].nil?
|
30
|
+
count = response['X-Total-Count'].to_i
|
31
|
+
|
32
|
+
if count == 1 # Make sure we have a unique result.
|
33
|
+
|
34
|
+
identities = JSON.parse( response.body )
|
35
|
+
|
36
|
+
identity = identities.first
|
37
|
+
|
38
|
+
identity_ref = {
|
39
|
+
"type": "IDENTITY",
|
40
|
+
"id": identity['id'],
|
41
|
+
"name": identity['name']
|
42
|
+
}
|
43
|
+
|
44
|
+
return identity_ref
|
45
|
+
|
46
|
+
elsif name != "slpt.services" # We don't have a unique result, and we're not looking up slpt.services, so we'll look that up instead.
|
47
|
+
|
48
|
+
$log.debug "\t\tCannot resolve unique identity '#{name}'. Resolving identity 'slpt.services' instead."
|
49
|
+
return ReferenceResolver.get_default_identity_ref
|
50
|
+
|
51
|
+
else # We don't have a unique result, and we couldn't resolve anything else. Punt. Hopefully we never see this message.
|
52
|
+
|
53
|
+
$log.debug "\t\tCannot resolve identity '#{name}' . Giving up with no identity."
|
54
|
+
return nil
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end # if response['X-Total-Count'].nil?
|
59
|
+
|
60
|
+
return nil # catch all.
|
61
|
+
|
62
|
+
end # def self.get_identity_ref ( name )
|
63
|
+
|
64
|
+
def self.get_default_cluster_ref
|
65
|
+
|
66
|
+
if @@default_cluster_ref.nil?
|
67
|
+
|
68
|
+
response = IDNAPI.get( "#{$url}/cc/api/cluster/list", $token )
|
69
|
+
|
70
|
+
case response
|
71
|
+
when Net::HTTPSuccess
|
72
|
+
|
73
|
+
clusters = JSON.parse( response.body )
|
74
|
+
|
75
|
+
unless clusters.nil? || clusters.empty?
|
76
|
+
|
77
|
+
cluster = clusters.first
|
78
|
+
|
79
|
+
cluster_ref = {
|
80
|
+
"type": "CLUSTER",
|
81
|
+
"id": "#{cluster['configuration']['clusterExternalId']}",
|
82
|
+
"name": "#{cluster['name']}"
|
83
|
+
}
|
84
|
+
|
85
|
+
@@default_cluster_ref = cluster_ref
|
86
|
+
|
87
|
+
end #unless clusters["items"].nil?
|
88
|
+
|
89
|
+
else
|
90
|
+
$log.error "\tError: Unable to fetch clusters."
|
91
|
+
end # case response
|
92
|
+
|
93
|
+
end # if @@default_cluster_ref.nil?
|
94
|
+
|
95
|
+
return @@default_cluster_ref
|
96
|
+
|
97
|
+
end # def self.get_default_cluster_ref
|
98
|
+
|
99
|
+
def self.get_cluster_ref( name )
|
100
|
+
|
101
|
+
response = IDNAPI.get( "#{$url}/cc/api/cluster/list", $token )
|
102
|
+
|
103
|
+
case response
|
104
|
+
when Net::HTTPSuccess
|
105
|
+
|
106
|
+
clusters = JSON.parse( response.body )
|
107
|
+
|
108
|
+
unless clusters.nil? || clusters.empty?
|
109
|
+
|
110
|
+
clusters.each do |cluster|
|
111
|
+
|
112
|
+
# If we match the name of the cluster we are looking for.
|
113
|
+
if cluster['name'] == name
|
114
|
+
|
115
|
+
cluster_ref = {
|
116
|
+
"type": "CLUSTER",
|
117
|
+
"id": "#{cluster['configuration']['clusterExternalId']}",
|
118
|
+
"name": "#{cluster['name']}"
|
119
|
+
}
|
120
|
+
return cluster_ref
|
121
|
+
|
122
|
+
end # if cluster['name'] == name
|
123
|
+
|
124
|
+
end # clusters.each do |cluster|
|
125
|
+
|
126
|
+
end # unless clusters["items"].nil?
|
127
|
+
|
128
|
+
else
|
129
|
+
$log.error "\tError: Unable to fetch clusters."
|
130
|
+
end # case response
|
131
|
+
|
132
|
+
$log.warn "\tUnable to find a cluster which matches name #{name}."
|
133
|
+
|
134
|
+
return nil
|
135
|
+
|
136
|
+
end # def self.get_cluster_ref( name )
|
137
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "json"
|
3
|
+
require "csv"
|
4
|
+
require "idnio/idnapi"
|
5
|
+
require "idnio/program"
|
6
|
+
require "idnio/markdown"
|
7
|
+
|
8
|
+
module Roles
|
9
|
+
|
10
|
+
def self.querysearch( query )
|
11
|
+
|
12
|
+
response = IDNAPI.get( "#{$url}/v2/search/roles?offset=0&limit=10&query=#{query}", $token )
|
13
|
+
|
14
|
+
case response
|
15
|
+
when Net::HTTPSuccess
|
16
|
+
|
17
|
+
roles = JSON.parse( response.body )
|
18
|
+
|
19
|
+
unless roles.nil? || roles.empty?
|
20
|
+
return roles.first
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
return nil
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Exports Role configurations.
|
31
|
+
#
|
32
|
+
def self.export( directory )
|
33
|
+
|
34
|
+
response = IDNAPI.get( "#{$url}/cc/api/role/list", $token )
|
35
|
+
|
36
|
+
unless response.nil?
|
37
|
+
|
38
|
+
roles = JSON.parse( response.body )
|
39
|
+
|
40
|
+
$log.info "\tDetected #{roles['count']} roles."
|
41
|
+
|
42
|
+
roles['items'].each do |role|
|
43
|
+
|
44
|
+
apNames = ""
|
45
|
+
|
46
|
+
$log.info "\tRole: #{role["displayName"]}"
|
47
|
+
|
48
|
+
role_response = IDNAPI.get( "#{$url}/cc/api/role/get/?id=#{role["id"]}", $token )
|
49
|
+
|
50
|
+
full_role = JSON.parse( role_response.body )
|
51
|
+
|
52
|
+
full_role['accessProfileIds'].each do |ap|
|
53
|
+
|
54
|
+
response = IDNAPI.get( "#{$url}/v2/search/accessprofiles?query='id=#{ap}''", $token )
|
55
|
+
|
56
|
+
unless response.nil?
|
57
|
+
result = JSON.parse( response.body )
|
58
|
+
result.each do |r|
|
59
|
+
|
60
|
+
apNames << r['name']
|
61
|
+
apNames << ";"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
full_role['accessProfileNames'] = apNames
|
66
|
+
|
67
|
+
Program.write_file( "#{directory}/roles/", "Role - #{full_role["displayName"]}.json", JSON.pretty_generate(full_role) )
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Import Role configurations.
|
74
|
+
#
|
75
|
+
def self.import( directory )
|
76
|
+
$log.warn "\tImport for object type roles is not supported at this time."
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# Documents Role configurations.
|
81
|
+
#
|
82
|
+
def self.doc
|
83
|
+
Markdown.h2( "Roles" )
|
84
|
+
|
85
|
+
Markdown.text( "| Name | Description | Selector | Access Profiles |\n")
|
86
|
+
Markdown.text( "|------|-------------|----------|-----------------|\n")
|
87
|
+
|
88
|
+
response = IDNAPI.get( "#{$url}/cc/api/role/list", $token )
|
89
|
+
unless response.nil?
|
90
|
+
roles = JSON.parse( response.body )
|
91
|
+
|
92
|
+
$log.info "\tDetected #{roles['count']} roles."
|
93
|
+
|
94
|
+
roles['items'].each do |role|
|
95
|
+
$log.info "\tRole: #{role["displayName"]}"
|
96
|
+
role_response = IDNAPI.get( "#{$url}/cc/api/role/get/?id=#{role["id"]}", $token )
|
97
|
+
full_role = JSON.parse( role_response.body )
|
98
|
+
search_role = Roles.querysearch( "name:\"#{role["displayName"]}\"" )
|
99
|
+
accessProfileNames = ""
|
100
|
+
|
101
|
+
unless search_role["accessProfiles"].nil?
|
102
|
+
search_role["accessProfiles"].each do |ap|
|
103
|
+
if accessProfileNames != ""
|
104
|
+
accessProfileNames += ","
|
105
|
+
end
|
106
|
+
accessProfileNames += ap["name"]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
#end
|
110
|
+
Markdown.text( "|#{full_role["displayName"]}|#{full_role["description"]}|#{full_role["selector"]}|#{accessProfileNames}|\n")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
Markdown.write
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "json"
|
3
|
+
require "idnio/idnapi"
|
4
|
+
require "idnio/program"
|
5
|
+
require "idnio/markdown"
|
6
|
+
|
7
|
+
module Rules
|
8
|
+
|
9
|
+
@@default_rules = [
|
10
|
+
"AccessIQ Add Usage Certification",
|
11
|
+
"Account Report Form Customizer",
|
12
|
+
"Active Directory Customization",
|
13
|
+
"After Operation Rule Template for Web Services",
|
14
|
+
"All Objects",
|
15
|
+
"Approval Library",
|
16
|
+
"Azure AD Customization",
|
17
|
+
"Before Operation Rule Template for Web Services Connector",
|
18
|
+
"Build Manual Action Approvals",
|
19
|
+
"CEFActivityCorrelation",
|
20
|
+
"CEFTransformRule",
|
21
|
+
"Certification Report Customizer",
|
22
|
+
"Check Password Policy",
|
23
|
+
"Clear CustomGlobal",
|
24
|
+
"Cloud Account Attribute Transform",
|
25
|
+
"Cloud Account Group Refresh Rule",
|
26
|
+
"Cloud Active Phase Enter Rule",
|
27
|
+
"Cloud Approval Escalation Rule",
|
28
|
+
"Cloud Calculate Authentication Alias",
|
29
|
+
"Cloud Calculate Identity Status",
|
30
|
+
"Cloud Calculate Internal Identity Status",
|
31
|
+
"Cloud Cert Item Customization Rule",
|
32
|
+
"Cloud Certification Reassignment Rule",
|
33
|
+
"Cloud Clone Existing Account",
|
34
|
+
"Cloud Correlate Manager by AccountId",
|
35
|
+
"Cloud Detect Lifecycle State Change",
|
36
|
+
"Cloud End Phase Enter Rule",
|
37
|
+
"Cloud Flat File CustomizationRule",
|
38
|
+
"Cloud Identity Refresh Rule",
|
39
|
+
"Cloud Identity Tester",
|
40
|
+
"Cloud Promote Identity Attribute",
|
41
|
+
"CMS Cert Item Customization Rule",
|
42
|
+
"CMS Certification Reassignment Rule",
|
43
|
+
"CMS Execute Campaign Filter",
|
44
|
+
"Correct Link Idx Column",
|
45
|
+
"Create Password",
|
46
|
+
"Create Unique Account ID",
|
47
|
+
"Create Unique LDAP Attribute",
|
48
|
+
"Exclude Uncorrelated Identities",
|
49
|
+
"Execute Campaign Filter",
|
50
|
+
"Get Manager LDAP DN",
|
51
|
+
"Identity Report Form Customizer",
|
52
|
+
"IdentityNowSAML",
|
53
|
+
"JDBCProvisioning Rule Adapter",
|
54
|
+
"LCM Build Identity ApprovalSet",
|
55
|
+
"LCM Build Identity Approvers",
|
56
|
+
"LCM Build Owner Approvals",
|
57
|
+
"LCM Validate Identity Name",
|
58
|
+
"LCM Validate Password",
|
59
|
+
"LCM Workflow Library",
|
60
|
+
"Microsoft Office365 Customization",
|
61
|
+
"No Correlator",
|
62
|
+
"Objects in Requestee's Assigned Scope",
|
63
|
+
"Objects in Requestor's Authorized Scopes",
|
64
|
+
"Objects in Requestor's Authorized Scopes or Requestee's Assigned Scope",
|
65
|
+
"Objects Owned by the Requestor",
|
66
|
+
"Privileged Access Report Customizer",
|
67
|
+
"Privileged Access Report Validation Rule",
|
68
|
+
"Report Completion Notification",
|
69
|
+
"Report Scorecard Value Renderer",
|
70
|
+
"SuccessFactorsOperationProvisioning",
|
71
|
+
"System Configured Locale Rule",
|
72
|
+
"Task Completion Email Rule",
|
73
|
+
"WindowsActivityRuleLibrary",
|
74
|
+
"Workflow Library"
|
75
|
+
]
|
76
|
+
|
77
|
+
#
|
78
|
+
# Get Rule XML
|
79
|
+
#
|
80
|
+
def self.get_xml( rule )
|
81
|
+
|
82
|
+
if rule.nil?
|
83
|
+
return nil
|
84
|
+
end
|
85
|
+
|
86
|
+
rule_xml = "<?xml version='1.0' encoding='UTF-8'?>\n<!DOCTYPE Rule PUBLIC 'sailpoint.dtd' 'sailpoint.dtd'>\n<Rule language='beanshell' name='#{rule['name']}'"
|
87
|
+
|
88
|
+
unless rule['type'].nil?
|
89
|
+
rule_xml += " type='#{rule['type']}' "
|
90
|
+
end
|
91
|
+
|
92
|
+
unless rule['description'].nil?
|
93
|
+
rule_description = rule['description'].gsub(/\t+|\s+/," ").gsub(/(\r\n)+|\r+|^\s+|\s+$|\n+?/,"")
|
94
|
+
else
|
95
|
+
rule_description = ""
|
96
|
+
end
|
97
|
+
|
98
|
+
rule_xml += ">\n\t<Description>#{rule_description}</Description>\n\t<Source><![CDATA[\n#{rule['source']}\n]]></Source>\n</Rule>"
|
99
|
+
|
100
|
+
return rule_xml
|
101
|
+
end
|
102
|
+
|
103
|
+
#
|
104
|
+
# Exports Rule configurations.
|
105
|
+
#
|
106
|
+
def self.export( directory )
|
107
|
+
|
108
|
+
response = IDNAPI.get( "#{$url}/cc/api/rule/list", $token )
|
109
|
+
|
110
|
+
case response
|
111
|
+
when Net::HTTPSuccess
|
112
|
+
|
113
|
+
rules = JSON.parse( response.body )
|
114
|
+
|
115
|
+
$log.info "\tDetected #{rules["count"]} rules."
|
116
|
+
|
117
|
+
rules["items"].each do |rule|
|
118
|
+
|
119
|
+
if (!@@default_rules.include? rule["name"]) || $config["include-defaults"]
|
120
|
+
|
121
|
+
$log.info "\tRule: #{rule["name"]}"
|
122
|
+
|
123
|
+
if rule["type"].nil?
|
124
|
+
Program.write_file( "#{directory}/rules/", "Rule - Generic - #{rule["name"]}.xml", Rules.get_xml( rule ) )
|
125
|
+
else
|
126
|
+
Program.write_file( "#{directory}/rules/", "Rule - #{rule["type"]} - #{rule["name"]}.xml", Rules.get_xml( rule ) )
|
127
|
+
end
|
128
|
+
|
129
|
+
else
|
130
|
+
|
131
|
+
$log.info "\tSkipping Default Rule: #{rule["name"]}"
|
132
|
+
|
133
|
+
end # if (!@@default_transforms.include? transform["id"]...
|
134
|
+
|
135
|
+
end # rules["items"].each do |rule|
|
136
|
+
|
137
|
+
else
|
138
|
+
$log.error "\tError: Unable to fetch rules."
|
139
|
+
end # case response
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
#
|
144
|
+
# Imports Rule configurations.
|
145
|
+
#
|
146
|
+
def self.import( directory )
|
147
|
+
$log.warn "\t Import of rules is not supported. Please contact SailPoint in order to install a rule in the system."
|
148
|
+
end
|
149
|
+
|
150
|
+
#
|
151
|
+
# Documents Rule configurations.
|
152
|
+
#
|
153
|
+
def self.doc
|
154
|
+
|
155
|
+
response = IDNAPI.get( "#{$url}/cc/api/rule/list", $token )
|
156
|
+
|
157
|
+
case response
|
158
|
+
when Net::HTTPSuccess
|
159
|
+
|
160
|
+
rules = JSON.parse( response.body )
|
161
|
+
|
162
|
+
$log.info "\tDetected #{rules["count"]} rules."
|
163
|
+
|
164
|
+
Markdown.h2 "Rules"
|
165
|
+
|
166
|
+
rules["items"].each do |rule|
|
167
|
+
|
168
|
+
if (!@@default_rules.include? rule["name"]) || $config["include-defaults"]
|
169
|
+
|
170
|
+
$log.info "\tRule: #{rule["name"]}"
|
171
|
+
|
172
|
+
if rule["type"].nil?
|
173
|
+
Markdown.h3 "#{rule["name"]} (Generic)"
|
174
|
+
else
|
175
|
+
Markdown.h3 "#{rule["name"]} (#{rule["type"]})"
|
176
|
+
end
|
177
|
+
|
178
|
+
unless rule['description'].nil?
|
179
|
+
Markdown.text "#{rule['description'].gsub(/\t+|\s+/," ").gsub(/(\r\n)+|\r+|^\s+|\s+$|\n+?/,"")}\n"
|
180
|
+
end
|
181
|
+
|
182
|
+
Markdown.xml Rules.get_xml( rule )
|
183
|
+
|
184
|
+
else
|
185
|
+
|
186
|
+
$log.info "\tSkipping Default Rule: #{rule["name"]}"
|
187
|
+
|
188
|
+
end # if (!@@default_transforms.include? transform["id"]...
|
189
|
+
|
190
|
+
end # rules["items"].each do |rule|
|
191
|
+
|
192
|
+
else
|
193
|
+
$log.error "\tError: Unable to fetch rules."
|
194
|
+
end # case response
|
195
|
+
|
196
|
+
Markdown.write
|
197
|
+
end
|
198
|
+
end
|