The specific scenario is checked with Keycloak Module, where my Keycloak Instance is hosted with Cloudflare Proxy.
When I try run keycloak related task with ansible playbook, it fails with HTTP Error 403: Forbidden.
The reason being the bot protection in CDN Services, Cloudflare in my case. The request made by the keycloak module, doesn't add User-Agent header, which is blocked. I came across this issue when I was testing out keycloak realm creation with ansible playbook, It worked for my local test server, gave the following error for my cloudflare protected keycloak.
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Could not obtain access token from https://kc.korifi.run/realms/master/protocol/openid-connect/token: HTTP Error 403: Forbidden"}
I debugged down to the module and tried out the snippet to get token with a smaller python script.
Just adding the Useragent header with appropriate default value, and it worked
Many of the WAF Protected servers won't allow Requests without User-Agent headers, considering them as bot generated and block.
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
import traceback
import urllib
import ssl
from ansible.module_utils.urls import open_url
from ansible.module_utils.six.moves.urllib.parse import urlencode, quote
from ansible.module_utils.common.text.converters import to_native, to_text
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
request_url = "https://kc.korifi.run/realms/master/protocol/openid-connect/token" #Your Keycloak URL
## Taking out Snipper from
temp_payload = {
'grant_type': 'password',
'client_id': "admin-cli",
'username': "admin",
'password': "admin",
}
payload = dict(
(k, v) for k, v in temp_payload.items() if v is not None)
try: #Request without User-Agent header will return 403 Forbidden
r = json.loads(to_native(open_url(request_url, method='POST',
validate_certs='False',
data=urlencode(payload)).read()))
print(r)
except Exception as e:
print(e,"\n")
try: #Request with User-Agent header will work
rh = json.loads(to_native(open_url(request_url, method='POST',
validate_certs='False',
data=urlencode(payload), headers={"User-Agent": "Ansible"}).read()))
print(rh)
except Exception as e:
print(e,"\n")
### Demonstrating Behavior with URL Lib
data=urllib.parse.urlencode(payload)
data=data.encode('ascii')
try: #Request without User-Agent header will return 403 Forbidden
req = urllib.request.Request(url=request_url, data=data)
with urllib.request.urlopen(req, context=ctx) as f:
print("Response with no User-Agent Header")
print(json.loads(to_native(f.read())))
except Exception as e:
print("Exception with no User-Agent Header")
print(e,"\n")
try: #Request with User-Agent header will work
req_header = urllib.request.Request(url=request_url,headers={"User-Agent": "Ansible"},data=data)
with urllib.request.urlopen(req_header, context=ctx) as f:
print("Response with User-Agent Header\n")
print(f.read())
except Exception as e:
print(e,"\n")
One suggestion is to implicitly set User-Agent headers value to something like Ansible-
I will be working on applying the fix myself will create a PR once completed.
Summary
The specific scenario is checked with Keycloak Module, where my Keycloak Instance is hosted with Cloudflare Proxy.
When I try run keycloak related task with ansible playbook, it fails with HTTP Error 403: Forbidden. The reason being the bot protection in CDN Services, Cloudflare in my case. The request made by the keycloak module, doesn't add User-Agent header, which is blocked. I came across this issue when I was testing out keycloak realm creation with ansible playbook, It worked for my local test server, gave the following error for my cloudflare protected keycloak.
I debugged down to the module and tried out the snippet to get token with a smaller python script. Just adding the Useragent header with appropriate default value, and it worked
Many of the WAF Protected servers won't allow Requests without User-Agent headers, considering them as bot generated and block.
Adding User-Agent header to the request will work for most of the scenarios that use
ansible.module_uitls.urls
library Following Script demonstrates the exception and fix for the same with snippet taken from https://github.com/ansible-collections/community.general/blob/1c167ab8948afe429fd4591ea4434f14ab40a862/plugins/module_utils/identity/keycloak/keycloak.py#L140Issue Type
Feature request
Component Name
community.general(Keycloak)
Ansible Version
Community.general Version
Configuration
OS / Environment
Linux fedora 5.18.13-200.fc36.x86_64
Steps to Reproduce
Pre-requisites:
Keycloak Server Hosted with Cloudflare Proxy
Expected Results
It shoud be successful
Actual Results
Code of Conduct