Files
zuul/zuul/driver/gerrit/gcloudauth.py
James E. Blair b5a4d44645 Add gcloud_service auth option for Gerrit driver
A user running Zuul in the Google cloud may want to use service
accounts to authenticate to Gerrit.  Notably, the Gerrit project
itself operates in this manner.  Therefore, add support for
using the default service account to access Gerrit.

It is also very likely that a user may not want to expose a
service account with Gerrit credentials to the executors.
Therefore, we can not assume that they will have access to the
same service account.  Therefore if the gloud_service auth type
is specified for a Gerrit connection, we will only use anonymous
HTTP access for the git repositories.

This restriction is not ideal, and may be able to be removed later
if we find an out-of-band method of communicating a service account
token to the executor in a manner that would not make it available
to jobs running on it.

Change-Id: I02bc3219018278d517bc3ae6f1ac0be22ef7c0ed
2020-01-30 08:09:00 -08:00

67 lines
2.0 KiB
Python

# Copyright 2012 Google Inc.
# Copyright 2019 Red Hat, 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.
import logging
import requests
import threading
import time
TOKEN_URL = ('http://metadata.google.internal/computeMetadata/'
'v1/instance/service-accounts/default/token')
REFRESH = 25
RETRY_INTERVAL = 5
class GCloudAuth(requests.auth.AuthBase):
log = logging.getLogger('zuul.GerritConnection')
def __init__(self, user, password):
self.token = None
self.expires = 0
try:
self.getToken()
except Exception:
self.log.exception("Error updating token:")
self.update_thread = threading.Thread(target=self.update)
self.update_thread.daemon = True
self.update_thread.start()
def update(self):
while True:
try:
self._update()
except Exception:
self.log.exception("Error updating token:")
time.sleep(5)
def _update(self):
now = time.time()
expires = self.expires - REFRESH
expires = max(expires, now + RETRY_INTERVAL)
while now < expires:
time.sleep(expires - now)
now = time.time()
self.getToken()
def getToken(self):
r = requests.get(TOKEN_URL, headers={'Metadata-Flavor': 'Google'})
data = r.json()
self.token = data['access_token']
self.expires = time.time() + data['expires_in']
def __call__(self, request):
request.prepare_cookies({'o': self.token})
return request