roboscott 0.0.1

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 (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/roboscott +55 -0
  3. data/lib/roboscott.rb +144 -0
  4. metadata +46 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5c681267a2332eebb783cce94b68ceb1757f5cc8
4
+ data.tar.gz: 8d3cb169844fa3afbcbfa5f0b4a606c141043d44
5
+ SHA512:
6
+ metadata.gz: 08c304cccbd1c4d19eadf8870463811acd1891e1636b4ddf7c4c35b2346df0f35af9ac8fd87edfa86e6e83dd179679b9a47489c303647ccad4aabee69d687953
7
+ data.tar.gz: 205c6ff996af23354b5939ac5df33950b04afd12e8469f6e28655acc8f20198551ce3050181ae9edd3f6aa6e734a8027146ca24962e6fbc3d985094372455dcc
data/bin/roboscott ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'getoptlong'
4
+ require 'yaml'
5
+
6
+ begin
7
+ require 'roboscott'
8
+ rescue LoadError
9
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
10
+ require 'roboscott'
11
+ end
12
+
13
+ opts = GetoptLong.new(
14
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
15
+ [ '--unredacted', '-u', GetoptLong::NO_ARGUMENT ]
16
+ )
17
+
18
+ config = {}
19
+
20
+ opts.each do |opt, arg|
21
+ case opt
22
+ when '--help'
23
+ puts <<-EOF
24
+ roboscott [OPTION] ... <DIR|Files>
25
+
26
+ -h, --help:
27
+ show help
28
+
29
+ -u, --unredacted:
30
+ log all found suspicious passwords to the console
31
+
32
+ DIR|Files: The directory or files to parse
33
+ EOF
34
+ when '--unredacted'
35
+ puts 'Running in unredacted mode'
36
+ config[:unredacted] = true
37
+ end
38
+ end
39
+
40
+ if ARGV.length < 1
41
+ puts "Missing dir argument. Running on current directory (try --help if this isn't intendted)"
42
+ dir = ['.']
43
+ else
44
+ dir = ARGV
45
+ end
46
+
47
+ failed = 0
48
+
49
+ # Okay, enough setting up, let's check some files
50
+ ARGV.each do|file|
51
+ lint = RoboScott.new(file, config)
52
+ failed = failed + lint.do_lint
53
+ end
54
+
55
+ exit failed
data/lib/roboscott.rb ADDED
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+
5
+ module Logging
6
+ ESCAPES = { :green => "\033[32m",
7
+ :yellow => "\033[33m",
8
+ :red => "\033[31m",
9
+ :reset => "\033[0m" }
10
+
11
+ def error(message)
12
+ emit(:message => message, :color => :red)
13
+ end
14
+
15
+ def emit(opts={})
16
+ color = opts[:color]
17
+ message = opts[:message]
18
+ print ESCAPES[color]
19
+ print message
20
+ print ESCAPES[:reset]
21
+ print "\n"
22
+ end
23
+ end
24
+
25
+ class RoboScott
26
+ include Logging
27
+
28
+ def initialize(file, config={})
29
+ @file = file
30
+ @config = config
31
+ end
32
+
33
+ def do_lint
34
+ unless File.exists? @file
35
+ error "File #{@file} does not exist"
36
+ return 0
37
+ else
38
+ if File.directory? @file
39
+ return self.parse_directory @file
40
+ else
41
+ return self.parse_file @file
42
+ end
43
+ end
44
+ end
45
+
46
+ def parse_directory(directory)
47
+ Dir.glob("#{directory}/*").inject(0) do |mem, fdir|
48
+ if File.directory? fdir
49
+ mem + parse_directory(fdir)
50
+ else
51
+ mem + parse_file(fdir)
52
+ end
53
+ end
54
+ end
55
+
56
+ def parse_file(file)
57
+ if (not File.extname(file) =~ /.(yaml|yml)$/) && (not @config[:nocheckfileext])
58
+ # Instead of logging an error, just silently move on. Helps us scan a repo
59
+ return 1
60
+ end
61
+ begin
62
+ yaml = YAML.load_file(file)
63
+ rescue Exception => err
64
+ # Not a yaml file, move on, nothing to see here
65
+ return 1
66
+ else
67
+ traverse(file, yaml ) do |node|
68
+ #puts node
69
+ end
70
+ return 0
71
+ end
72
+ end
73
+
74
+ def has_keys?(yaml)
75
+ has_fails = false
76
+ yaml.each do |key, value|
77
+ puts "Key: #{key}"
78
+ if key_looks_important?(key) and value_looks_sensitive?(value)
79
+ has_fails = true
80
+ report_fail(key, value)
81
+ end
82
+ end
83
+ return has_fails
84
+ end
85
+
86
+ def key_looks_important?(key)
87
+ if key.class != String
88
+ return false
89
+ end
90
+
91
+ # TODO - move bad_words to a config value
92
+ bad_words = ['SECRET', 'TOKEN', 'PASSWORD', 'KEY']
93
+ bad_words.each do |baddy|
94
+ if key.upcase.include? baddy
95
+ return true
96
+ end
97
+ end
98
+ return false
99
+ end
100
+
101
+ def value_looks_sensitive?(val)
102
+ if val == nil or val == ''
103
+ return false
104
+ end
105
+
106
+ # TODO - move okay_vals to a config value
107
+ okay_vals = ['ENV', 'DUMMY']
108
+ okay_vals.each do |ok|
109
+ if val.upcase.include? ok
110
+ return false
111
+ end
112
+ end
113
+ rescue
114
+ return false
115
+ return true
116
+ end
117
+
118
+ def report_fail(file, key, value, redacted=true)
119
+ value = 'REDACTED' unless @config[:unredacted]
120
+
121
+ error "File #{file} - The value '#{value}' for key '#{key}' looks sensitive"
122
+ end
123
+
124
+ def traverse(filename, obj, &blk)
125
+ case obj
126
+ when Hash
127
+ obj.each {|key, val|
128
+ if val.class == Hash
129
+ traverse(filename, val, &blk)
130
+ else
131
+ # In this case the value should be a leaf node (not another hash)
132
+ if key_looks_important?(key) and value_looks_sensitive?(val)
133
+ has_fails = true
134
+ report_fail(filename, key, val)
135
+ end
136
+ end
137
+ }
138
+ when Array
139
+ obj.each {|v| traverse(filename, v, &blk) }
140
+ else
141
+ blk.call(obj)
142
+ end
143
+ end
144
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: roboscott
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Elliot Rushton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-20 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Check if YAML files contain secrets that should be in ENV
14
+ email: elliot.rushton@gmail.com
15
+ executables:
16
+ - roboscott
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/roboscott
21
+ - lib/roboscott.rb
22
+ homepage: https://github.com/elliotrushton/roboscott
23
+ licenses:
24
+ - MIT
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 2.4.5.1
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: Simple secret linter
46
+ test_files: []