1
1
#!/usr/bin/env python
2
2
"""
3
3
With this command you can log in to DIRAC.
4
-
5
4
There are two options:
6
-
7
5
- using a user certificate, creating a proxy.
8
6
- go through DIRAC Authorization Server by selecting your Identity Provider.
9
7
10
-
11
8
Example:
12
9
# Login with default group
13
10
$ dirac-login
19
16
import os
20
17
import sys
21
18
import copy
22
- from prompt_toolkit import prompt
19
+ from prompt_toolkit import prompt , print_formatted_text as print , HTML
23
20
24
21
import DIRAC
25
22
from DIRAC import gConfig , gLogger , S_OK , S_ERROR
26
- from DIRAC .Core .Security import Locations
23
+ from DIRAC .Core .Security . Locations import getDefaultProxyLocation , getCertificateAndKeyLocation
27
24
from DIRAC .Core .Security .ProxyFile import writeToProxyFile
28
25
from DIRAC .Core .Security .ProxyInfo import getProxyInfo , formatProxyInfoAsString
29
26
from DIRAC .Core .Security .X509Chain import X509Chain # pylint: disable=import-error
37
34
getTokenFileLocation ,
38
35
)
39
36
37
+ # This value shows what authorization way will be by default
38
+ DEFAULT_AUTH_WAY = "certificate" # possible values are "certificate", "diracas"
39
+ # This value shows what response will be by default
40
+ DEFAULT_RESPONSE = "proxy" # possible values are "proxy", "token"
41
+
40
42
41
43
class Params :
42
44
"""This class describes the input parameters"""
@@ -54,109 +56,76 @@ def __init__(self):
54
56
self .issuer = None
55
57
self .certLoc = None
56
58
self .keyLoc = None
57
- self .result = "proxy"
58
- self .authWith = "certificate"
59
+ self .response = DEFAULT_RESPONSE
60
+ self .authWith = DEFAULT_AUTH_WAY
59
61
self .enableCS = True
60
62
61
- def disableCS (self , _arg ) -> dict :
62
- """Set issuer
63
-
64
- :param arg: issuer
65
- """
63
+ def disableCS (self , _ ) -> dict :
64
+ """Disable CS"""
66
65
self .enableCS = False
67
66
return S_OK ()
68
67
69
- def setIssuer (self , arg : str ) -> dict :
70
- """Set issuer
71
-
72
- :param arg: issuer
73
- """
68
+ def setIssuer (self , issuer : str ) -> dict :
69
+ """Set DIRAC Authorization Server issuer"""
74
70
self .useDIRACAS (None )
75
- self .issuer = arg
71
+ self .issuer = issuer
76
72
return S_OK ()
77
73
78
- def useDIRACAS (self , _arg ) -> dict :
79
- """Use DIRAC AS
80
-
81
- :param _arg: unuse
82
- """
74
+ def useDIRACAS (self , _ ) -> dict :
75
+ """Use DIRAC AS"""
83
76
self .authWith = "diracas"
84
77
return S_OK ()
85
78
86
- def useCertificate (self , _arg ) -> dict :
87
- """Use certificate
88
-
89
- :param _arg: unuse
90
- """
79
+ def useCertificate (self , _ ) -> dict :
80
+ """Use certificate"""
91
81
os .environ ["DIRAC_USE_ACCESS_TOKEN" ] = "false"
92
82
self .authWith = "certificate"
93
- self .result = "proxy"
83
+ self .response = "proxy"
94
84
return S_OK ()
95
85
96
- def setCertificate (self , arg : str ) -> dict :
97
- """Set certificate file path
98
-
99
- :param arg: path
100
- """
101
- if not os .path .exists (arg ):
102
- DIRAC .gLogger .error (f"{ arg } does not exist." )
86
+ def setCertificate (self , filePath : str ) -> dict :
87
+ """Set certificate file path"""
88
+ if not os .path .exists (filePath ):
89
+ DIRAC .gLogger .error (f"{ filePath } does not exist." )
103
90
DIRAC .exit (1 )
104
91
self .useCertificate (None )
105
- self .certLoc = arg
92
+ self .certLoc = filePath
106
93
return S_OK ()
107
94
108
- def setPrivateKey (self , arg : str ) -> dict :
109
- """Set private key file path
110
-
111
- :param arg: path
112
- """
113
- if not os .path .exists (arg ):
114
- DIRAC .gLogger .error (f"{ arg } is not exist." )
95
+ def setPrivateKey (self , filePath : str ) -> dict :
96
+ """Set private key file path"""
97
+ if not os .path .exists (filePath ):
98
+ DIRAC .gLogger .error (f"{ filePath } is not exist." )
115
99
DIRAC .exit (1 )
116
100
self .useCertificate (None )
117
- self .keyLoc = arg
101
+ self .keyLoc = filePath
118
102
return S_OK ()
119
103
120
- def setOutputFile (self , arg : str ) -> dict :
121
- """Set output file location
122
-
123
- :param arg: output file location
124
- """
125
- self .outputFile = arg
104
+ def setOutputFile (self , filePath : str ) -> dict :
105
+ """Set output file location"""
106
+ self .outputFile = filePath
126
107
return S_OK ()
127
108
128
- def setLifetime (self , arg : str ) -> dict :
129
- """Set proxy lifetime
130
-
131
- :param arg: lifetime
132
- """
133
- self .lifetime = arg
109
+ def setLifetime (self , lifetime : str ) -> dict :
110
+ """Set proxy lifetime"""
111
+ self .lifetime = lifetime
134
112
return S_OK ()
135
113
136
- def setProxy (self , _arg ) -> dict :
137
- """Return proxy
138
-
139
- :param _arg: unuse
140
- """
114
+ def setProxy (self , _ ) -> dict :
115
+ """Return proxy"""
141
116
os .environ ["DIRAC_USE_ACCESS_TOKEN" ] = "false"
142
- self .result = "proxy"
117
+ self .response = "proxy"
143
118
return S_OK ()
144
119
145
- def setToken (self , _arg ) -> dict :
146
- """Return tokens
147
-
148
- :param _arg: unuse
149
- """
120
+ def setToken (self , _ ) -> dict :
121
+ """Return tokens"""
150
122
os .environ ["DIRAC_USE_ACCESS_TOKEN" ] = "true"
151
123
self .useDIRACAS (None )
152
- self .result = "token"
124
+ self .response = "token"
153
125
return S_OK ()
154
126
155
- def authStatus (self , _arg ) -> dict :
156
- """Get authorization status
157
-
158
- :param _arg: unuse
159
- """
127
+ def authStatus (self , _ ) -> dict :
128
+ """Get authorization status"""
160
129
result = self .getAuthStatus ()
161
130
if result ["OK" ]:
162
131
self .howToSwitch ()
@@ -208,8 +177,8 @@ def doOAuthMagic(self):
208
177
idpObj = result ["Value" ]
209
178
if self .group and self .group not in self .scopes :
210
179
self .scopes .append (f"g:{ self .group } " )
211
- if self .result == "proxy" and self .result not in self .scopes :
212
- self .scopes .append (self .result )
180
+ if self .response == "proxy" and self .response not in self .scopes :
181
+ self .scopes .append (self .response )
213
182
if self .lifetime :
214
183
self .scopes .append ("lifetime:%s" % (int (self .lifetime or 12 ) * 3600 ))
215
184
idpObj .scope = "+" .join (self .scopes ) if self .scopes else ""
@@ -219,8 +188,8 @@ def doOAuthMagic(self):
219
188
if not result ["OK" ]:
220
189
return result
221
190
222
- if self .result == "proxy" :
223
- self .outputFile = self .outputFile or Locations . getDefaultProxyLocation ()
191
+ if self .response == "proxy" :
192
+ self .outputFile = self .outputFile or getDefaultProxyLocation ()
224
193
# Save new proxy certificate
225
194
result = writeToProxyFile (idpObj .token ["proxy" ].encode ("UTF-8" ), self .outputFile )
226
195
if not result ["OK" ]:
@@ -261,8 +230,10 @@ def loginWithCertificate(self):
261
230
"""Login with certificate"""
262
231
# Search certificate and key
263
232
if not self .certLoc or not self .keyLoc :
264
- cakLoc = Locations .getCertificateAndKeyLocation ()
265
- if not cakLoc :
233
+ if not (cakLoc := getCertificateAndKeyLocation ()):
234
+ if not self .authWith : # if user do not choose this way
235
+ print (HTML ("<yellow>Can't find user certificate and key</yellow>, trying to connact to DIRAC AS.." ))
236
+ return self .doOAuthMagic () # Then try to use DIRAC AS
266
237
return S_ERROR ("Can't find user certificate and key" )
267
238
self .certLoc = self .certLoc or cakLoc [0 ]
268
239
self .keyLoc = self .keyLoc or cakLoc [1 ]
@@ -287,7 +258,7 @@ def loginWithCertificate(self):
287
258
proxy = copy .copy (chain )
288
259
289
260
# Create local proxy with group
290
- self .outputFile = self .outputFile or Locations . getDefaultProxyLocation ()
261
+ self .outputFile = self .outputFile or getDefaultProxyLocation ()
291
262
result = chain .generateProxyToFile (self .outputFile , int (self .lifetime or 12 ) * 3600 , self .group )
292
263
if not result ["OK" ]:
293
264
return S_ERROR (f"Couldn't generate proxy: { result ['Message' ]} " )
@@ -325,9 +296,10 @@ def howToSwitch(self) -> bool:
325
296
if src == "conf" :
326
297
msg += f" set /DIRAC/Security/UseTokens={ not useTokens } in dirac.cfg\n or\n "
327
298
msg += f" export DIRAC_USE_ACCESS_TOKEN={ not useTokens } \n "
328
- gLogger .notice (msg )
329
299
330
- return useTokens
300
+ # Show infomation message only if the current state of the user environment does not match the authorization result
301
+ if (useTokens and (self .response == "proxy" )) or (not useTokens and (self .response == "token" )):
302
+ gLogger .notice (msg )
331
303
332
304
def getAuthStatus (self ):
333
305
"""Try to get user authorization status.
@@ -339,7 +311,7 @@ def getAuthStatus(self):
339
311
return S_ERROR ("Cannot contact CS." )
340
312
gConfig .forceRefresh ()
341
313
342
- if self .result == "proxy" :
314
+ if self .response == "proxy" :
343
315
result = getProxyInfo (self .outputFile )
344
316
if result ["OK" ]:
345
317
gLogger .notice (formatProxyInfoAsString (result ["Value" ]))
@@ -353,8 +325,8 @@ def getAuthStatus(self):
353
325
354
326
@Script ()
355
327
def main ():
356
- p = Params ()
357
- p .registerCLISwitches ()
328
+ userParams = Params ()
329
+ userParams .registerCLISwitches ()
358
330
359
331
# Check time
360
332
deviation = getClockDeviation ()
@@ -374,24 +346,24 @@ def main():
374
346
)
375
347
DIRAC .exit (1 )
376
348
377
- p .group , p .scopes = Script .getPositionalArgs (group = True )
349
+ userParams .group , userParams .scopes = Script .getPositionalArgs (group = True )
378
350
# If you have chosen to use a certificate then a proxy will be generated locally using the specified certificate
379
- if p .authWith == "certificate" :
380
- result = p .loginWithCertificate ()
351
+ if userParams .authWith == "certificate" :
352
+ result = userParams .loginWithCertificate ()
381
353
382
354
# Otherwise, you must log in to the authorization server to gain access
383
355
else :
384
- result = p .doOAuthMagic ()
356
+ result = userParams .doOAuthMagic ()
385
357
386
358
# Print authorization status
387
- if result ["OK" ] and p .enableCS :
388
- result = p .getAuthStatus ()
359
+ if result ["OK" ] and userParams .enableCS :
360
+ result = userParams .getAuthStatus ()
389
361
390
362
if not result ["OK" ]:
391
- gLogger . fatal ( result [" Message" ] )
363
+ print ( HTML ( f"<red> { result [' Message' ] } </red>" ) )
392
364
sys .exit (1 )
393
365
394
- p .howToSwitch ()
366
+ userParams .howToSwitch ()
395
367
sys .exit (0 )
396
368
397
369
0 commit comments