* issue #61672: make jenkins_plugin module work in a session when CSRF enabled This commit modifies the signature of `fetch_url` so that a cookie jar can be specified allowing multiple calls to operate with the same session. It uses a similar construct to the `Request` class to initialise the cookie jar if it is not provided. The jenkins_plugin module is modified to create a cookie jar if CSRF is enabled. This cookie jar is then submitted with every call to fetch_url. Also changed is to submit the crumb in the request headers rather than in the data field. This has been tested with Jenkins 2.176. * issue #61672: fix jenkins_script module This commit modifies the jenkins_script module to use the authorization crumb in a session in a similar fashion to the jenkins_plugin change for the same issue.
This commit is contained in:
parent
dfc023209f
commit
76b5b90bd6
3 changed files with 19 additions and 11 deletions
|
@ -1423,7 +1423,7 @@ def url_argument_spec():
|
||||||
|
|
||||||
def fetch_url(module, url, data=None, headers=None, method=None,
|
def fetch_url(module, url, data=None, headers=None, method=None,
|
||||||
use_proxy=True, force=False, last_mod_time=None, timeout=10,
|
use_proxy=True, force=False, last_mod_time=None, timeout=10,
|
||||||
use_gssapi=False, unix_socket=None, ca_path=None):
|
use_gssapi=False, unix_socket=None, ca_path=None, cookies=None):
|
||||||
"""Sends a request via HTTP(S) or FTP (needs the module as parameter)
|
"""Sends a request via HTTP(S) or FTP (needs the module as parameter)
|
||||||
|
|
||||||
:arg module: The AnsibleModule (used to get username, password etc. (s.b.).
|
:arg module: The AnsibleModule (used to get username, password etc. (s.b.).
|
||||||
|
@ -1479,7 +1479,8 @@ def fetch_url(module, url, data=None, headers=None, method=None,
|
||||||
client_cert = module.params.get('client_cert')
|
client_cert = module.params.get('client_cert')
|
||||||
client_key = module.params.get('client_key')
|
client_key = module.params.get('client_key')
|
||||||
|
|
||||||
cookies = cookiejar.LWPCookieJar()
|
if not isinstance(cookies, cookiejar.CookieJar):
|
||||||
|
cookies = cookiejar.LWPCookieJar()
|
||||||
|
|
||||||
r = None
|
r = None
|
||||||
info = dict(url=url, status=-1)
|
info = dict(url=url, status=-1)
|
||||||
|
|
|
@ -264,6 +264,7 @@ state:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule, to_bytes
|
from ansible.module_utils.basic import AnsibleModule, to_bytes
|
||||||
|
from ansible.module_utils.six.moves import http_cookiejar as cookiejar
|
||||||
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
||||||
from ansible.module_utils.urls import fetch_url, url_argument_spec
|
from ansible.module_utils.urls import fetch_url, url_argument_spec
|
||||||
from ansible.module_utils._text import to_native, text_type, binary_type
|
from ansible.module_utils._text import to_native, text_type, binary_type
|
||||||
|
@ -287,8 +288,11 @@ class JenkinsPlugin(object):
|
||||||
|
|
||||||
# Crumb
|
# Crumb
|
||||||
self.crumb = {}
|
self.crumb = {}
|
||||||
|
# Cookie jar for crumb session
|
||||||
|
self.cookies = None
|
||||||
|
|
||||||
if self._csrf_enabled():
|
if self._csrf_enabled():
|
||||||
|
self.cookies = cookiejar.LWPCookieJar()
|
||||||
self.crumb = self._get_crumb()
|
self.crumb = self._get_crumb()
|
||||||
|
|
||||||
# Get list of installed plugins
|
# Get list of installed plugins
|
||||||
|
@ -332,7 +336,8 @@ class JenkinsPlugin(object):
|
||||||
# Get the URL data
|
# Get the URL data
|
||||||
try:
|
try:
|
||||||
response, info = fetch_url(
|
response, info = fetch_url(
|
||||||
self.module, url, timeout=self.timeout, **kwargs)
|
self.module, url, timeout=self.timeout, cookies=self.cookies,
|
||||||
|
headers=self.crumb, **kwargs)
|
||||||
|
|
||||||
if info['status'] != 200:
|
if info['status'] != 200:
|
||||||
self.module.fail_json(msg=msg_status, details=info['msg'])
|
self.module.fail_json(msg=msg_status, details=info['msg'])
|
||||||
|
@ -405,7 +410,6 @@ class JenkinsPlugin(object):
|
||||||
script_data = {
|
script_data = {
|
||||||
'script': install_script
|
'script': install_script
|
||||||
}
|
}
|
||||||
script_data.update(self.crumb)
|
|
||||||
data = urlencode(script_data)
|
data = urlencode(script_data)
|
||||||
|
|
||||||
# Send the installation request
|
# Send the installation request
|
||||||
|
@ -691,14 +695,12 @@ class JenkinsPlugin(object):
|
||||||
def _pm_query(self, action, msg):
|
def _pm_query(self, action, msg):
|
||||||
url = "%s/pluginManager/plugin/%s/%s" % (
|
url = "%s/pluginManager/plugin/%s/%s" % (
|
||||||
self.params['url'], self.params['name'], action)
|
self.params['url'], self.params['name'], action)
|
||||||
data = urlencode(self.crumb)
|
|
||||||
|
|
||||||
# Send the request
|
# Send the request
|
||||||
self._get_url_data(
|
self._get_url_data(
|
||||||
url,
|
url,
|
||||||
msg_status="Plugin not found. %s" % url,
|
msg_status="Plugin not found. %s" % url,
|
||||||
msg_exception="%s has failed." % msg,
|
msg_exception="%s has failed." % msg)
|
||||||
data=data)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
|
@ -105,6 +105,7 @@ output:
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.six.moves import http_cookiejar as cookiejar
|
||||||
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
||||||
from ansible.module_utils.urls import fetch_url
|
from ansible.module_utils.urls import fetch_url
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils._text import to_native
|
||||||
|
@ -121,10 +122,11 @@ def is_csrf_protection_enabled(module):
|
||||||
return json.loads(content).get('useCrumbs', False)
|
return json.loads(content).get('useCrumbs', False)
|
||||||
|
|
||||||
|
|
||||||
def get_crumb(module):
|
def get_crumb(module, cookies):
|
||||||
resp, info = fetch_url(module,
|
resp, info = fetch_url(module,
|
||||||
module.params['url'] + '/crumbIssuer/api/json',
|
module.params['url'] + '/crumbIssuer/api/json',
|
||||||
method='GET')
|
method='GET',
|
||||||
|
cookies=cookies)
|
||||||
if info["status"] != 200:
|
if info["status"] != 200:
|
||||||
module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"], output='')
|
module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"], output='')
|
||||||
|
|
||||||
|
@ -163,8 +165,10 @@ def main():
|
||||||
script_contents = module.params['script']
|
script_contents = module.params['script']
|
||||||
|
|
||||||
headers = {}
|
headers = {}
|
||||||
|
cookies = None
|
||||||
if is_csrf_protection_enabled(module):
|
if is_csrf_protection_enabled(module):
|
||||||
crumb = get_crumb(module)
|
cookies = cookiejar.LWPCookieJar()
|
||||||
|
crumb = get_crumb(module, cookies)
|
||||||
headers = {crumb['crumbRequestField']: crumb['crumb']}
|
headers = {crumb['crumbRequestField']: crumb['crumb']}
|
||||||
|
|
||||||
resp, info = fetch_url(module,
|
resp, info = fetch_url(module,
|
||||||
|
@ -172,7 +176,8 @@ def main():
|
||||||
data=urlencode({'script': script_contents}),
|
data=urlencode({'script': script_contents}),
|
||||||
headers=headers,
|
headers=headers,
|
||||||
method="POST",
|
method="POST",
|
||||||
timeout=module.params['timeout'])
|
timeout=module.params['timeout'],
|
||||||
|
cookies=cookies)
|
||||||
|
|
||||||
if info["status"] != 200:
|
if info["status"] != 200:
|
||||||
module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"], output='')
|
module.fail_json(msg="HTTP error " + str(info["status"]) + " " + info["msg"], output='')
|
||||||
|
|
Loading…
Reference in a new issue