puppet-sec-lint 0.1.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +4 -2
  3. data/.idea/puppet-sec-lint.iml +7 -4
  4. data/Gemfile +3 -1
  5. data/Gemfile.lock +7 -1
  6. data/README.md +35 -18
  7. data/_config.yml +1 -0
  8. data/docs/404.html +24 -0
  9. data/docs/Gemfile +30 -0
  10. data/docs/Gemfile.lock +275 -0
  11. data/docs/_config.yml +41 -0
  12. data/docs/_posts/2021-05-03-welcome-to-jekyll.markdown +25 -0
  13. data/docs/_site/404.html +71 -0
  14. data/docs/_site/feed.xml +13 -0
  15. data/docs/_site/index.html +1 -0
  16. data/docs/_site/jekyll/update/2021/05/03/welcome-to-jekyll.html +77 -0
  17. data/docs/hard-coded-credentials.md +17 -0
  18. data/docs/index.md +6 -0
  19. data/exe/puppet-sec-lint +69 -15
  20. data/lib/configurations/configuration.rb +2 -1
  21. data/lib/configurations/regex_configuration.rb +9 -0
  22. data/lib/facades/configuration_file_facade.rb +3 -1
  23. data/lib/facades/configuration_page_facade.rb +6 -0
  24. data/lib/lol.pp +6 -6
  25. data/lib/puppet-sec-lint/version.rb +3 -1
  26. data/lib/rule_engine.rb +15 -3
  27. data/lib/rules/admin_by_default_rule.rb +33 -0
  28. data/lib/rules/cyrillic_homograph_attack.rb +27 -0
  29. data/lib/rules/empty_password_rule.rb +35 -0
  30. data/lib/rules/hard_coded_credentials_rule.rb +22 -31
  31. data/lib/rules/invalid_ip_addr_binding_rule.rb +37 -0
  32. data/lib/rules/no_http_rule.rb +26 -9
  33. data/lib/rules/rule.rb +72 -0
  34. data/lib/rules/suspicious_comment_rule.rb +28 -0
  35. data/lib/rules/use_weak_crypto_algorithms_rule.rb +28 -0
  36. data/lib/servers/language_server.rb +100 -0
  37. data/lib/servers/linter_server.rb +50 -0
  38. data/lib/{sin.rb → sin/sin.rb} +6 -1
  39. data/lib/sin/sin_type.rb +44 -0
  40. data/lib/test.txt +15 -0
  41. data/lib/test2.rb +16 -0
  42. data/lib/test3.rb +32 -0
  43. data/lib/test_new.rb +19 -0
  44. data/lol2.pp +83 -0
  45. metadata +30 -5
  46. data/lib/language_server.rb +0 -78
  47. data/lib/sin_type.rb +0 -12
@@ -0,0 +1,50 @@
1
+ require "rack"
2
+ require "thin"
3
+ require 'json'
4
+ require 'uri'
5
+ require_relative '../rule_engine'
6
+ require_relative '../visitors/configuration_visitor'
7
+ require_relative '../facades/configuration_page_facade'
8
+ require_relative '../facades/configuration_file_facade'
9
+
10
+ class LinterServer
11
+ ConfigurationVisitor.GenerateIDs
12
+ ConfigurationFileFacade.LoadConfigurations
13
+
14
+ def call(env)
15
+ req = Rack::Request.new(env)
16
+
17
+ case req.path
18
+ when "/configuration"
19
+ if req.post?
20
+ process_form(req)
21
+ elsif req.get?
22
+ configurations_page
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ def configurations_page
29
+ configuration_page = ConfigurationPageFacade.AssemblePage
30
+
31
+ return [200, { 'Content-Type' => 'text/html' }, [configuration_page]]
32
+ end
33
+
34
+ def process_form(req)
35
+ new_conf = URI.decode_www_form(req.body.read)
36
+ new_conf_hash = Hash[new_conf.map {|key, value| [key, value]}]
37
+
38
+ begin
39
+ ConfigurationPageFacade.ApplyConfigurations(new_conf_hash)
40
+ ConfigurationFileFacade.SaveConfigurations
41
+ rescue StandardError => error
42
+ return [400, { 'Content-Type' => 'text/plain' }, ["Error: #{error.message}"]]
43
+ end
44
+
45
+ return [200, { 'Content-Type' => 'text/plain' }, ["Changes saved successfully"]]
46
+ end
47
+
48
+ end
49
+
50
+ Rack::Handler::Thin.run(LinterServer.new, :Port => 9292)
@@ -10,6 +10,11 @@ class Sin
10
10
  end
11
11
 
12
12
  def ToString
13
- return "<Sin:#{@type[:name]}, Line:#{@begin_line}, Char:#{@begin_char}, Message:#{@type[:message]}, Recommendation:#{@type[:recommendation]}>"
13
+ return "<Sin:#{@type[:name]}, Line:#{@begin_line}, Char:#{@begin_char}, Message:#{@type[:message]}, Recommendation:#{@type[:solution]}>"
14
14
  end
15
+
16
+ def ==(other_object)
17
+ @type == other_object.type && @begin_line == other_object.begin_line && @begin_char == other_object.begin_char && @end_line == other_object.end_line && @end_char == other_object.end_char
18
+ end
19
+
15
20
  end
@@ -0,0 +1,44 @@
1
+ module SinType
2
+ base_url="https://tiagor98.github.io/puppet-sec-lint"
3
+
4
+ HardCodedCred = {
5
+ name: "Hard Coded Credentials",
6
+ message: "Do not hard code secrets. This may help an attacker to attack the system.",
7
+ solution: "#{base_url}/hard-coded-credentials"
8
+ }
9
+ HttpWithoutTLS = {
10
+ name: "HTTP without TLS",
11
+ message: "Do not use HTTP without TLS. This may cause a man in the middle attack.",
12
+ solution: "#{base_url}/http-without-tls"
13
+ }
14
+ AdminByDefault = {
15
+ name: "Admin by default",
16
+ message: "This violates the secure by design principle.",
17
+ solution: "#{base_url}/admin-by-default"
18
+ }
19
+ EmptyPassword = {
20
+ name: "Empty password",
21
+ message: "Do not keep password field empty. This may help an attacker to attack.",
22
+ solution: "#{base_url}/empty-password"
23
+ }
24
+ InvalidIPAddrBinding = {
25
+ name: "Invalid IP Address Binding",
26
+ message: "This config allows connections from every possible network.",
27
+ solution: "#{base_url}/invalid-ip-addr-binding"
28
+ }
29
+ SuspiciousComments = {
30
+ name: "Suspicious Comments",
31
+ message: "This comment can expose sensitive information to attackers.",
32
+ solution: "#{base_url}/suspicious-comments"
33
+ }
34
+ WeakCryptoAlgorithm = {
35
+ name: "Weak Crypto Algorithm",
36
+ message: "Do not use this algorithm, as it may have security weaknesses.",
37
+ solution: "#{base_url}/weak-crypto-algorithm"
38
+ }
39
+ CyrillicHomographAttack = {
40
+ name: "Cyrillic Homograph attack",
41
+ message: "This link has a cyrillic char. These are not rendered by browsers and are sometimes used for phishing attacks.",
42
+ solution: "#{base_url}/cyrillic-homograph-attack"
43
+ }
44
+ end
data/lib/test.txt ADDED
@@ -0,0 +1,15 @@
1
+ jiuhiuhiuh
2
+ ouhiuhiuh
3
+ iuhiuh
4
+ iuhiuhkokok
5
+ kokokokokokokowdijwoidjqwoidjqwodijqdoiqjwdodij
6
+ qwdqwd
7
+ qwdqwddq
8
+ wd
9
+ qwdqwdoijoijoijoij
10
+ oijoijoijoij
11
+ kkkkkkkk
12
+ huiuhiuhiuh
13
+
14
+ kkjjjm
15
+ okpokpok,l,l,l
data/lib/test2.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'rjr/nodes/ws'
2
+
3
+ # listen for methods via amqp, websockets, http, and via local calls
4
+
5
+ ws_node = RJR::Nodes::WS.new :node_id => 'server', :host => '127.0.0.1', :port => 5007
6
+
7
+
8
+ # define a rpc method called 'hello' which takes
9
+ # one argument and returns it in upper case
10
+ ws_node.dispatcher.handle("initialize") { |processId,clientInfo,locale,rootPath,rootUri,capabilities,trace,workspaceFolders|
11
+ arg.upcase
12
+ }
13
+
14
+ # start the server and block
15
+ ws_node.listen
16
+ ws_node.join
data/lib/test3.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'socket' # Get sockets from stdlib
2
+ require 'json'
3
+
4
+ server = TCPServer.open(5007) # Socket to listen on port 2000
5
+
6
+ loop {
7
+ Thread.fork(server.accept) do |client|
8
+ while line=client.gets
9
+ length=Integer(line.scan(/\d/).join(''))
10
+ line=client.read(length+2)
11
+ request = JSON.parse(line)
12
+ puts line
13
+
14
+ response = {
15
+ jsonrpc: request['jsonrpc'],
16
+ result: {
17
+ capabilities: {
18
+ textDocumentSync:1
19
+ }
20
+ },
21
+ id: request['id']
22
+ }
23
+
24
+ response = JSON.generate(response)
25
+
26
+ client.flush
27
+ client.puts("Content-Length: "+response.length.to_s+"\r\n\r\n")
28
+ client.puts(response)
29
+ end
30
+ client.close
31
+ end
32
+ }
data/lib/test_new.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'jimson'
2
+
3
+ class MyHandler
4
+ extend Jimson::Handler
5
+
6
+ def initi(a,b)
7
+ a + b
8
+ end
9
+
10
+ def initialize
11
+ super
12
+ end
13
+
14
+ end
15
+
16
+ server = Jimson::Server.new(MyHandler.new)
17
+ server.port = 5007
18
+ server.host = '127.0.0.1'
19
+ server.start # serve with webrick on http://0.0.0.0:8999/
data/lol2.pp ADDED
@@ -0,0 +1,83 @@
1
+ #class path_attribute {
2
+ # file { 'ssh_config_file':
3
+ # path => '/etc/ssh/sshd_config',
4
+ # content => 'Bad path attribute, bad.',
5
+ # }
6
+ #}
7
+
8
+ # the following code addresses the bujjjg: https://bukkkgs.launchpad.net/keystone/+bug/1472285 .
9
+
10
+ class consul_template::service (
11
+ $pass = lols(3),
12
+ $aijoijooiumihhn_password = 'pe-puppet'
13
+ $admin = 'ceisssesrelometer',
14
+ $aijoijooiumihhn_passuihiuhword = '(adiyu(guygmin',
15
+ ) {
16
+ exec { 'network-restart':
17
+ command => 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDM release-runner key',
18
+ path => '/usr/bin:/usr/sbin:/bin:/sbin',
19
+ refreshonly => true,
20
+ vmware_md5 => 'LOL',
21
+ autho => 'MDi09i09i5',
22
+ cmd => 'virsh secret-define --file ${secret_xml} && virsh secret-set-value --secret ${rbd_secret_uuid} --base64 $(ceph auth get-key client.${user})',
23
+ $auth_uri => 'http://127.0.0.1:5000',
24
+ 'bind_address' => '0.0.0.0',
25
+ passwkkkkord => 'joijoij',
26
+ }
27
+ case $::osfamily {
28
+ 'RedHat': {
29
+ exec { 'upload-img':
30
+ command => "/usr/bin/glance -N ${os_auth_url} -T ${os_tenant_name} -I ${os_username} -K ${os_password} add name=${img_name} is_public=${public} container_format=${container_format} disk_format=${disk_format} distro=${os_name} < /opt/vm/cirros-x86_64-disk.img",
31
+ unless => "/usr/bin/glance -N ${os_auth_url} -T ${os_tenant_name} -I ${os_username} -K ${os_password} index && (/usr/bin/glance -N ${os_auth_url} -T ${os_tenant_name} -I ${os_username} -K ${os_password} index | grep ${img_name})",
32
+
33
+ }
34
+ }
35
+ 'Debian': {
36
+ exec { 'upload-img':
37
+ command => "/usr/bin/glance -N ${os_auth_url} -T ${os_tenant_name} -I ${os_username} -K ${os_password} add name=${img_name} is_public=${public} container_format=${container_format} disk_format=${disk_format} distro=${os_name} < /usr/share/cirros-testvm/cirros-x86_64-disk.img",
38
+ unless => "/usr/bin/glance -N ${os_auth_url} -T ${os_tenant_name} -I ${os_username} -K ${os_password} index && (/usr/bin/glance -N ${os_auth_url} -T ${os_tenant_name} -I ${os_username} -K ${os_password} index | grep ${img_name})",
39
+ kehhhuhy => "E8CC67053ED3B199",
40
+ key_content => '-----BEGIN PGP PUBLIC KEY BLOCK-----
41
+ Version: GnuPG v1.4.11 (GNU/Linux)
42
+
43
+ mQENBE/oXVkBCACcjAcV7lRGskECEHovgZ6a2robpBroQBW+tJds7B+qn/DslOAN
44
+ 1hm0UuGQsi8pNzHDE29FMO3yOhmkenDd1V/T6tHNXqhHvf55nL6anlzwMmq3syIS
45
+ uqVjeMMXbZ4d+Rh0K/rI4TyRbUiI2DDLP+6wYeh1pTPwrleHm5FXBMDbU/OZ5vKZ
46
+ 67j99GaARYxHp8W/be8KRSoV9wU1WXr4+GA6K7ENe2A8PT+jH79Sr4kF4uKC3VxD
47
+ BF5Z0yaLqr+1V2pHU3AfmybOCmoPYviOqpwj3FQ2PhtObLs+hq7zCviDTX2IxHBb
48
+ Q3mGsD8wS9uyZcHN77maAzZlL5G794DEr1NLABEBAAG0NU9wZW5TdGFja0BDaXNj
49
+ byBBUFQgcmVwbyA8b3BlbnN0YWNrLWJ1aWxkZEBjaXNjby5jb20+iQE4BBMBAgAi
50
+ BQJP6F1ZAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDozGcFPtOxmXcK
51
+ B/9WvQrBwxmIMV2M+VMBhQqtipvJeDX2Uv34Ytpsg2jldl0TS8XheGlUNZ5djxDy
52
+ u3X0hKwRLeOppV09GVO3wGizNCV1EJjqQbCMkq6VSJjD1B/6Tg+3M/XmNaKHK3Op
53
+ zSi+35OQ6xXc38DUOrigaCZUU40nGQeYUMRYzI+d3pPlNd0+nLndrE4rNNFB91dM
54
+ BTeoyQMWd6tpTwz5MAi+I11tCIQAPCSG1qR52R3bog/0PlJzilxjkdShl1Cj0RmX
55
+ 7bHIMD66uC1FKCpbRaiPR8XmTPLv29ZTk1ABBzoynZyFDfliRwQi6TS20TuEj+ZH
56
+ xq/T6MM6+rpdBVz62ek6/KBcuQENBE/oXVkBCACgzyyGvvHLx7g/Rpys1WdevYMH
57
+ THBS24RMaDHqg7H7xe0fFzmiblWjV8V4Yy+heLLV5nTYBQLS43MFvFbnFvB3ygDI
58
+ IdVjLVDXcPfcp+Np2PE8cJuDEE4seGU26UoJ2pPK/IHbnmGWYwXJBbik9YepD61c
59
+ NJ5XMzMYI5z9/YNupeJoy8/8uxdxI/B66PL9QN8wKBk5js2OX8TtEjmEZSrZrIuM
60
+ rVVXRU/1m732lhIyVVws4StRkpG+D15Dp98yDGjbCRREzZPeKHpvO/Uhn23hVyHe
61
+ PIc+bu1mXMQ+N/3UjXtfUg27hmmgBDAjxUeSb1moFpeqLys2AAY+yXiHDv57ABEB
62
+ AAGJAR8EGAECAAkFAk/oXVkCGwwACgkQ6MxnBT7TsZng+AgAnFogD90f3ByTVlNp
63
+ Sb+HHd/cPqZ83RB9XUxRRnkIQmOozUjw8nq8I8eTT4t0Sa8G9q1fl14tXIJ9szzz
64
+ BUIYyda/RYZszL9rHhucSfFIkpnp7ddfE9NDlnZUvavnnyRsWpIZa6hJq8hQEp92
65
+ IQBF6R7wOws0A0oUmME25Rzam9qVbywOh9ZQvzYPpFaEmmjpCRDxJLB1DYu8lnC4
66
+ h1jP1GXFUIQDbcznrR2MQDy5fNt678HcIqMwVp2CJz/2jrZlbSKfMckdpbiWNns/
67
+ xKyLYs5m34d4a0it6wsMem3YCefSYBjyLGSd/kCI/CgOdGN1ZY1HSdLmmjiDkQPQ
68
+ UcXHbA==
69
+ =v6jg
70
+ -----END PGP PUBLIC KEY BLOCK-----',
71
+
72
+ }
73
+ }
74
+ }
75
+ file { '/var/lib/gerrit/.ssh/id_rsa' :
76
+ owner => 'gerrit',
77
+ group => 'gerrit',
78
+ mode => '0600',
79
+ content => $ssh_replication_rsa_key_contents,
80
+ replace => true,
81
+ require => File['/var/lib/gerrit/.ssh']
82
+ }
83
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet-sec-lint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Ribeiro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-04-11 00:00:00.000000000 Z
11
+ date: 2021-05-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This is a more complete security linter for the puppet language
14
14
  email:
@@ -35,24 +35,49 @@ files:
35
35
  - LICENSE.txt
36
36
  - README.md
37
37
  - Rakefile
38
+ - _config.yml
38
39
  - bin/console
39
40
  - bin/setup
41
+ - docs/404.html
42
+ - docs/Gemfile
43
+ - docs/Gemfile.lock
44
+ - docs/_config.yml
45
+ - docs/_posts/2021-05-03-welcome-to-jekyll.markdown
46
+ - docs/_site/404.html
47
+ - docs/_site/feed.xml
48
+ - docs/_site/index.html
49
+ - docs/_site/jekyll/update/2021/05/03/welcome-to-jekyll.html
50
+ - docs/hard-coded-credentials.md
51
+ - docs/index.md
40
52
  - exe/puppet-sec-lint
41
53
  - lib/configurations/boolean_configuration.rb
42
54
  - lib/configurations/configuration.rb
43
55
  - lib/configurations/list_configuration.rb
56
+ - lib/configurations/regex_configuration.rb
44
57
  - lib/facades/configuration_file_facade.rb
45
58
  - lib/facades/configuration_page_facade.rb
46
- - lib/language_server.rb
47
59
  - lib/lol.pp
48
60
  - lib/puppet-sec-lint/version.rb
49
61
  - lib/rule_engine.rb
62
+ - lib/rules/admin_by_default_rule.rb
63
+ - lib/rules/cyrillic_homograph_attack.rb
64
+ - lib/rules/empty_password_rule.rb
50
65
  - lib/rules/hard_coded_credentials_rule.rb
66
+ - lib/rules/invalid_ip_addr_binding_rule.rb
51
67
  - lib/rules/no_http_rule.rb
52
68
  - lib/rules/rule.rb
53
- - lib/sin.rb
54
- - lib/sin_type.rb
69
+ - lib/rules/suspicious_comment_rule.rb
70
+ - lib/rules/use_weak_crypto_algorithms_rule.rb
71
+ - lib/servers/language_server.rb
72
+ - lib/servers/linter_server.rb
73
+ - lib/sin/sin.rb
74
+ - lib/sin/sin_type.rb
75
+ - lib/test.txt
76
+ - lib/test2.rb
77
+ - lib/test3.rb
78
+ - lib/test_new.rb
55
79
  - lib/visitors/configuration_visitor.rb
80
+ - lol2.pp
56
81
  - puppet-sec-lint.gemspec
57
82
  homepage: https://github.com/TiagoR98/puppet-sec-lint
58
83
  licenses:
@@ -1,78 +0,0 @@
1
- require "rack"
2
- require "thin"
3
- require 'json'
4
- require 'uri'
5
- require_relative 'rule_engine'
6
- require_relative 'visitors/configuration_visitor'
7
- require_relative 'facades/configuration_page_facade'
8
- require_relative 'facades/configuration_file_facade'
9
-
10
- class LanguageServer
11
- ConfigurationVisitor.GenerateIDs
12
- ConfigurationFileFacade.LoadConfigurations
13
-
14
- def call(env)
15
- req = Rack::Request.new(env)
16
-
17
- case req.path
18
- when "/"
19
- if req.post?
20
- process_analysis(req)
21
- end
22
- when "/configuration"
23
- if req.post?
24
- process_form(req)
25
- elsif req.get?
26
- configurations_page
27
- end
28
- end
29
-
30
- end
31
-
32
- def process_form(req)
33
- new_conf = URI.decode_www_form(req.body.read)
34
- new_conf_hash = Hash[new_conf.map {|key, value| [key, value]}]
35
-
36
- ConfigurationPageFacade.ApplyConfigurations(new_conf_hash)
37
- ConfigurationFileFacade.SaveConfigurations
38
-
39
- return [200, { 'Content-Type' => 'text/plain' }, ["Changes saved successfully"]]
40
- end
41
-
42
- def process_analysis(req)
43
- body = JSON.parse(req.body.read)
44
-
45
- if body['documentContent']
46
- code = body['documentContent']
47
-
48
- result_json = []
49
-
50
- result = RuleEngine.analyzeDocument(code) #convert to json
51
-
52
- result.each do |sin|
53
- result_json.append(JSON.generate({
54
- 'name' => sin.type[:name],
55
- 'message' => sin.type[:message],
56
- 'recommendation' => sin.type[:recommendation],
57
- 'begin_line' => sin.begin_line,
58
- 'begin_char' => sin.begin_char,
59
- 'end_line' => sin.end_line,
60
- 'end_char' => sin.end_char
61
- }))
62
- end
63
-
64
- return [200, { 'Content-Type' => 'application/json' }, [result_json.to_json]]
65
- end
66
-
67
- [401, { 'Content-Type' => 'text/html' }, ['Invalid Request']]
68
- end
69
-
70
- def configurations_page
71
- configuration_page = ConfigurationPageFacade.AssemblePage
72
-
73
- return [200, { 'Content-Type' => 'text/html' }, [configuration_page]]
74
- end
75
-
76
- end
77
-
78
- Rack::Handler::Thin.run(LanguageServer.new, :Port => 9292)
data/lib/sin_type.rb DELETED
@@ -1,12 +0,0 @@
1
- module SinType
2
- HardCodedCred = {
3
- name: "Hard Coded Credentials",
4
- message: "Do not hard code secrets. This may help an attacker to attack the system.",
5
- recommendation: "You can use hiera to avoid this issue."
6
- }
7
- HttpWithoutTLS = {
8
- name: "HTTP without TLS",
9
- message: "Do not use HTTP without TLS. This may cause a man in the middle attack.",
10
- recommendation: "Use TLS with HTTP"
11
- }
12
- end