feat: enable Lix admins to admin the Buildbot properly
This removes the need for a proxy and rely on the `groups` property of the `userDetails` passed at the authentication layer. To add a certain role, add the group `buildbot-$role` to that user via Keycloak. Signed-off-by: Raito Bezarius <raito@lix.systems>
This commit is contained in:
parent
45135d249b
commit
f2d7f25f86
|
@ -9,6 +9,7 @@ from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
|
import buildbot
|
||||||
from buildbot.configurators import ConfiguratorBase
|
from buildbot.configurators import ConfiguratorBase
|
||||||
from buildbot.plugins import reporters, schedulers, secrets, steps, util, worker
|
from buildbot.plugins import reporters, schedulers, secrets, steps, util, worker
|
||||||
from buildbot.process import buildstep, logobserver, remotecommand
|
from buildbot.process import buildstep, logobserver, remotecommand
|
||||||
|
@ -17,7 +18,6 @@ from buildbot.process.properties import Interpolate, Properties
|
||||||
from buildbot.process.results import ALL_RESULTS, statusToString
|
from buildbot.process.results import ALL_RESULTS, statusToString
|
||||||
from buildbot.steps.trigger import Trigger
|
from buildbot.steps.trigger import Trigger
|
||||||
from buildbot.util import asyncSleep
|
from buildbot.util import asyncSleep
|
||||||
from buildbot.www.authz.endpointmatchers import EndpointMatcherBase, Match
|
|
||||||
from buildbot.www.oauth2 import OAuth2Auth
|
from buildbot.www.oauth2 import OAuth2Auth
|
||||||
from buildbot.changes.gerritchangesource import GerritChangeSource
|
from buildbot.changes.gerritchangesource import GerritChangeSource
|
||||||
from buildbot.reporters.utils import getURLForBuild
|
from buildbot.reporters.utils import getURLForBuild
|
||||||
|
@ -27,6 +27,7 @@ from buildbot.process.buildstep import EXCEPTION
|
||||||
from buildbot.process.buildstep import SUCCESS
|
from buildbot.process.buildstep import SUCCESS
|
||||||
from buildbot.process.results import worst_status
|
from buildbot.process.results import worst_status
|
||||||
from buildbot_nix.binary_cache import LocalSigner
|
from buildbot_nix.binary_cache import LocalSigner
|
||||||
|
import requests
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from buildbot.process.log import Log
|
from buildbot.process.log import Log
|
||||||
|
@ -46,11 +47,33 @@ log = Logger()
|
||||||
class LixSystemsOAuth2(OAuth2Auth):
|
class LixSystemsOAuth2(OAuth2Auth):
|
||||||
name = 'Lix'
|
name = 'Lix'
|
||||||
faIcon = 'fa-login'
|
faIcon = 'fa-login'
|
||||||
resourceEndpoint = "https://identity.lix.systems"
|
resourceEndpoint = "https://identity.lix.systems/realms/lix-project/protocol/openid-connect"
|
||||||
# is passing scope necessary?
|
sslVerify = True
|
||||||
|
debug = False
|
||||||
authUri = 'https://identity.lix.systems/realms/lix-project/protocol/openid-connect/auth'
|
authUri = 'https://identity.lix.systems/realms/lix-project/protocol/openid-connect/auth'
|
||||||
tokenUri = 'https://identity.lix.systems/realms/lix-project/protocol/openid-connect/token'
|
tokenUri = 'https://identity.lix.systems/realms/lix-project/protocol/openid-connect/token'
|
||||||
|
|
||||||
|
def createSessionFromToken(self, token):
|
||||||
|
s = requests.Session()
|
||||||
|
s.headers = {
|
||||||
|
'Authorization': 'Bearer ' + token['access_token'],
|
||||||
|
'User-Agent': f'buildbot/{buildbot.version}',
|
||||||
|
}
|
||||||
|
if self.debug:
|
||||||
|
log.info("Token obtained: {}".format(token))
|
||||||
|
s.verify = self.sslVerify
|
||||||
|
return s
|
||||||
|
|
||||||
|
def getUserInfoFromOAuthClient(self, c):
|
||||||
|
userinfo_resp = c.get("https://identity.lix.systems/realms/lix-project/protocol/openid-connect/userinfo")
|
||||||
|
log.info("Userinfo request to Lix OAuth2: {}".format(userinfo_resp.status_code))
|
||||||
|
if userinfo_resp.status_code != 200:
|
||||||
|
log.info("Userinfo failure: {}".format(userinfo_resp.headers["www-authenticate"]))
|
||||||
|
userinfo_data = userinfo_resp.json()
|
||||||
|
return {
|
||||||
|
'groups': userinfo_data['buildbot_roles']
|
||||||
|
}
|
||||||
|
|
||||||
class BuildbotNixError(Exception):
|
class BuildbotNixError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -901,3 +924,18 @@ class GerritNixConfigurator(ConfiguratorBase):
|
||||||
|
|
||||||
if "auth" not in config["www"]:
|
if "auth" not in config["www"]:
|
||||||
config["www"]["auth"] = LixSystemsOAuth2('buildbot', read_secret_file('buildbot-oauth2-secret'), autologin=True)
|
config["www"]["auth"] = LixSystemsOAuth2('buildbot', read_secret_file('buildbot-oauth2-secret'), autologin=True)
|
||||||
|
|
||||||
|
if "authz" not in config["www"]:
|
||||||
|
config["www"]["authz"] = util.Authz(
|
||||||
|
allowRules=[
|
||||||
|
util.AnyEndpointMatcher(role="admin", defaultDeny=False),
|
||||||
|
util.StopBuildEndpointMatcher(role="owner"),
|
||||||
|
util.AnyControlEndpointMatcher(role="admin"),
|
||||||
|
],
|
||||||
|
roleMatchers=[
|
||||||
|
# A user must have buildbot-<something> to have the role <something>
|
||||||
|
# e.g. buildbot-admin to be admin.
|
||||||
|
util.RolesFromGroups(groupPrefix="buildbot-"),
|
||||||
|
util.RolesFromOwner(role="owner")
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue