1
-
2
- import import_declare_test
3
1
"""
4
2
This module will be used to get oauth token from auth code
5
3
"""
4
+ import import_declare_test
6
5
7
6
import urllib
8
7
try :
13
12
import splunk .admin as admin
14
13
from solnlib import log
15
14
from solnlib import conf_manager
15
+ from solnlib .conf_manager import InvalidHostnameError , InvalidPortError
16
16
from solnlib .utils import is_true
17
17
import json
18
- import requests
19
18
20
19
21
20
log .Logs .set_context ()
22
21
logger = log .Logs ().get_logger ('ta_cisco_webex_add_on_for_splunk_rh_oauth2_token' )
23
22
24
- # Note: Comment L30 to get rid of the following error
25
- # Python ERROR: AttributeError: module 'socks' has no attribute 'PROXY_TYPE_HTTP_NO_TUNNEL'
26
- # UI ERROR: 500 Internal Server Error
27
-
28
23
# Map for available proxy type
29
24
_PROXY_TYPE_MAP = {
30
25
'http' : socks .PROXY_TYPE_HTTP ,
31
- # 'http_no_tunnel': socks.PROXY_TYPE_HTTP_NO_TUNNEL,
32
26
'socks4' : socks .PROXY_TYPE_SOCKS4 ,
33
27
'socks5' : socks .PROXY_TYPE_SOCKS5 ,
34
28
}
35
29
30
+ if hasattr (socks , 'PROXY_TYPE_HTTP_NO_TUNNEL' ):
31
+ _PROXY_TYPE_MAP ['http_no_tunnel' ] = socks .PROXY_TYPE_HTTP_NO_TUNNEL
32
+
36
33
"""
37
34
REST Endpoint of getting token by OAuth2 in Splunk Add-on UI Framework. T
38
35
"""
@@ -44,14 +41,33 @@ class ta_cisco_webex_add_on_for_splunk_rh_oauth2_token(admin.MConfigHandler):
44
41
This method checks which action is getting called and what parameters are required for the request.
45
42
"""
46
43
44
+ def __init__ (self , * args , ** kwargs ):
45
+ super ().__init__ (* args , ** kwargs )
46
+ session_key = self .getSessionKey ()
47
+ log_level = conf_manager .get_log_level (
48
+ logger = logger ,
49
+ session_key = session_key ,
50
+ app_name = "ta_cisco_webex_add_on_for_splunk" ,
51
+ conf_name = "ta_cisco_webex_add_on_for_splunk_settings" ,
52
+ log_stanza = "logging" ,
53
+ log_level_field = "loglevel"
54
+ )
55
+ log .Logs ().set_level (log_level )
56
+
47
57
def setup (self ):
48
58
if self .requestedAction == admin .ACTION_EDIT :
49
59
# Add required args in supported args
50
60
for arg in ('url' , 'method' ,
51
- 'grant_type' , 'code' ,
52
- 'client_id' , 'client_secret' ,
53
- 'redirect_uri' ):
61
+ 'grant_type' , 'client_id' ,
62
+ 'client_secret' ):
54
63
self .supportedArgs .addReqArg (arg )
64
+
65
+ for arg in (
66
+ 'scope' , # Optional for client_credentials
67
+ 'code' , # Required for authorization_code
68
+ 'redirect_uri' , # Required for authorization_code
69
+ ):
70
+ self .supportedArgs .addOptArg (arg )
55
71
return
56
72
57
73
"""
@@ -69,63 +85,93 @@ def handleEdit(self, confInfo):
69
85
logger .debug ("oAUth url %s" , url )
70
86
proxy_info = self .getProxyDetails ()
71
87
88
+ http = Http (proxy_info = proxy_info )
89
+ method = self .callerArgs .data ['method' ][0 ]
90
+
72
91
# Create payload from the arguments received
92
+ grant_type = self .callerArgs .data ['grant_type' ][0 ]
93
+
73
94
payload = {
74
95
'grant_type' : self .callerArgs .data ['grant_type' ][0 ],
75
- 'code' : self .callerArgs .data ['code' ][0 ],
76
96
'client_id' : self .callerArgs .data ['client_id' ][0 ],
77
97
'client_secret' : self .callerArgs .data ['client_secret' ][0 ],
78
- 'redirect_uri' : self .callerArgs .data ['redirect_uri' ][0 ],
79
98
}
80
- headers = {"Content-Type" : "application/x-www-form-urlencoded" , }
81
99
82
- response = requests .request (
83
- "POST" , url , headers = headers , data = urlencode (payload ), proxies = proxy_info , verify = False
84
- )
100
+ if grant_type == "authorization_code" :
101
+ # If grant_type is authorization_code then add code and redirect_uri in payload
102
+ for param_name in ('code' , 'redirect_uri' ):
103
+ param = self .callerArgs .data .get (param_name , [None ])[0 ]
104
+
105
+ if param is None :
106
+ raise ValueError (
107
+ "%s is required for authorization_code grant type" % param_name
108
+ )
85
109
86
- content = response .json ()
110
+ payload [param_name ] = param
111
+ elif grant_type == "client_credentials" :
112
+ # If grant_type is client_credentials add scope exists then add it in payload
113
+ scope = self .callerArgs .data .get ('scope' , [None ])[0 ]
87
114
115
+ if scope :
116
+ payload ['scope' ] = scope
117
+ else :
118
+ # Else raise an error
119
+ logger .error ("Invalid grant_type %s" , grant_type )
120
+ raise ValueError (
121
+ "Invalid grant_type %s. Supported values are authorization_code and client_credentials" % grant_type
122
+ )
123
+
124
+ headers = {"Content-Type" : "application/x-www-form-urlencoded" , }
125
+ # Send http request to get the accesstoken
126
+ resp , content = http .request (url ,
127
+ method = method ,
128
+ headers = headers ,
129
+ body = urlencode (payload ))
130
+ content = json .loads (content )
88
131
# Check for any errors in response. If no error then add the content values in confInfo
89
- if response . status_code == 200 :
132
+ if resp . status == 200 :
90
133
for key , val in content .items ():
91
134
confInfo ['token' ][key ] = val
92
135
else :
93
136
# Else add the error message in the confinfo
94
- confInfo ['token' ]['error' ] = content ['message ' ]
137
+ confInfo ['token' ]['error' ] = content ['error_description ' ]
95
138
logger .info (
96
- "Exiting OAuth rest handler after getting access token with response %s" , response . status_code )
139
+ "Exiting OAuth rest handler after getting access token with response %s" , resp . status )
97
140
except Exception as exc :
98
141
logger .exception (
99
- "Error occurred while getting access token using auth code" )
100
- raise exc ()
142
+ "Error occurred while getting accesstoken using auth code" )
143
+ raise
101
144
102
145
"""
103
146
This method is to get proxy details stored in settings conf file
104
147
"""
105
148
106
149
def getProxyDetails (self ):
107
- # Create confmanger object for the app with realm
108
- cfm = conf_manager .ConfManager (self .getSessionKey (
109
- ), "ta_cisco_webex_add_on_for_splunk" , realm = "__REST_CREDENTIAL__#ta_cisco_webex_add_on_for_splunk#configs/conf-ta_cisco_webex_add_on_for_splunk_settings" )
110
- # Get Conf object of apps settings
111
- conf = cfm .get_conf ('ta_cisco_webex_add_on_for_splunk_settings' )
112
- # Get proxy stanza from the settings
113
- proxy_config = conf .get ("proxy" , True )
150
+ proxy_config = None
151
+
152
+ try :
153
+ proxy_config = conf_manager .get_proxy_dict (
154
+ logger = logger ,
155
+ session_key = self .getSessionKey (),
156
+ app_name = "ta_cisco_webex_add_on_for_splunk" ,
157
+ conf_name = "ta_cisco_webex_add_on_for_splunk_settings" ,
158
+ )
159
+
160
+ # Handle invalid port case
161
+ except InvalidPortError as e :
162
+ logger .error (f"Proxy configuration error: { e } " )
163
+
164
+ # Handle invalid hostname case
165
+ except InvalidHostnameError as e :
166
+ logger .error (f"Proxy configuration error: { e } " )
167
+
114
168
if not proxy_config or not is_true (proxy_config .get ('proxy_enabled' )):
115
169
logger .info ('Proxy is not enabled' )
116
170
return None
117
171
118
172
url = proxy_config .get ('proxy_url' )
119
173
port = proxy_config .get ('proxy_port' )
120
174
121
- if url or port :
122
- if not url :
123
- raise ValueError ('Proxy "url" must not be empty' )
124
- if not self .is_valid_port (port ):
125
- raise ValueError (
126
- 'Proxy "port" must be in range [1,65535]: %s' % port
127
- )
128
-
129
175
user = proxy_config .get ('proxy_username' )
130
176
password = proxy_config .get ('proxy_password' )
131
177
@@ -162,11 +208,5 @@ def getProxyDetails(self):
162
208
:type port: ``int``
163
209
"""
164
210
165
- def is_valid_port (self , port ):
166
- try :
167
- return 0 < int (port ) <= 65535
168
- except ValueError :
169
- return False
170
-
171
211
if __name__ == "__main__" :
172
212
admin .init (ta_cisco_webex_add_on_for_splunk_rh_oauth2_token , admin .CONTEXT_APP_AND_USER )
0 commit comments