Coverage for python/lsst/ctrl/bps/panda/panda_auth_utils.py: 22%
43 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-05 00:47 -0700
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-05 00:47 -0700
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 program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
22"""Functions for each panda_auth subcommand.
23"""
26__all__ = [
27 "panda_auth_clean",
28 "panda_auth_expiration",
29 "panda_auth_setup",
30 "panda_auth_status",
31 "panda_auth_update",
32]
35import logging
36import os
38import idds.common.utils as idds_utils
39import pandaclient.idds_api
40from pandaclient.openidc_utils import OpenIdConnect_Utils
42_LOG = logging.getLogger(__name__)
45def panda_auth_clean():
46 """Clean up token and token cache files."""
47 open_id = panda_auth_setup()
48 open_id.cleanup()
51def panda_auth_expiration():
52 """Get number of seconds until token expires.
54 Return
55 ------
56 expiration : `int`
57 Number of seconds until token expires.
58 """
59 expiration = 0
60 ret = panda_auth_status()
61 if ret:
62 expiration = ret[-1]["exp"]
63 return expiration
66def panda_auth_setup():
67 """Initialize auth object used by various auth functions.
69 Return
70 ------
71 open_id : `pandaclient.openidc_utils.OpenIdConnect_Utils`
72 Auth object which can interact with auth token.
73 """
74 for key in [
75 "PANDA_AUTH",
76 "PANDA_VERIFY_HOST",
77 "PANDA_AUTH_VO",
78 "PANDA_URL_SSL",
79 "PANDA_URL",
80 ]:
81 if key not in os.environ:
82 raise OSError(f"Missing environment variable {key}")
84 # OpenIdConnect_Utils have a verbose flag that filters
85 # some debugging messages. If user chose debug, just
86 # turn on all of the messages.
87 verbose = False
88 if _LOG.isEnabledFor(logging.DEBUG):
89 verbose = True
91 open_id = OpenIdConnect_Utils(None, log_stream=_LOG, verbose=verbose)
92 return open_id
95def panda_auth_status():
96 """Gather information about a token if it exists.
98 Return
99 ------
100 status : `dict`
101 Status information about a token if it exists.
102 Includes filename and expiration epoch.
103 """
104 status = None
105 open_id = panda_auth_setup()
106 ret = open_id.check_token()
107 if ret and ret[0]:
108 # get_token_path will return the path even if a token doesn't
109 # currently exist. So check for token first via check_token, then
110 # add path.
111 status = {"filename": open_id.get_token_path()}
112 status.update(ret[-1])
113 return status
116def panda_auth_update(idds_server=None, reset=False):
117 """Get new auth token if needed or reset is True.
119 Parameters
120 ----------
121 idds_server : `str`, optional
122 URL for the iDDS server. Defaults to None which means that the
123 underlying functions use any value in the panda relay service.
124 reset : `bool`, optional
125 Whether to first clean up any previous token. Defaults to False.
126 """
127 if reset:
128 panda_auth_clean()
130 # Create client manager
131 # (There is a function in OpenIdConnect_Utils, but it takes several
132 # parameters. Letting the client manager do it is currently easiest
133 # way to match what happens when the workflow is actually submitted.)
134 cm = pandaclient.idds_api.get_api(
135 idds_utils.json_dumps, idds_host=idds_server, compress=True, manager=True, verbose=False
136 )
138 # Must call some function to actually check auth
139 # https://panda-wms.readthedocs.io/en/latest/client/notebooks/jupyter_setup.html#Get-an-OIDC-ID-token
140 ret = cm.get_status(request_id=0, with_detail=False)
141 _LOG.debug("get_status results: %s", ret)
143 # Check success
144 # https://panda-wms.readthedocs.io/en/latest/client/rest_idds.html
145 if ret[0] == 0 and ret[1][0]:
146 # The success keys from get_status currently do not catch if invalid
147 # idds server given. So for now, check result string for keywords.
148 if "request_id" not in ret[1][-1] or "status" not in ret[1][-1]:
149 raise RuntimeError(f"Error contacting PanDA service: {str(ret)}")