class PuppetSneakernet
Public Instance Methods
check_size_limit!()
click to toggle source
# File lib/puppet-sneakernet.rb, line 77 def check_size_limit! content = request.body.read request.body.rewind if content.size > MAXSIZE halt 400, "Submitted code size is #{content.size}, which is larger than the maximum size of #{MAXSIZE}." end end
csrf_safe!()
click to toggle source
# File lib/puppet-sneakernet.rb, line 63 def csrf_safe! return true unless settings.csrf if session[:csrf] == params['_csrf'] && session[:csrf] == request.cookies['authenticity_token'] true else logger.warn 'CSRF attempt detected. Ensure that server time is correct.' logger.debug "session: #{session[:csrf]}" logger.debug " param: #{params['_csrf']}" logger.debug " cookie: #{request.cookies['authenticity_token']}" halt 403, 'Request validation failed.' end end
pack_puppetfile()
click to toggle source
# File lib/puppet-sneakernet.rb, line 97 def pack_puppetfile begin # Parse the Puppetfile into an object model puppetfile = ::PuppetfileResolver::Puppetfile::Parser::R10KEval.parse(params['code']) rescue PuppetfileResolver::Puppetfile::Parser::ParserError => e logger.error 'Syntax error in Puppetfile' halt 400, "Syntax error in Puppetfile: #{e.message}" end # Make sure the Puppetfile is valid unless puppetfile.valid? logger.error 'Puppetfile is not valid' puppetfile.validation_errors.each { |err| logger.warn err } halt 400, 'Puppetfile is not valid' end resolver = PuppetfileResolver::Resolver.new(puppetfile, nil) result = resolver.resolve(strict_mode: true) result.validation_errors.each { |err| logger.warn "Dependency resolution: #{err}"} unless result.dependency_graph.count > 0 logger.warn 'No modules resolved!' halt 400, 'No modules resolved, press back and try again.' end buffer = StringIO.new tmpdir = Dir.mktmpdir Dir.mktmpdir('sneakernet') do |dir| Dir.chdir(dir) do Dir.mkdir('modules') File.open('Puppetfile', "w+") do |puppetfile| result.dependency_graph.each do |dep| mod = dep.payload next unless mod.is_a? PuppetfileResolver::Models::ModuleSpecification # record the module we're downloading puppetfile.write "mod '#{dep.payload.owner}-#{dep.payload.name}', '#{dep.payload.version}'\n" release_slug = "#{dep.payload.owner}-#{dep.payload.name}-#{dep.payload.version}" release_tarball = release_slug + ".tar.gz" destination = "modules/#{dep.payload.name}" logger.debug "Retrieving #{release_slug}" begin release = PuppetForge::Release.find(release_slug) release.download(Pathname(release_tarball)) release.verify(Pathname(release_tarball)) PuppetForge::Unpacker.unpack(release_tarball, destination, tmpdir) FileUtils.rm(release_tarball) rescue Faraday::BadRequestError logger.error "Error retrieving #{release_slug}" halt 400, "Error retrieving #{release_slug}" end end end Minitar.pack('.', Zlib::GzipWriter.new(buffer)) end end FileUtils.rm_rf(tmpdir) attachment("Puppetfile.packed.#{Date.today}.tar.gz") buffer.string end
sanitize_code!()
click to toggle source
# File lib/puppet-sneakernet.rb, line 86 def sanitize_code! variants = [:command, :call, :fcall, :vcall] tokens = Ripper.sexp(params['code']).flatten indices = tokens.map.with_index { |a, i| variants.include?(a) ? i : nil }.compact methods = indices.map { |i| tokens[i + 2] }.flatten.compact methods.reject! { |name| ['mod', 'forge', 'moduledir'].include? name } halt 400, "Arbitrary Ruby code is not supported. Please remove '#{methods.join(', ')}' and try again." unless methods.empty? end
validate_request!()
click to toggle source
# File lib/puppet-sneakernet.rb, line 58 def validate_request! csrf_safe! check_size_limit! end