Coverage for python/lsst/ctrl/bps/panda/panda_auth_utils.py: 22%
43 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-27 10:33 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-27 10:33 +0000
1# This file is part of ctrl_bps_panda.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
28"""Functions for each panda_auth subcommand.
29"""
32__all__ = [
33 "panda_auth_clean",
34 "panda_auth_expiration",
35 "panda_auth_setup",
36 "panda_auth_status",
37 "panda_auth_update",
38]
41import logging
42import os
44import idds.common.utils as idds_utils
45import pandaclient.idds_api
46from pandaclient.openidc_utils import OpenIdConnect_Utils
48_LOG = logging.getLogger(__name__)
51def panda_auth_clean():
52 """Clean up token and token cache files."""
53 open_id = panda_auth_setup()
54 open_id.cleanup()
57def panda_auth_expiration():
58 """Get number of seconds until token expires.
60 Returns
61 -------
62 expiration : `int`
63 Number of seconds until token expires.
64 """
65 expiration = 0
66 ret = panda_auth_status()
67 if ret:
68 expiration = ret[-1]["exp"]
69 return expiration
72def panda_auth_setup():
73 """Initialize auth object used by various auth functions.
75 Returns
76 -------
77 open_id : `pandaclient.openidc_utils.OpenIdConnect_Utils`
78 Auth object which can interact with auth token.
79 """
80 for key in [
81 "PANDA_AUTH",
82 "PANDA_VERIFY_HOST",
83 "PANDA_AUTH_VO",
84 "PANDA_URL_SSL",
85 "PANDA_URL",
86 ]:
87 if key not in os.environ:
88 raise OSError(f"Missing environment variable {key}")
90 # OpenIdConnect_Utils have a verbose flag that filters
91 # some debugging messages. If user chose debug, just
92 # turn on all of the messages.
93 verbose = False
94 if _LOG.isEnabledFor(logging.DEBUG):
95 verbose = True
97 open_id = OpenIdConnect_Utils(None, log_stream=_LOG, verbose=verbose)
98 return open_id
101def panda_auth_status():
102 """Gather information about a token if it exists.
104 Returns
105 -------
106 status : `dict`
107 Status information about a token if it exists.
108 Includes filename and expiration epoch.
109 """
110 status = None
111 open_id = panda_auth_setup()
112 ret = open_id.check_token()
113 if ret and ret[0]:
114 # get_token_path will return the path even if a token doesn't
115 # currently exist. So check for token first via check_token, then
116 # add path.
117 status = {"filename": open_id.get_token_path()}
118 status.update(ret[-1])
119 return status
122def panda_auth_update(idds_server=None, reset=False):
123 """Get new auth token if needed or reset is True.
125 Parameters
126 ----------
127 idds_server : `str`, optional
128 URL for the iDDS server. Defaults to None which means that the
129 underlying functions use any value in the panda relay service.
130 reset : `bool`, optional
131 Whether to first clean up any previous token. Defaults to False.
132 """
133 if reset:
134 panda_auth_clean()
136 # Create client manager
137 # (There is a function in OpenIdConnect_Utils, but it takes several
138 # parameters. Letting the client manager do it is currently easiest
139 # way to match what happens when the workflow is actually submitted.)
140 cm = pandaclient.idds_api.get_api(
141 idds_utils.json_dumps, idds_host=idds_server, compress=True, manager=True, verbose=False
142 )
144 # Must call some function to actually check auth
145 # https://panda-wms.readthedocs.io/en/latest/client/notebooks/jupyter_setup.html#Get-an-OIDC-ID-token
146 ret = cm.get_status(request_id=0, with_detail=False)
147 _LOG.debug("get_status results: %s", ret)
149 # Check success
150 # https://panda-wms.readthedocs.io/en/latest/client/rest_idds.html
151 if ret[0] == 0 and ret[1][0]:
152 # The success keys from get_status currently do not catch if invalid
153 # idds server given. So for now, check result string for keywords.
154 if "request_id" not in ret[1][-1] or "status" not in ret[1][-1]:
155 raise RuntimeError(f"Error contacting PanDA service: {str(ret)}")