Coverage for python/lsst/ctrl/bps/wms/panda/panda_auth_utils.py: 22%
43 statements
« prev ^ index » next coverage.py v7.2.1, created at 2023-03-12 03:01 -0700
« prev ^ index » next coverage.py v7.2.1, created at 2023-03-12 03:01 -0700
1# This file is part of ctrl_bps.
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
38from pandaclient.openidc_utils import OpenIdConnect_Utils
39import idds.common.utils as idds_utils
40import pandaclient.idds_api
42_LOG = logging.getLogger(__name__)
45def panda_auth_clean():
46 """Clean up token and token cache files.
47 """
48 open_id = panda_auth_setup()
49 open_id.cleanup()
52def panda_auth_expiration():
53 """Get number of seconds until token expires.
55 Return
56 ------
57 expiration : `int`
58 Number of seconds until token expires.
59 """
60 expiration = 0
61 ret = panda_auth_status()
62 if ret:
63 expiration = ret[-1]["exp"]
64 return expiration
67def panda_auth_setup():
68 """Initialize auth object used by various auth functions.
70 Return
71 ------
72 open_id : `pandaclient.openidc_utils.OpenIdConnect_Utils`
73 Auth object which can interact with auth token.
74 """
75 for key in ["PANDA_AUTH", "PANDA_VERIFY_HOST", "PANDA_AUTH_VO", "PANDA_URL_SSL", "PANDA_URL",
76 "IDDS_CONFIG"]:
77 if key not in os.environ:
78 raise OSError(f"Missing environment variable {key}")
80 # OpenIdConnect_Utils have a verbose flag that filters
81 # some debugging messages. If user chose debug, just
82 # turn on all of the messages.
83 verbose = False
84 if _LOG.isEnabledFor(logging.DEBUG):
85 verbose = True
87 open_id = OpenIdConnect_Utils(None, log_stream=_LOG, verbose=verbose)
88 return open_id
91def panda_auth_status():
92 """Gather information about a token if it exists.
94 Return
95 ------
96 status : `dict`
97 Status information about a token if it exists.
98 Includes filename and expiration epoch.
99 """
100 status = None
101 open_id = panda_auth_setup()
102 ret = open_id.check_token()
103 if ret and ret[0]:
104 # get_token_path will return the path even if a token doesn't
105 # currently exist. So check for token first via check_token, then
106 # add path.
107 status = {"filename": open_id.get_token_path()}
108 status.update(ret[-1])
109 return status
112def panda_auth_update(idds_server=None, reset=False):
113 """Get new auth token if needed or reset is True.
115 Parameters
116 ----------
117 idds_server : `str`, optional
118 URL for the iDDS server. Defaults to None which means that the
119 underlying functions use any value in the IDDS_CONFIG.
120 reset : `bool`, optional
121 Whether to first clean up any previous token. Defaults to False.
122 """
123 if reset:
124 panda_auth_clean()
126 # Create client manager
127 # (There is a function in OpenIdConnect_Utils, but it takes several
128 # parameters. Letting the client manager do it is currently easiest
129 # way to match what happens when the workflow is actually submitted.)
130 cm = pandaclient.idds_api.get_api(idds_utils.json_dumps, idds_host=idds_server, compress=True,
131 manager=True, verbose=False)
133 # Must call some function to actually check auth
134 # https://panda-wms.readthedocs.io/en/latest/client/notebooks/jupyter_setup.html#Get-an-OIDC-ID-token
135 ret = cm.get_status(request_id=0, with_detail=False)
136 _LOG.debug("get_status results: %s", ret)
138 # Check success
139 # https://panda-wms.readthedocs.io/en/latest/client/rest_idds.html
140 if ret[0] == 0 and ret[1][0]:
141 # The success keys from get_status currently do not catch if invalid
142 # idds server given. So for now, check result string for keywords.
143 if "request_id" not in ret[1][-1] or "status" not in ret[1][-1]:
144 raise RuntimeError(f"Error contacting PanDA service: {str(ret)}")