Coverage for python/lsst/ctrl/bps/panda/panda_auth_utils.py: 22%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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 "IDDS_CONFIG",
81 ]:
82 if key not in os.environ:
83 raise OSError(f"Missing environment variable {key}")
85 # OpenIdConnect_Utils have a verbose flag that filters
86 # some debugging messages. If user chose debug, just
87 # turn on all of the messages.
88 verbose = False
89 if _LOG.isEnabledFor(logging.DEBUG):
90 verbose = True
92 open_id = OpenIdConnect_Utils(None, log_stream=_LOG, verbose=verbose)
93 return open_id
96def panda_auth_status():
97 """Gather information about a token if it exists.
99 Return
100 ------
101 status : `dict`
102 Status information about a token if it exists.
103 Includes filename and expiration epoch.
104 """
105 status = None
106 open_id = panda_auth_setup()
107 ret = open_id.check_token()
108 if ret and ret[0]:
109 # get_token_path will return the path even if a token doesn't
110 # currently exist. So check for token first via check_token, then
111 # add path.
112 status = {"filename": open_id.get_token_path()}
113 status.update(ret[-1])
114 return status
117def panda_auth_update(idds_server=None, reset=False):
118 """Get new auth token if needed or reset is True.
120 Parameters
121 ----------
122 idds_server : `str`, optional
123 URL for the iDDS server. Defaults to None which means that the
124 underlying functions use any value in the IDDS_CONFIG.
125 reset : `bool`, optional
126 Whether to first clean up any previous token. Defaults to False.
127 """
128 if reset:
129 panda_auth_clean()
131 # Create client manager
132 # (There is a function in OpenIdConnect_Utils, but it takes several
133 # parameters. Letting the client manager do it is currently easiest
134 # way to match what happens when the workflow is actually submitted.)
135 cm = pandaclient.idds_api.get_api(
136 idds_utils.json_dumps, idds_host=idds_server, compress=True, manager=True, verbose=False
137 )
139 # Must call some function to actually check auth
140 # https://panda-wms.readthedocs.io/en/latest/client/notebooks/jupyter_setup.html#Get-an-OIDC-ID-token
141 ret = cm.get_status(request_id=0, with_detail=False)
142 _LOG.debug("get_status results: %s", ret)
144 # Check success
145 # https://panda-wms.readthedocs.io/en/latest/client/rest_idds.html
146 if ret[0] == 0 and ret[1][0]:
147 # The success keys from get_status currently do not catch if invalid
148 # idds server given. So for now, check result string for keywords.
149 if "request_id" not in ret[1][-1] or "status" not in ret[1][-1]:
150 raise RuntimeError(f"Error contacting PanDA service: {str(ret)}")