-
Notifications
You must be signed in to change notification settings - Fork 175
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Include DiracX token in proxy PEM files
- Loading branch information
Showing
11 changed files
with
167 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
from __future__ import annotations | ||
|
||
__all__ = ( | ||
"DiracXClient", | ||
"diracxTokenFromPEM", | ||
) | ||
|
||
import base64 | ||
import json | ||
import re | ||
import textwrap | ||
from contextlib import contextmanager | ||
from pathlib import Path | ||
from tempfile import NamedTemporaryFile | ||
from typing import Any | ||
|
||
from diracx.client import DiracClient as _DiracClient | ||
from diracx.core.models import TokenResponse | ||
from diracx.core.preferences import DiracxPreferences | ||
from diracx.core.utils import serialize_credentials | ||
|
||
from DIRAC import gConfig | ||
from DIRAC.ConfigurationSystem.Client.Helpers import Registry | ||
from DIRAC.Core.Security.Locations import getDefaultProxyLocation | ||
from DIRAC.Core.Utilities.ReturnValues import convertToReturnValue, returnValueOrRaise | ||
|
||
|
||
PEM_BEGIN = "-----BEGIN DIRACX-----" | ||
PEM_END = "-----END DIRACX-----" | ||
RE_DIRACX_PEM = re.compile(rf"{PEM_BEGIN}\n(.*)\n{PEM_END}", re.MULTILINE | re.DOTALL) | ||
|
||
|
||
@convertToReturnValue | ||
def addProxyToPEM(pemPath, group): | ||
from DIRAC.Core.Base.Client import Client | ||
|
||
vo = Registry.getVOMSVOForGroup(group) | ||
disabledVOs = gConfig.getValue("/DiracX/DisabledVOs", []) | ||
if vo and vo not in disabledVOs: | ||
token_content = returnValueOrRaise( | ||
Client(url="Framework/ProxyManager", proxyLocation=pemPath).exchangeProxyForToken() | ||
) | ||
|
||
diracxUrl = gConfig.getValue("/DiracX/URL") | ||
if not diracxUrl: | ||
return S_ERROR("Missing mandatory /DiracX/URL configuration") | ||
|
||
token = TokenResponse( | ||
access_token=token_content["access_token"], | ||
expires_in=token_content["expires_in"], | ||
token_type=token_content.get("token_type"), | ||
refresh_token=token_content.get("refresh_token"), | ||
) | ||
|
||
token_pem = f"{PEM_BEGIN}\n" | ||
data = base64.b64encode(serialize_credentials(token).encode("utf-8")).decode() | ||
token_pem += textwrap.fill(data, width=64) | ||
token_pem += f"\n{PEM_END}\n" | ||
|
||
with open(pemPath, "a") as f: | ||
f.write(token_pem) | ||
|
||
|
||
def diracxTokenFromPEM(pemPath) -> dict[str, Any] | None: | ||
"""Extract the DiracX token from the proxy PEM file""" | ||
pem = Path(pemPath).read_text() | ||
if match := RE_DIRACX_PEM.search(pem): | ||
match = match.group(1) | ||
return json.loads(base64.b64decode(match).decode("utf-8")) | ||
|
||
|
||
@contextmanager | ||
def DiracXClient() -> _DiracClient: | ||
"""Get a DiracX client instance with the current user's credentials""" | ||
diracxUrl = gConfig.getValue("/DiracX/URL") | ||
if not diracxUrl: | ||
raise ValueError("Missing mandatory /DiracX/URL configuration") | ||
|
||
proxyLocation = getDefaultProxyLocation() | ||
diracxToken = diracxTokenFromPEM(proxyLocation) | ||
|
||
with NamedTemporaryFile(mode="wt") as token_file: | ||
token_file.write(json.dumps(diracxToken)) | ||
token_file.flush() | ||
token_file.seek(0) | ||
|
||
pref = DiracxPreferences(url=diracxUrl, credentials_path=token_file.name) | ||
with _DiracClient(diracx_preferences=pref) as api: | ||
yield api |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
"""Query DiracX for information about the current user | ||
This is a stripped down version of the "dirac whoami" script from DiracX. | ||
It primarily exists as a method of validating the current user's credentials are functional. | ||
""" | ||
import json | ||
|
||
from DIRAC.Core.Base.Script import Script | ||
from DIRAC.Core.Security.DiracX import DiracXClient | ||
|
||
|
||
@Script() | ||
def main(): | ||
Script.parseCommandLine() | ||
|
||
with DiracXClient() as api: | ||
user_info = api.auth.userinfo() | ||
print(json.dumps(user_info.as_dict(), indent=2)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters