idnio 2.3.2b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a338413e2b8be16c9974354d15d8bc953e54a3378601a62c07e9609d29c63bb9
4
+ data.tar.gz: e5c86b39c1e50cf90d652c77957065bc4caeaa28531d0527991fdec6d5344680
5
+ SHA512:
6
+ metadata.gz: e3b13ab5922d07ba762603c50ff6d783eaa88f485dc925ddfe34fa3551d15411505085ed2adbb90de81d4080d4bf1b2e95b8b4264f9ebe1d0198f7879935ec1e
7
+ data.tar.gz: 2ef7893e6c0fe821d1b198cca854ace82ad5b8c656ad129e026e705cad6d06dd88d6ea094aca05ff3188c156410ab0dcb84c1f97a87160086690c39b8ce7adae
checksums.yaml.gz.sig ADDED
Binary file
data.tar.gz.sig ADDED
Binary file
data/lib/idnio.rb ADDED
@@ -0,0 +1,295 @@
1
+ require 'fileutils'
2
+ require 'logger'
3
+ require "date"
4
+ require "idnio/version"
5
+ require "idnio/program"
6
+ require "idnio/markdown"
7
+ require "objects/transforms"
8
+ require "objects/system-settings"
9
+ require "objects/sources"
10
+ require "objects/account-schemas"
11
+ require "objects/account-profiles"
12
+ require "objects/access-profiles"
13
+ require "objects/applications"
14
+ require "objects/attribute-sync-config"
15
+ require "objects/branding"
16
+ require "objects/campaign-filters"
17
+ require "objects/connectors"
18
+ require "objects/email-templates"
19
+ require "objects/identity-attributes"
20
+ require "objects/identity-profiles"
21
+ require "objects/integrations"
22
+ require "objects/lifecycle-states"
23
+ require "objects/password-policies"
24
+ require "objects/password-sync-groups"
25
+ require "objects/public-identities-config"
26
+ require "objects/access-request-config"
27
+ require "objects/reference-resolver"
28
+ require "objects/roles"
29
+ require "objects/rules"
30
+
31
+ module IDNIO
32
+
33
+ $config = nil
34
+
35
+ $log = Logger.new(STDOUT)
36
+ $log.level = Logger::WARN
37
+ $log.datetime_format = '%Y-%m-%d %H:%M:%S'
38
+ $log.formatter = proc do |severity, datetime, progname, msg|
39
+ "#{msg}\n"
40
+ end
41
+
42
+ def self.setConfig(config)
43
+ $config = config
44
+
45
+ unless $config["log-level"].nil?
46
+ $log.level = $config["log-level"]
47
+ end
48
+
49
+ end
50
+
51
+ def self.docs()
52
+
53
+ #
54
+ # Program Start / Version
55
+ #
56
+ Program.start( "IdentityNow I/O Documenter", "Neil McGlennon, Dustin Yeager", Idnio::VERSION, Idnio::UPDATE_DATE )
57
+
58
+ #
59
+ # Constants
60
+ #
61
+ $output = File.join( $config['output-directory'], $tenant, "README.md")
62
+
63
+ #
64
+ # Initialize Markdown
65
+ #
66
+ Markdown.open( $output )
67
+ Markdown.text( "![SailPoint](https://files.accessiq.sailpoint.com/modules/builds/static-assets/perpetual/sailpoint/logo/1.0/sailpoint_logo_color_228x50.png)\n\n\n" )
68
+ Markdown.h1( "IdentityNow Configuration" )
69
+ Markdown.ul( [
70
+ "Generated on **#{Date.today.iso8601}**",
71
+ "Generated for **#{$tenant}**"
72
+ ] )
73
+ Markdown.toc
74
+ Markdown.write
75
+
76
+ #
77
+ # Main Process
78
+ #
79
+ $config['process'].each do |key, value|
80
+ if value
81
+ Program.output( "Documenting #{key}..." )
82
+ case key
83
+ when "access-profiles"
84
+ AccessProfiles.doc
85
+ when "account-profiles"
86
+ AccountProfiles.doc
87
+ when "account-schemas"
88
+ AccountSchemas.doc
89
+ when "applications"
90
+ Applications.doc
91
+ when "attribute-sync-config"
92
+ AttributeSyncConfig.doc
93
+ when "branding"
94
+ Branding.doc
95
+ when "campaign-filters"
96
+ CampaignFilters.doc
97
+ when "connectors"
98
+ Connectors.doc
99
+ when "email-templates"
100
+ EmailTemplates.doc
101
+ when "identity-attributes"
102
+ IdentityAttributes.doc
103
+ when "identity-profiles"
104
+ IdentityProfiles.doc
105
+ when "integrations"
106
+ Integrations.doc
107
+ when "lifecycle-states"
108
+ LifecycleStates.doc
109
+ when "password-policies"
110
+ PasswordPolicies.doc
111
+ when "password-sync-groups"
112
+ PasswordSyncGroups.doc
113
+ when "roles"
114
+ Roles.doc
115
+ when "rules"
116
+ Rules.doc
117
+ when "sources"
118
+ Sources.doc
119
+ when "system-settings"
120
+ SystemSettings.doc
121
+ when "public-identities-config"
122
+ PublicIdentitiesConfig.doc
123
+ when "access-request-config"
124
+ AccessRequestConfig.doc
125
+ when "transforms"
126
+ Transforms.doc
127
+ else
128
+ $log.warn "#{key} is not a valid doc type! Skipping."
129
+ end
130
+ else
131
+ Program.output( "Skipping #{key}, since it is disabled." )
132
+ end
133
+ end
134
+
135
+ #
136
+ # Completion!
137
+ #
138
+ Program.end
139
+ end
140
+
141
+ def self.import()
142
+
143
+ #
144
+ # Program Start / Version
145
+ #
146
+ Program.start( "IdentityNow I/O Importer", "Neil McGlennon, Dustin Yeager", Idnio::VERSION, Idnio::UPDATE_DATE )
147
+
148
+ #
149
+ # Constants
150
+ #
151
+ $input = File.join( $config['input-directory'], $tenant )
152
+
153
+ #
154
+ # Main Process
155
+ #
156
+ $config['process'].each do |key, value|
157
+ if value
158
+ Program.output( "Importing #{key}..." )
159
+ case key
160
+ when "access-profiles"
161
+ AccessProfiles.import( $input )
162
+ when "account-profiles"
163
+ AccountProfiles.import( $input )
164
+ when "account-schemas"
165
+ AccountSchemas.import( $input )
166
+ when "applications"
167
+ Applications.import( $input )
168
+ when "attribute-sync-config"
169
+ AttributeSyncConfig.import( $input )
170
+ when "branding"
171
+ Branding.import( $input )
172
+ when "campaign-filters"
173
+ CampaignFilters.import( $input )
174
+ when "connectors"
175
+ Connectors.import( $input )
176
+ when "email-templates"
177
+ EmailTemplates.import( $input )
178
+ when "identity-attributes"
179
+ IdentityAttributes.import( $input )
180
+ when "identity-profiles"
181
+ IdentityProfiles.import( $input )
182
+ when "integrations"
183
+ Integrations.import( $input )
184
+ when "lifecycle-states"
185
+ LifecycleStates.import( $input )
186
+ when "password-policies"
187
+ PasswordPolicies.import( $input )
188
+ when "password-sync-groups"
189
+ PasswordSyncGroups.import( $input )
190
+ when "roles"
191
+ Roles.import( $input )
192
+ when "rules"
193
+ Rules.import( $input )
194
+ when "sources"
195
+ Sources.import( $input )
196
+ when "system-settings"
197
+ SystemSettings.import( $input )
198
+ when "public-identities-config"
199
+ PublicIdentitiesConfig.import( $input )
200
+ when "access-request-config"
201
+ AccessRequestConfig.import( $input )
202
+ when "transforms"
203
+ Transforms.import( $input )
204
+ else
205
+ $log.warn "#{key} is not a valid export type! Skipping."
206
+ end
207
+ else
208
+ Program.output( "Skipping #{key}, since it is disabled." )
209
+ end
210
+ end
211
+
212
+ #
213
+ # Completion!
214
+ #
215
+ Program.end
216
+ end
217
+
218
+ def self.export()
219
+
220
+ #
221
+ # Program Start / Version
222
+ #
223
+ Program.start( "IdentityNow I/O Exporter", "Neil McGlennon, Dustin Yeager", Idnio::VERSION, Idnio::UPDATE_DATE )
224
+
225
+ #
226
+ # Constants
227
+ #
228
+ $output = File.join( $config['output-directory'], $tenant )
229
+
230
+ #
231
+ # Main Process
232
+ #
233
+ $config['process'].each do |key, value|
234
+ if value
235
+ Program.output( "Exporting #{key}..." )
236
+ case key
237
+ when "access-profiles"
238
+ AccessProfiles.export( $output )
239
+ when "account-profiles"
240
+ AccountProfiles.export( $output )
241
+ when "account-schemas"
242
+ AccountSchemas.export( $output )
243
+ when "applications"
244
+ Applications.export( $output )
245
+ when "attribute-sync-config"
246
+ AttributeSyncConfig.export( $output )
247
+ when "branding"
248
+ Branding.export( $output )
249
+ when "campaign-filters"
250
+ CampaignFilters.export( $output)
251
+ when "connectors"
252
+ Connectors.export( $output )
253
+ when "email-templates"
254
+ EmailTemplates.export( $output )
255
+ when "identity-attributes"
256
+ IdentityAttributes.export( $output )
257
+ when "identity-profiles"
258
+ IdentityProfiles.export( $output )
259
+ when "integrations"
260
+ Integrations.export( $output )
261
+ when "lifecycle-states"
262
+ LifecycleStates.export( $output )
263
+ when "password-policies"
264
+ PasswordPolicies.export( $output )
265
+ when "password-sync-groups"
266
+ PasswordSyncGroups.export( $output )
267
+ when "roles"
268
+ Roles.export( $output )
269
+ when "rules"
270
+ Rules.export( $output )
271
+ when "sources"
272
+ Sources.export( $output )
273
+ when "system-settings"
274
+ SystemSettings.export( $output )
275
+ when "public-identities-config"
276
+ PublicIdentitiesConfig.export( $output )
277
+ when "access-request-config"
278
+ AccessRequestConfig.export( $output )
279
+ when "transforms"
280
+ Transforms.export( $output )
281
+ else
282
+ $log.warn "#{key} is not a valid export type! Skipping."
283
+ end
284
+ else
285
+ Program.output( "Skipping #{key}, since it is disabled." )
286
+ end
287
+ end
288
+
289
+ #
290
+ # Completion!
291
+ #
292
+ Program.end
293
+ end
294
+
295
+ end
@@ -0,0 +1,34 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ #
5
+ # Auxillary Cryptography classes for hashing and RSA encryption.
6
+ #
7
+ module Crypto
8
+
9
+ #
10
+ # Hashes a password given a password and a salt.
11
+ #
12
+ def self.hash_password( password, salt )
13
+ if ( password.nil? || salt.nil? )
14
+ return nil
15
+ end
16
+
17
+ return Digest::SHA256.hexdigest( password + Digest::SHA256.hexdigest( salt.downcase ) )
18
+ end
19
+
20
+ #
21
+ # Encrypts the password using RSA encryption. Used for password reset utilities.
22
+ # public_key_string must be in the format:
23
+ # "-----BEGIN PUBLIC KEY-----\nMIIBI...+QwIDAQAB\n-----END PUBLIC KEY-----"
24
+ #
25
+ def self.encrypt_password( public_key_string, password )
26
+ if ( public_key_string.nil? || password.nil? )
27
+ return nil
28
+ end
29
+
30
+ public_key = OpenSSL::PKey::RSA.new( public_key_string )
31
+ return Base64.encode64( public_key.public_encrypt( password ) )
32
+ end
33
+
34
+ end
@@ -0,0 +1,158 @@
1
+ require 'fileutils'
2
+ require "net/http"
3
+ require "uri"
4
+ require "json"
5
+
6
+ #
7
+ # IDN API Utility
8
+ #
9
+ module IDNAPI
10
+
11
+ #
12
+ # Utility method to call the API (for GET calls only).
13
+ #
14
+ def self.get( url, token )
15
+
16
+ $log.debug "Calling GET #{url}"
17
+
18
+ url = URI.parse( url )
19
+ http = Net::HTTP.new( url.host, url.port )
20
+ http.use_ssl = true
21
+ header = {
22
+ "Authorization": "Bearer #{token}"
23
+ }
24
+ request = Net::HTTP::Get.new( url, header )
25
+ response = http.request( request )
26
+
27
+ return analyze_response( request, response )
28
+
29
+ end
30
+
31
+ #
32
+ # Utility method to call the API for Unauthenticated POST calls only
33
+ #
34
+ def self.post_unauth( url )
35
+
36
+ $log.debug "Calling (unathenticated) POST #{url} with no data."
37
+
38
+ url = URI( url )
39
+ http = Net::HTTP.new( url.host, url.port )
40
+ http.use_ssl = true
41
+ header = {}
42
+ request = Net::HTTP::Post.new( url, header )
43
+ response = http.request( request )
44
+
45
+ return analyze_response( request, response )
46
+
47
+ end
48
+
49
+ #
50
+ # Utility method to call the API (for JSON POST calls only).
51
+ #
52
+ def self.post_json( url, token, json_object )
53
+
54
+ $log.debug "Calling POST #{url} with data: #{json_object}"
55
+
56
+ url = URI( url )
57
+ http = Net::HTTP.new( url.host, url.port )
58
+ http.use_ssl = true
59
+ header = {
60
+ "Authorization": "Bearer #{token}",
61
+ "Content-Type":"application/json",
62
+ "cache-control": "no-cache"
63
+ }
64
+ request = Net::HTTP::Post.new( url, header )
65
+ unless json_object.nil?
66
+ request.body = json_object.to_json
67
+ end
68
+ response = http.request( request )
69
+
70
+ return analyze_response( request, response )
71
+
72
+ end
73
+
74
+ #
75
+ # Utility method to call the API (for JSON POST calls only).
76
+ #
77
+ def self.put_json( url, token, json_object )
78
+
79
+ $log.debug "Calling PUT #{url} with data: #{json_object}"
80
+
81
+ url = URI( url )
82
+ http = Net::HTTP.new( url.host, url.port )
83
+ http.use_ssl = true
84
+ header = {
85
+ "Authorization": "Bearer #{token}",
86
+ "Content-Type":"application/json",
87
+ "cache-control": "no-cache"
88
+ }
89
+ request = Net::HTTP::Put.new( url, header )
90
+ request.body = json_object.to_json
91
+ response = http.request( request )
92
+
93
+ return analyze_response( request, response )
94
+
95
+ end
96
+
97
+ #
98
+ # Utility method to call the API (for form POST calls only)
99
+ #
100
+ def self.post_form( url, token, form_data )
101
+
102
+ $log.debug "Calling POST #{url} with data: #{form_data}"
103
+
104
+ url = URI( url )
105
+ http = Net::HTTP.new( url.host, url.port )
106
+ http.use_ssl = true
107
+ header = {
108
+ "Authorization": "Bearer #{token}",
109
+ "Content-Type":"application/x-www-form-urlencoded",
110
+ "cache-control": "no-cache"
111
+ }
112
+
113
+ request = Net::HTTP::Post.new( url, header )
114
+ request.body = URI.encode_www_form( form_data )
115
+ response = http.request( request )
116
+
117
+ return analyze_response( request, response )
118
+
119
+ end
120
+
121
+ #
122
+ # Utility method to analyze the responses
123
+ #
124
+ def self.analyze_response( request, response )
125
+
126
+ $log.debug( "Received response: #{response.code} #{response.message} #{response.body}")
127
+
128
+ case response
129
+ when Net::HTTPSuccess
130
+ $log.debug "Successful response recieved."
131
+ return response
132
+ when Net::HTTPForbidden
133
+ $log.fatal "Error: Forbidden. Try logging in as an admin, or stepping up auth."
134
+ abort
135
+ when Net::HTTPUnauthorized
136
+ $log.fatal "Error: The token has expired. Update your session token and try again."
137
+ abort
138
+ when Net::OpenTimeout
139
+ $log.fatal "Error: API has been unresponsive. Please retry the operation."
140
+ abort
141
+ when Net::HTTPBadRequest
142
+ $log.debug "\tError: Bad Request."
143
+ when Net::HTTPNotFound
144
+ $log.debug "\tWarning: Not Found."
145
+ when Net::HTTPServerError
146
+ $log.debug "\tError: Server Error."
147
+ else
148
+ unless response.body.nil?
149
+ $log.debug "\tError: #{ response.body }"
150
+ else
151
+ $log.debug "\tError: Unknown."
152
+ end
153
+ end
154
+
155
+ return response
156
+ end
157
+
158
+ end