identitynow_rule_validator 1.0.0b

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: f72bbdbdfce7f45b1010ee5bc4f170fe219c83fd8e9b156d7b719dc912b7147d
4
+ data.tar.gz: 832e3afdb507f4d7d080709c209aa82edd338b82c5d281a4bc6a27909ca88206
5
+ SHA512:
6
+ metadata.gz: 86e792cc08b0964c237e725e84895883854f40e45b5ea65b5571ddfbed39438e1f872989d48561d4f0fe2508b3e4ca55b470b13c63152a416299414f406fb06b
7
+ data.tar.gz: 70b4295494b9129f7df960015ecd52f73744e201895de2086a2933b5d8f90f7dd86f7537afddb4dd2d6b7907e22ba2b39e69d081fb37bb5f51f971798c520d84
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ uH:B�\�o�P[�Qò9�슫Wĩz"�i����2�J(������8�xY^)๕� ��s��UUZ��en����~D����5(�yg��K��Se؎��9�g~L fu yK��dmr���d�K������=�sч+N�B��%�-����<�V t����n�pvr�8�O���)q�A �`Z�3��TLB�'*T�i&\:
2
+ ��_G���'�'�9ܚ��8t���H�� ]Tp�VK.ԋ$UH��x�Rn�"��$���>7� �\9+0���i��8��I xv A �%sj��$1� 8�,wu�H�xCݢ����]f=?�r*Na��ڱ�fN�[�2��4������4��A��h�>> E_�
data.tar.gz.sig ADDED
Binary file
@@ -0,0 +1,179 @@
1
+ require 'json'
2
+ require 'colorize'
3
+ require 'program'
4
+
5
+ class IdentityNowRuleValidator
6
+
7
+ #
8
+ # This will collect findings for each file.
9
+ #
10
+ @@findings = []
11
+
12
+ #
13
+ # This holds details about the files.
14
+ #
15
+ @@filesCount = 0;
16
+
17
+ #
18
+ # These are the rules which are used for validation.
19
+ #
20
+ @@rules = []
21
+
22
+ #
23
+ # This will help determine if we're still showing findings for the same file.
24
+ #
25
+ @@previousFile = nil
26
+
27
+ def self.validate_directory( directory )
28
+
29
+ self.initialize
30
+
31
+ puts "Validating files from directory: #{directory}"
32
+
33
+ Dir.glob( File.join( directory + '**/*.xml' ) ).each do |file|
34
+
35
+ self.analyze_file( file )
36
+
37
+ end # files.each do |file|
38
+
39
+ self.report_findings
40
+
41
+ end
42
+
43
+ def self.validate_files( files )
44
+
45
+ self.initialize
46
+
47
+ puts "Validating files: #{files}"
48
+
49
+ if ( !files.nil? && !files.empty? )
50
+
51
+ files.each do |file|
52
+
53
+ self.analyze_file( file )
54
+
55
+ end # files.each do |file|
56
+
57
+ end # if ( !files.nil? && !files.empty? )
58
+
59
+ self.report_findings
60
+
61
+ end
62
+
63
+ def self.validate_file( file )
64
+
65
+ self.initialize
66
+
67
+ puts "Validating file: #{file}"
68
+
69
+ self.analyze_file( file )
70
+
71
+ self.report_findings
72
+
73
+ end
74
+
75
+ private
76
+
77
+ def self.initialize
78
+
79
+ #
80
+ # Initialize findings to be empty.
81
+ #
82
+ @@findings = []
83
+
84
+ #
85
+ # Initialize filesCount to be 0.
86
+ #
87
+ @@filesCount = 0;
88
+
89
+ #
90
+ # Initialize rules from JSON.
91
+ #
92
+ @@rules = JSON.parse( File.read( File.join( __dir__, "rules.json" ) ) )
93
+
94
+ #
95
+ # Initialize previous file to empty
96
+ #
97
+ @@previousFile = nil
98
+
99
+ #
100
+ # Program Start / Version
101
+ #
102
+ Program.start( "IdentityNow Rule Validator", "Neil McGlennon (neil.mcglennon@sailpoint.com)", "1.0.0b", "2020-01-21" )
103
+
104
+ end
105
+
106
+ def self.analyze_file( file )
107
+
108
+ #
109
+ # Make sure we are working with files, not directories.
110
+ #
111
+ if File.file?( file )
112
+
113
+ @@filesCount += 1;
114
+ puts "\t" + File.basename( file )
115
+
116
+ File.readlines( file ).each_with_index do |line, lineNumber|
117
+
118
+ @@rules.each do |rule|
119
+
120
+ if line.valid_encoding?
121
+ if( line.match( /#{rule['pattern']}/ ) )
122
+
123
+ finding = {
124
+ 'file': file,
125
+ 'line': lineNumber + 1,
126
+ 'text': line.strip,
127
+ 'message': rule['message'],
128
+ 'type': rule['type']
129
+ }
130
+ @@findings.push finding
131
+ end
132
+
133
+ end # if( line.match( /#{rule['pattern']}/ ) )
134
+
135
+ end # @@rules.each do |rule|
136
+
137
+ end # File.readlines( file ).each_with_index do |line, lineNumber|
138
+
139
+ end # if File.file?( file )
140
+
141
+ end
142
+
143
+ def self.report_findings
144
+
145
+ #
146
+ # Iterate through all of our findings.
147
+ #
148
+ @@findings.each do |finding|
149
+
150
+ #
151
+ # Output the file header
152
+ #
153
+ if ( finding[:file] != @@previousFile )
154
+ puts File.dirname( finding[:file] ) + "\n"
155
+ puts File.basename( finding[:file] ).bold + "\n\n"
156
+ end
157
+
158
+ #
159
+ # Output the issue
160
+ #
161
+ puts "\tLine #{finding[:line]}: #{finding[:text][0..80].gsub(/\s\w+$/,'...').light_black}"
162
+ type = ( finding[:type] == "error" ) ? "Error".red : "Warning".yellow
163
+ puts "\t#{type}: #{finding[:message]}\n\n"
164
+
165
+ #
166
+ # Set this for the next iteration
167
+ #
168
+ @@previousFile = finding[:file]
169
+
170
+ end
171
+
172
+ #
173
+ # Completion!
174
+ #
175
+ Program.end
176
+
177
+ end
178
+
179
+ end
data/lib/program.rb ADDED
@@ -0,0 +1,167 @@
1
+ # require "./lib/timer.rb"
2
+ require "json"
3
+
4
+ #
5
+ # Time Utility
6
+ #
7
+ module Timer
8
+ @@timeStart = nil
9
+ @@timeEnd = nil
10
+
11
+ #
12
+ # Starts the timer
13
+ #
14
+ def self.start
15
+ @@timeStart = Process.clock_gettime( Process::CLOCK_MONOTONIC )
16
+ end
17
+
18
+ #
19
+ # Stops the timer
20
+ #
21
+ def self.stop
22
+ @@timeEnd = Process.clock_gettime( Process::CLOCK_MONOTONIC )
23
+ end
24
+
25
+ #
26
+ # Gets elapsed time
27
+ #
28
+ def self.elapsed
29
+ unless @@timeEnd.nil? || @@timeStart.nil?
30
+
31
+ elapsed = @@timeEnd.to_i - @@timeStart.to_i # distance between t1 and t2 in seconds
32
+
33
+ resolution = if elapsed > 29030400 # seconds in a year
34
+ [(elapsed/29030400), 'years']
35
+ elsif elapsed > 2419200
36
+ [(elapsed/2419200), 'months']
37
+ elsif elapsed > 604800
38
+ [(elapsed/604800), 'weeks']
39
+ elsif elapsed > 86400
40
+ [(elapsed/86400), 'days']
41
+ elsif elapsed > 3600 # seconds in an hour
42
+ [(elapsed/3600), 'hours']
43
+ elsif elapsed > 60
44
+ [(elapsed/60), 'minutes']
45
+ else
46
+ [elapsed, 'seconds']
47
+ end
48
+
49
+ if resolution[0] == 1
50
+ return resolution.join(' ')[0...-1]
51
+ else
52
+ return resolution.join(' ')
53
+ end
54
+
55
+ else
56
+ return nil
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ #
63
+ # Program Utility
64
+ #
65
+ module Program
66
+
67
+ #
68
+ # Utility method for printing messages.
69
+ #
70
+ def self.line( )
71
+ puts ( "-" * 62 )
72
+ end
73
+
74
+ #
75
+ # Utility method for printing messages.
76
+ #
77
+ def self.output( message )
78
+ Program.line
79
+ puts " #{message}"
80
+ Program.line
81
+ end
82
+
83
+ #
84
+ # Utility to start the program
85
+ #
86
+ def self.start( name, author, version, date )
87
+ Timer.start
88
+
89
+ Program.line
90
+ puts " #{name} "
91
+ Program.line
92
+ puts " Version: #{version}"
93
+ puts " Date: #{date}"
94
+ puts " Author: #{author}"
95
+ Program.line
96
+
97
+ $tenant = nil
98
+
99
+ unless $tenant.nil?
100
+ puts " Tenant: #{$tenant}"
101
+ Program.line
102
+ end
103
+
104
+ end
105
+
106
+ #
107
+ # Utility to end the program
108
+ #
109
+ def self.end( )
110
+ Timer.stop
111
+ output( "Process completed in #{Timer.elapsed}" )
112
+ end
113
+
114
+
115
+ #
116
+ # Utility method to write output files to a directory.
117
+ #
118
+ def self.write_file( directory, name, text )
119
+ name.gsub!(/[^0-9A-Za-z. -]/,"-")
120
+ FileUtils.mkdir_p directory
121
+ File.open( File.join( directory, name ), 'w+') { |file| file.write( text ) }
122
+ end
123
+
124
+ def self.get_filenames( directory )
125
+ output = Array.new
126
+ Dir.glob("#{directory}/*.json") do |file|
127
+ #tmp = file.slice! "#{directory}/"
128
+ output.push(file)
129
+ end
130
+ return output
131
+ end
132
+
133
+ def self.read_directory( directory )
134
+ output = Array.new
135
+ Dir.glob("#{directory}/*.json") do |file|
136
+ output.push(Program.read_file(file))
137
+ end
138
+ return output
139
+ end
140
+
141
+ #
142
+ # Utility method to read output files to a directory.
143
+ #
144
+ def self.read_file( directory, name )
145
+ return Program.read_file("#{directory}/#{name}")
146
+ end
147
+
148
+ def self.read_file( name )
149
+ output = ""
150
+ #name.gsub!(/[^0-9A-Za-z. -]/,"-")
151
+ f = File.open( name, 'r')
152
+ f.each_line do |line|
153
+ output += line
154
+ end
155
+ f.close
156
+ return output
157
+ end
158
+
159
+ def self.write_csv(directory, name, content)
160
+ if !File.file?("#{directory}/#{name}")
161
+ Program.write_file(directory, name, "")
162
+ end
163
+ CSV.open("#{directory}/#{name}", "ab") do |csv|
164
+ csv << content
165
+ end
166
+ end
167
+ end
data/lib/rules.json ADDED
@@ -0,0 +1,228 @@
1
+ [{
2
+ "pattern": "System\\.(out|err)\\.print",
3
+ "message": "Remove any System.out configurations in favor of logging statements.",
4
+ "type": "warning"
5
+ },
6
+ {
7
+ "pattern": "\\.printStackTrace\\(",
8
+ "message": "Detected instances of printStackTrace(...). Remove this reference.",
9
+ "type": "warning"
10
+ },
11
+ {
12
+ "pattern": "public static",
13
+ "message": "Remove references to 'static' in methods. This can cause unexpected behavior.",
14
+ "type": "warning"
15
+ },
16
+ {
17
+ "pattern": "(<Source>)((?!<\\!\\[CDATA\\[).)*\\s?$",
18
+ "message": "Correct tag to be <Source><![CDATA[",
19
+ "type": "warning"
20
+ },
21
+ {
22
+ "pattern": "^(\\s)?(\\<\\/Source\\>)",
23
+ "message": "Correct tag to be ]]></Source>",
24
+ "type": "warning"
25
+ },
26
+ {
27
+ "pattern": "&gt;",
28
+ "message": "Detected instances of '&gt;' Convert to '>'.",
29
+ "type": "warning"
30
+ },
31
+ {
32
+ "pattern": "&lt;",
33
+ "message": "Detected instances of '&lt;' Convert to '<'.",
34
+ "type": "warning"
35
+ },
36
+ {
37
+ "pattern": "&amp;",
38
+ "message": "Detected instances of '&amp;' Convert to '&'.",
39
+ "type": "warning"
40
+ },
41
+ {
42
+ "pattern": "context\\.decrypt(\\s)?\\(",
43
+ "message": "Remove references to 'decrypt'. This is not allowed.",
44
+ "type": "error"
45
+ },
46
+ {
47
+ "pattern": "context\\.commitTransaction(\\s)?\\(",
48
+ "message": "Remove references to 'commitTransaction'. This is not allowed.",
49
+ "type": "error"
50
+ },
51
+ {
52
+ "pattern": "context\\.saveObject(\\s)?\\(",
53
+ "message": "Remove references to 'saveObject'. This is not allowed.",
54
+ "type": "error"
55
+ },
56
+ {
57
+ "pattern": "context\\.authenticate(\\s)?\\(",
58
+ "message": "Remove references to 'authenticate'. This is not allowed.",
59
+ "type": "error"
60
+ },
61
+ {
62
+ "pattern": "context\\.close(\\s)?\\(",
63
+ "message": "Remove references to 'close'. This is not allowed.",
64
+ "type": "error"
65
+ },
66
+ {
67
+ "pattern": "context\\.decache(\\s)?\\(",
68
+ "message": "Remove references to 'decache'. This is not allowed.",
69
+ "type": "error"
70
+ },
71
+
72
+ {
73
+ "pattern": "context\\.encrypt(\\s)?\\(",
74
+ "message": "Remove references to 'encrypt'. This is not allowed.",
75
+ "type": "error"
76
+ },
77
+ {
78
+ "pattern": "context\\.getJdbcConnection(\\s)?\\(",
79
+ "message": "Remove references to 'encrypt'. This is not allowed.",
80
+ "type": "error"
81
+ },
82
+ {
83
+ "pattern": "context\\.impersonate(\\s)?\\(",
84
+ "message": "Remove references to 'impersonate'. This is not allowed.",
85
+ "type": "error"
86
+ },
87
+ {
88
+ "pattern": "context\\.importObject(\\s)?\\(",
89
+ "message": "Remove references to 'importObject'. This is not allowed.",
90
+ "type": "error"
91
+ },
92
+
93
+ {
94
+ "pattern": "XMLObjectFactory\\.getInstance()\\.toXml\\(*\\)",
95
+ "message": "Remove references to XMLObjectFactory.getInstance().toXml(...).",
96
+ "type": "error"
97
+ },
98
+ {
99
+ "pattern": "\\.toXml(\\s)?\\(*\\)",
100
+ "message": "Remove references to 'toXml'. This is not allowed.",
101
+ "type": "error"
102
+ },
103
+ {
104
+ "pattern": "Thread\\.",
105
+ "message": "Remove references to 'Thread'. This is not allowed.",
106
+ "type": "error"
107
+ },
108
+ {
109
+ "pattern": "Runnable\\.",
110
+ "message": "Remove references to 'Runnable'. This is not allowed.",
111
+ "type": "error"
112
+ },
113
+ {
114
+ "pattern": "context\\.lockObject(\\s)?\\(",
115
+ "message": "Remove references to 'lockObject'. This is not allowed.",
116
+ "type": "error"
117
+ },
118
+ {
119
+ "pattern": "context\\.lockObjectById(\\s)?\\(",
120
+ "message": "Remove references to 'lockObjectById'. This is not allowed.",
121
+ "type": "error"
122
+ },
123
+ {
124
+ "pattern": "context\\.lockObjectByName(\\s)?\\(",
125
+ "message": "Remove references to 'lockObjectByName'. This is not allowed.",
126
+ "type": "error"
127
+ },
128
+ {
129
+ "pattern": "context\\.notify(\\s)?\\(",
130
+ "message": "Remove references to 'notify'. This is not allowed.",
131
+ "type": "error"
132
+ },
133
+ {
134
+ "pattern": "context\\.notifyAll(\\s)?\\(",
135
+ "message": "Remove references to 'notifyAll'. This is not allowed.",
136
+ "type": "error"
137
+ },
138
+ {
139
+ "pattern": "context\\.printStatistics(\\s)?\\(",
140
+ "message": "Remove references to 'printStatistics'. This is not allowed.",
141
+ "type": "error"
142
+ },
143
+ {
144
+ "pattern": "context\\.reconnect(\\s)?\\(",
145
+ "message": "Remove references to 'reconnect'. This is not allowed.",
146
+ "type": "error"
147
+ },
148
+ {
149
+ "pattern": "context\\.removeObject(\\s)?\\(",
150
+ "message": "Remove references to 'removeObject'. This is not allowed.",
151
+ "type": "error"
152
+ },
153
+ {
154
+ "pattern": "context\\.removeObjects(\\s)?\\(",
155
+ "message": "Remove references to 'removeObjects'. This is not allowed.",
156
+ "type": "error"
157
+ },
158
+ {
159
+ "pattern": "context\\.rollbackTransaction\\(",
160
+ "message": "Remove references to 'rollbackTransaction'. This is not allowed.",
161
+ "type": "error"
162
+ },
163
+ {
164
+ "pattern": "context\\.runRule(\\s)?\\(",
165
+ "message": "Remove references to 'runRule'. This is not allowed.",
166
+ "type": "error"
167
+ },
168
+ {
169
+ "pattern": "context\\.runScript(\\s)?\\(",
170
+ "message": "Remove references to 'runScript'. This is not allowed.",
171
+ "type": "error"
172
+ },
173
+ {
174
+ "pattern": "context\\.sendEmailNotification(\\s)?\\(",
175
+ "message": "Remove references to 'sendEmailNotification'. This is not allowed.",
176
+ "type": "error"
177
+ },
178
+ {
179
+ "pattern": "TimeZone\\.setTimeZone\\(",
180
+ "message": "Setting TimeZones is not supported.",
181
+ "type": "error"
182
+ },
183
+ {
184
+ "pattern": "identity\\.getLinks(\\s)?\\(",
185
+ "message": "The function 'getLinks' is deprecated. Use an identity search instead.",
186
+ "type": "error"
187
+ },
188
+ {
189
+ "pattern": "^(\\s)?(<Rule)(.*?)(type=)('|\")(ResourceObjectCustomization)('|\")",
190
+ "message": "Unsupported Rule Type: ResourceObjectCustomization rules are not supported, and cannot be submitted.",
191
+ "type": "error"
192
+ },
193
+ {
194
+ "pattern": "^(\\s)?(<Rule)(.*?)(type=)('|\")(Integration)('|\")",
195
+ "message": "Unsupported Rule Type: Integration rules are not supported. Consider implementation of a BeforeProvisioning rule instead.",
196
+ "type": "error"
197
+ },
198
+ {
199
+ "pattern": "^(\\s)?(<Rule)(.*?)(type=)('|\")(?!(IdentityAttribute|AttributeGenerator|AttributeGeneratorFromTemplate|Correlation|ManagerCorrelation|BeforeProvisioning|ConnectorAfterCreate|ConnectorAfterModify|BuildMap|JDBCBuildMap|JDBCProvisioning|SAPBuildMap|SapHrOperationProvisioning|WebServiceBeforeOperation|WebServiceAfterOperation))('|\")",
200
+ "message": "Unsupported Rule Type: This type of rule is not supported. See the IdentityNow Rule Guide for more details on supported rules.",
201
+ "type": "error"
202
+ },
203
+ {
204
+ "pattern": "^(\\s)?(<Rule)(.*?)(type=)('|\")(CertificationExclusion)('|\")",
205
+ "message": "Deprecated Rule Type: CertificationExclusion rules are deprecated. Consider configuration via certification campaign filters instead.",
206
+ "type": "warning"
207
+ },
208
+ {
209
+ "pattern": "^(\\s)?(<Rule)(.*?)(type=)('|\")(IdentitySelector)('|\")",
210
+ "message": "Deprecated Rule Type: IdentitySelector rules are deprecated. Consider configuration via rule assignment criteria instead.",
211
+ "type": "warning"
212
+ },
213
+ {
214
+ "pattern": "(context\\.)(getObjectByName|getObjectById|getObjects|getObject)(.*?)(\\s)?(\\()+(\\s)?(?!((\\s)?(sailpoint\\.object\\.)?(Identity|Link)))",
215
+ "message": "Cannot get objects other than sailpoint.object.Identity or sailpoint.object.Link objects.",
216
+ "type": "error"
217
+ },
218
+ {
219
+ "pattern": "Log4j",
220
+ "message": "Do not declare your own loggers.",
221
+ "type": "error"
222
+ },
223
+ {
224
+ "pattern": "(context\\.search)(\\s)?(\\()+(\\s)?(?!((\\s)?(sailpoint\\.object\\.)?(Identity|Link)))",
225
+ "message": "Only sailpoint.object.Identity or sailpoint.object.Link objects are searchable.",
226
+ "type": "error"
227
+ }
228
+ ]
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: identitynow_rule_validator
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0b
5
+ platform: ruby
6
+ authors:
7
+ - neil-mcglennon-sp
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEYjCCAsqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDDCJuZWls
14
+ Lm1jZ2xlbm5vbi9EQz1zYWlscG9pbnQvREM9Y29tMB4XDTIwMDEyODE3MzYwNloX
15
+ DTIxMDEyNzE3MzYwNlowLTErMCkGA1UEAwwibmVpbC5tY2dsZW5ub24vREM9c2Fp
16
+ bHBvaW50L0RDPWNvbTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKqi
17
+ 9+1E2sipSc7Iju7N6oQT1NNnRzjC0lQYh2w8XyrkNrmBDq3DrZcK08tDHSZDeII3
18
+ pI3wUduamXJ9fLlIp3THv01sB/PZGpcuLsJlxlCnnXrnckFqGoWApgRgtDChn5xk
19
+ CqQshFrk7felCJj95RmhWqgjp/jzRL8djksbxVB4wc3qCBkw2mS6v3Z516gALJrK
20
+ ILXwttgQoXZipvm1GAnfXBOJaXVO1yGt4D7egeNnqLZ8p92vBEI8gwhA4nsw2bgI
21
+ Rm7Y/eeWMuzoNBAXVZnPUB65hrS7kpSpKomWHbV91TzjcKohyjYBj4/1xuIhED31
22
+ jxpoIOOIdzvCxERxPS5ay5+VlTaBXxNsIz12UFUImSMjqLpa6i/SLLwLXO4pyq8q
23
+ 6seUSqpLai6vue7pFFQSgINrpTfw2VxrhF4mSipEwgkQ479e451/tFG1Fw5jJWtz
24
+ o95bJWBBxH8mm8T+z/XUeY0xMyHegAN7cHXfe8wU3z2OLLop3XzB+7P/P8zYdwID
25
+ AQABo4GMMIGJMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQ5225b
26
+ ZgQ6rTZpji087FmAGRc02TAnBgNVHREEIDAegRxuZWlsLm1jZ2xlbm5vbkBzYWls
27
+ cG9pbnQuY29tMCcGA1UdEgQgMB6BHG5laWwubWNnbGVubm9uQHNhaWxwb2ludC5j
28
+ b20wDQYJKoZIhvcNAQELBQADggGBAJgrmpwrIu1WO1r8WL62je6PcJdBjKHux5xU
29
+ D/x3oiSG+qrP2XMKHIHmo1mjQmObWviMVmgU238imT/hcelGbZnkGQ82swAECvZ2
30
+ SEDYx6Dpu0qisI1GliK5m/T7aGhkjxlCxcBa8/eDUwmU55sEXY0Xu1lkq5XoTUwQ
31
+ rEsm8j74ilJOdRf3nla3UUrxGAfWvC/Jul4CTlNt7ADQcMKUiFvkSswY2R+pQWXu
32
+ PKfzNu+y/GU4zwLwfbfPYh9k3s8ynqodBFbwnkh5Q+1CUgYyb//HyOmV5emphaf7
33
+ inuam3RWZl2R2x4o0bOrj277XWJtUoOKgEuV27tmT1TdpAnuaPIrCR/sr7w383aO
34
+ NLKmt0gcTRRt327KOFTls9hByUNR6uEglbaDyErVRECLYOUk19wo6vE9onjaEZTR
35
+ KxiqTPt+66S5Zu9TMeBdYHKYzP8OMs2AwIPrSQH1tGxuGdrjvMvRU3XPxEnuJTwE
36
+ 1Av2VddcX+awmjPuUJVxXSyVzEbPZg==
37
+ -----END CERTIFICATE-----
38
+ date: 2020-01-28 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: bundler
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.16'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.16'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rake
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '10.0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '10.0'
68
+ description: A tool to validate IdentityNow rules.
69
+ email:
70
+ - neil.mcglennon@sailpoint.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/identitynow_rule_validator.rb
76
+ - lib/program.rb
77
+ - lib/rules.json
78
+ homepage: http://www.sailpoint.com
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">"
94
+ - !ruby/object:Gem::Version
95
+ version: 1.3.1
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 2.7.6
99
+ signing_key:
100
+ specification_version: 4
101
+ summary: IdentityNow Rule Validator
102
+ test_files: []
metadata.gz.sig ADDED
Binary file