|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +# This is a simple script meant to retrieve the latest rubygem (provided through environment variables) and perform a |
| 4 | +# Rusty Hog scan on the contents of the download. It will then post the results to Insights. |
| 5 | + |
| 6 | +import os |
| 7 | +import feedparser |
| 8 | +import gzip |
| 9 | +import re |
| 10 | +import requests |
| 11 | +import tempfile |
| 12 | +import sys |
| 13 | +import subprocess |
| 14 | +import json |
| 15 | +import logging |
| 16 | + |
| 17 | +loglevel = "WARNING" |
| 18 | +for arg in sys.argv: |
| 19 | + if arg.startswith("--log="): |
| 20 | + loglevel = arg[6:] |
| 21 | + |
| 22 | +numeric_level = getattr(logging, loglevel.upper(), None) |
| 23 | +if not isinstance(numeric_level, int): |
| 24 | + raise ValueError('Invalid log level: %s' % loglevel) |
| 25 | +logging.basicConfig(level=numeric_level) |
| 26 | + |
| 27 | +# initialize auth tokens, fail if not present |
| 28 | +RUBYGEM_NAME = os.environ["RUBYGEM_NAME"] |
| 29 | +INSIGHTS_INSERT_KEY = os.environ["INSIGHTS_INSERT_KEY"] |
| 30 | +INSIGHTS_ACCT_ID = os.environ["INSIGHTS_ACCT_ID"] |
| 31 | +DUROC_HOG_PATH = os.environ["DUROC_HOG_PATH"] |
| 32 | + |
| 33 | +feed_result = feedparser.parse(f"https://rubygems.org/gems/{RUBYGEM_NAME}/versions.atom") |
| 34 | +latest_gem = feed_result['entries'][0]['title'] |
| 35 | +title_regex = re.compile("(.*)\s+\(([0-9\.]+)\)") |
| 36 | +(gem_title, gem_version) = title_regex.match(latest_gem).groups() |
| 37 | + |
| 38 | +url = f"https://rubygems.org/downloads/{gem_title}-{gem_version}.gem" |
| 39 | +r = requests.get(url) |
| 40 | +tempdir = tempfile.gettempdir() |
| 41 | +tempfile = os.path.join(tempdir, f"{gem_title}-{gem_version}.gem") |
| 42 | +f = open(tempfile, "wb") |
| 43 | +f.write(r.content) |
| 44 | +f.close() |
| 45 | + |
| 46 | +duroc_hog_output = subprocess.run([DUROC_HOG_PATH, '-z', tempfile], capture_output=True, check=True) |
| 47 | +json_output = json.loads(duroc_hog_output.stdout) |
| 48 | +os.remove(tempfile) |
| 49 | + |
| 50 | +output_array = [] |
| 51 | +for finding in json_output: |
| 52 | + output_array.append({ |
| 53 | + 'eventType': "rubyagent_secret_monitor", |
| 54 | + "reason": finding["reason"], |
| 55 | + "path": finding["path"], |
| 56 | + 'url': url, |
| 57 | + 'gem_title': gem_title, |
| 58 | + 'gem_version': gem_version |
| 59 | + }) |
| 60 | + |
| 61 | +url = "https://insights-collector.newrelic.com/v1/accounts/{INSIGHTS_ACCT_ID}/events" |
| 62 | +headers = { |
| 63 | + "Content-Type": "application/json", |
| 64 | + "X-Insert-Key": INSIGHTS_INSERT_KEY, |
| 65 | + "Content-Encoding": "gzip", |
| 66 | +} |
| 67 | +post = gzip.compress(json.dumps(output_array).encode("utf-8")) |
| 68 | +logging.info(f"len(output_array) = {len(output_array)}") |
| 69 | +logging.debug(output_array) |
| 70 | +logging.info("Submitting data to New Relic Insights...") |
| 71 | +r = requests.post(url, data=post, headers=headers) |
| 72 | +logging.info(f"insights status code: {r.status_code}") |
| 73 | + |
| 74 | + |
0 commit comments