Move to metadata server v1 API

Support any scope that may be accepted by a service.

Change-Id: Ifef92158ff425b1e478b6fb73eae60878d782f63
diff --git a/git-cookie-authdaemon b/git-cookie-authdaemon
index 9e37004..27fae4b 100755
--- a/git-cookie-authdaemon
+++ b/git-cookie-authdaemon
@@ -20,10 +20,31 @@
 REFRESH = 25  # seconds remaining when starting refresh
 RETRY_INTERVAL = 5 # seconds between retrying a failed refresh
 
-A = 'http://metadata/0.1/meta-data/service-accounts/default/acquire'
-S = 'https://www.googleapis.com/auth/gerritcodereview'
+META_URL = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/'
+SUPPORTED_SCOPES = [
+  '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
 
+def read_meta(part):
+  r = urllib2.Request(META_URL + part)
+  r.add_header('Metadata-Flavor', 'Google')
+  return contextlib.closing(urllib2.urlopen(r))
+
+def select_scope():
+  with read_meta('scopes') as d:
+    avail = set(d.read().split())
+  scopes = [s for s in SUPPORTED_SCOPES if s in avail]
+  if scopes:
+    return iter(scopes).next()
+  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
 
@@ -39,59 +60,43 @@
     'http.cookiefile', COOKIE_JAR
   ])
 
-def acquire_token(retry):
+def acquire_token(scope, retry):
   while True:
     try:
-      with contextlib.closing(urllib2.urlopen(A + '?scopes=' + S)) as token:
-        return json.load(token)
+      with read_meta('token?scopes=' + scope) as d:
+        return json.load(d)
     except urllib2.URLError:
       if not retry:
         raise
     time.sleep(RETRY_INTERVAL)
 
-def update_cookie(retry):
-  token = acquire_token(retry)
-  expires = token['expiresAt']
-  access_token = token['accessToken']
+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'])
 
   tmp_jar = COOKIE_JAR + '.lock'
   cj = cookielib.MozillaCookieJar(tmp_jar)
 
-  cj.set_cookie(cookielib.Cookie(
-    version = 0,
-    name = 'o',
-    value = access_token,
-    port = None,
-    port_specified = False,
-    domain = 'source.developers.google.com',
-    domain_specified = True,
-    domain_initial_dot = False,
-    path = '/',
-    path_specified = True,
-    secure = True,
-    expires = expires,
-    discard = False,
-    comment = None,
-    comment_url = None,
-    rest = None))
-
-  cj.set_cookie(cookielib.Cookie(
-    version = 0,
-    name = 'o',
-    value = access_token,
-    port = None,
-    port_specified = False,
-    domain = '.googlesource.com',
-    domain_specified = True,
-    domain_initial_dot = True,
-    path = '/',
-    path_specified = True,
-    secure = True,
-    expires = expires,
-    discard = False,
-    comment = None,
-    comment_url = None,
-    rest = None))
+  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()
   os.rename(tmp_jar, COOKIE_JAR)
@@ -103,7 +108,7 @@
       if os.path.exists(p):
         os.remove(p)
 
-def refresh_loop(expires):
+def refresh_loop(scope, expires):
   atexit.register(cleanup)
   expires = expires - REFRESH
   while True:
@@ -112,11 +117,12 @@
     while now < expires:
       time.sleep(expires - now)
       now = time.time()
-    expires = update_cookie(retry=True) - REFRESH
+    expires = update_cookie(scope, retry=True) - REFRESH
 
 def main():
+  scope = select_scope()
   configure_git()
-  expires = update_cookie(retry=False)
+  expires = update_cookie(scope, retry=False)
 
   if '--nofork' not in sys.argv:
     if os.fork() > 0:
@@ -128,10 +134,10 @@
 
     pid = os.fork()
     if pid > 0:
-      print '%s PID %d' % (sys.argv[0], pid)
+      print 'git-cookie-authdaemon PID %d' % (pid)
       sys.exit(0)
 
-  refresh_loop(expires)
+  refresh_loop(scope, expires)
 
 if __name__ == '__main__':
   main()