#!/usr/bin/python
# Copyright (C) 2012 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Background daemon to refresh OAuth access tokens.
Tokens are written to ~/.git-credential-cache/cookie
Git config variable http.cookiefile is updated.

Runs only on Google Compute Engine (GCE). On GCE Windows '--nofork' option
is needed. '--debug' option is available.
"""

from __future__ import print_function

import atexit
import contextlib
import json
import os
import platform
import subprocess
import sys
import time

if sys.version_info[0] > 2:
  # Python 3 imports
  from urllib.request import urlopen, Request
  from urllib.error import URLError
  from urllib.error import HTTPError
  import http.cookiejar as cookielib
else:
  # Python 2 imports
  from urllib2 import urlopen, Request, HTTPError, URLError
  import cookielib

REFRESH = 25  # seconds remaining when starting refresh
RETRY_INTERVAL = 5 # seconds between retrying a failed refresh

META_URL = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/'
SUPPORTED_SCOPES = [
  'https://www.googleapis.com/auth/cloud-platform',
  'https://www.googleapis.com/auth/gerritcodereview',
  'https://www.googleapis.com/auth/source.full_control',
  'https://www.googleapis.com/auth/source.read_write',
  'https://www.googleapis.com/auth/source.read_only',
]
COOKIE_JAR = None
IS_WINDOWS = platform.system() == 'Windows'

def read_meta(part):
  r = Request(META_URL + part)
  r.add_header('Metadata-Flavor', 'Google')
  return contextlib.closing(urlopen(r))

def select_scope():
  with read_meta('scopes') as d:
    avail = set(map(lambda s: s.decode('utf-8'), d.read().split()))
  scopes = [s for s in SUPPORTED_SCOPES if s in avail]
  if scopes:
    return next(iter(scopes))
  sys.stderr.write('error: VM must have one of these scopes:\n\n')
  for s in SUPPORTED_SCOPES:
    sys.stderr.write('  %s\n' % (s))
  sys.exit(1)

def configure_git():
  global COOKIE_JAR

  if IS_WINDOWS:
    # Git for Windows reads %HOMEPATH%/.gitconfig in Command Prompt,
    # but $HOME/.gitconfig in Cygwin. The two paths can be different.
    # Cygwin sets env var $HOMEPATH accordingly to %HOMEPATH%.
    # Set cookie file as %HOMEPATH%/.git-credential-cache/cookie,
    # so it can be used in both cases.
    if 'HOMEPATH' in os.environ:
      homepath = os.environ['HOMEPATH']
    else:
      # When launched as a scheduled task at machine startup
      # HOMEPATH may not be set.
      sys.stderr.write('HOMEPATH is not set.\n')
      sys.exit(1)
  else:
    homepath = os.environ['HOME']
  dir = os.path.join(homepath, '.git-credential-cache')

  COOKIE_JAR = os.path.join(dir, 'cookie')
  if '--debug' in sys.argv:
    print('Cookie file: %s' % COOKIE_JAR)

  if os.path.exists(dir):
    os.chmod(dir, 0o700)
  else:
    os.mkdir(dir, 0o700)
  subprocess.call([
    'git', 'config', '--global',
    'http.cookiefile', COOKIE_JAR
  ])

def acquire_token(scope, retry):
  while True:
    try:
      with read_meta('token?scopes=' + scope) as d:
        return json.load(d)
    except URLError:
      if not retry:
        raise
    time.sleep(RETRY_INTERVAL)

def update_cookie(scope, retry):
  now = int(time.time())
  token = acquire_token(scope, retry)
  access_token = token['access_token']
  expires = now + int(token['expires_in'])  # Epoch in sec

  tmp_jar = COOKIE_JAR + '.lock'
  cj = cookielib.MozillaCookieJar(tmp_jar)

  for d in ['source.developers.google.com', '.googlesource.com']:
    cj.set_cookie(cookielib.Cookie(
      version = 0,
      name = 'o',
      value = access_token,
      port = None,
      port_specified = False,
      domain = d,
      domain_specified = True,
      domain_initial_dot = d.startswith('.'),
      path = '/',
      path_specified = True,
      secure = True,
      expires = expires,
      discard = False,
      comment = None,
      comment_url = None,
      rest = None))

  cj.save()
  if '--debug' in sys.argv:
    print('Updating %s.' % COOKIE_JAR)
    print('Expires: %d, %s, in %d seconds'% (
      expires, time.ctime(expires), expires - now))
    sys.stdout.flush()
  if IS_WINDOWS:
    # os.rename() below on Windows will raise OSError when dst exists.
    # See https://docs.python.org/2/library/os.html#os.rename
    if os.path.isfile(COOKIE_JAR):
      os.remove(COOKIE_JAR)
  os.rename(tmp_jar, COOKIE_JAR)
  return expires

def cleanup():
  if COOKIE_JAR:
    for p in [COOKIE_JAR, COOKIE_JAR + '.lock']:
      if os.path.exists(p):
        os.remove(p)

def refresh_loop(scope, expires):
  atexit.register(cleanup)
  expires = expires - REFRESH
  while True:
    now = time.time()
    expires = max(expires, now + RETRY_INTERVAL)
    while now < expires:
      time.sleep(expires - now)
      now = time.time()
    expires = update_cookie(scope, retry=True) - REFRESH

def main():
  scope = select_scope()
  configure_git()

  expires = update_cookie(scope, retry=False)

  if '--nofork' not in sys.argv:
    if IS_WINDOWS:
      # os.fork() is not supported on Windows.
      sys.stderr.write('Add \'--nofork\' on Windows\n')
      sys.exit(1)

    if os.fork() > 0:
      sys.exit(0)

    os.chdir('/')
    os.setsid()
    os.umask(0)

    pid = os.fork()
    if pid > 0:
      print('git-cookie-authdaemon PID %d' % (pid))
      sys.exit(0)

  refresh_loop(scope, expires)

if __name__ == '__main__':
  main()
