# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Manage Google Low Overhead Authentication Service (LOAS) tasks.

This is used by scripts that run outside of the chroot and require access to
Google production resources.

If you don't know what any of this means, then you don't need this module :).
"""

from __future__ import print_function

import datetime
import re
import socket

from chromite.lib import alerts
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging


class LoasError(Exception):
  """Raised when a LOAS error occurs"""


class Loas(object):
  """Class for holding all the various LOAS cruft."""

  def __init__(self, user, email_notify):
    self.user = user
    self.email_notify = email_notify
    self.enroll_msg = 'become -t -c "prodaccess --sslenroll" %s@%s' % (
        self.user, socket.getfqdn())
    self.last_notification = (
        datetime.date.today() - datetime.timedelta(weeks=10))

  def Check(self):
    logging.debug('Checking LOAS credentials for %s', self.user)
    cmd = ['runloas', '/usr/bin/loas_check']

    # Error message to print when loas credential check fails. This usually
    # is the result of production credentials expiring for accessing
    # Keystore for the unwrapping private key.
    loas_error = 'loas_check for %s failed! Did you run: %s' % (
        self.user, self.enroll_msg)
    try:
      cros_build_lib.SudoRunCommand(cmd,
                                    user=self.user,
                                    error_message=loas_error)
    except cros_build_lib.RunCommandError as e:
      raise LoasError(e.msg)

  def Status(self):
    # Only bother checking once a day.  Our certs are valid in the
    # range of weeks, so there's no need to constantly do this.
    if (datetime.date.today() <
        self.last_notification + datetime.timedelta(days=1)):
      return

    cmd = ['prodcertstatus', '--check_loas_cert_location', 'sslenrolled']
    result = cros_build_lib.SudoRunCommand(cmd,
                                           user=self.user,
                                           error_code_ok=True,
                                           redirect_stdout=True)

    # Figure out how many days are left.  The command should display:
    # SSL-ENROLLED CERT cert expires in about 22 days
    m = re.search(r'cert expires in about ([0-9]+) days', result.output)
    if m:
      days_left = int(m.group(1))
    else:
      days_left = 0

    # Send out one notification a day if there's a week or less left
    # before our creds expire.
    if days_left <= 7:
      alerts.SendEmail(
          'Loas certs expiring soon!',
          self.email_notify,
          message='Please run:\n %s\n\n%s\n%s' % (
              self.enroll_msg, result.output, result.error))
      self.last_notification = datetime.date.today()
    else:
      # We won't expire for a while, so stop the periodic polling.
      self.last_notification = (
          datetime.date.today() + datetime.timedelta(days=days_left - 8))
