| #!/usr/bin/env python |
| |
| # Copyright 2018 Google LLC. |
| # |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| |
| """Search the syslog on a jumphost to determine when auth tokens changed.""" |
| |
| |
| from __future__ import print_function |
| import sys |
| |
| |
| SYSLOG = '/var/log/syslog' |
| |
| INCLUDE_LINES = [ |
| # (process-name, pattern) |
| ('metadata-server', 'Updated token: '), |
| ('metadata-server', 'Token requested by '), |
| ('get-oauth2-token', 'Wrote new auth token: '), |
| ] |
| |
| |
| def transform_line(line): |
| """Trim the log line and return it iff it matches INCLUDE_LINES.""" |
| for proc, pattern in INCLUDE_LINES: |
| if pattern in line: |
| # Log lines look like this: |
| # pylint: disable=line-too-long |
| # Mar 12 09:58:43 jumphost-win-02 metadata-server[5259]: I0312 09:58:43.756257 5259 server.go:87] Updated token: [redacted] |
| timestamp = line.split('jumphost', 1)[0] |
| suffix = line.split(pattern, 1)[1].rstrip() |
| return timestamp + proc + ': ' + pattern + suffix |
| return None |
| |
| |
| def read_syslog(): |
| """Read the syslog, returning any relevant lines.""" |
| lines = [] |
| with open(SYSLOG, 'rb') as f: |
| for line in f: |
| tf = transform_line(line) |
| if tf: |
| lines.append(tf) |
| return lines |
| |
| |
| def filter_logs(ip, log_lines): |
| """Filter the log lines to only those relevant to a particular IP address.""" |
| # First, collect all tokens used by the IP address. |
| tokens = [] |
| for line in log_lines: |
| if ip and ip in line: |
| tok = line.split(', serving ', 1)[1] |
| tokens.append(tok) |
| |
| # Filter to only lines which contain the IP address or one of its tokens. |
| filtered = [] |
| for line in log_lines: |
| if ip in line: |
| filtered.append(line) |
| else: |
| for tok in tokens: |
| # We don't care about other bots which used the token. |
| if tok in line and not 'Token requested by' in line: |
| filtered.append(line) |
| return filtered |
| |
| |
| def main(): |
| """Read the syslog, filter to relevant lines, then print them.""" |
| lines = read_syslog() |
| if len(sys.argv) > 1: |
| lines = filter_logs(sys.argv[1], lines) |
| for line in lines: |
| print(line) |
| |
| |
| if __name__ == '__main__': |
| main() |