mirror of
https://github.com/ansible/awx.git
synced 2026-03-07 19:51:08 -03:30
Ship analytics data using service account token (#15812)
Use oidc client to ship analytics data
This commit is contained in:
@@ -10,6 +10,7 @@ from awx.api.generics import APIView, Response
|
|||||||
from awx.api.permissions import AnalyticsPermission
|
from awx.api.permissions import AnalyticsPermission
|
||||||
from awx.api.versioning import reverse
|
from awx.api.versioning import reverse
|
||||||
from awx.main.utils import get_awx_version
|
from awx.main.utils import get_awx_version
|
||||||
|
from awx.main.utils.analytics_proxy import OIDCClient, DEFAULT_OIDC_ENDPOINT
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
@@ -179,32 +180,48 @@ class AnalyticsGenericView(APIView):
|
|||||||
|
|
||||||
return Response(response.content, status=response.status_code)
|
return Response(response.content, status=response.status_code)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _base_auth_request(request: requests.Request, method: str, url: str, user: str, pw: str, headers: dict[str, str]) -> requests.Response:
|
||||||
|
response = requests.request(
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
auth=(user, pw),
|
||||||
|
verify=settings.INSIGHTS_CERT_PATH,
|
||||||
|
params=getattr(request, 'query_params', {}),
|
||||||
|
headers=headers,
|
||||||
|
json=getattr(request, 'data', {}),
|
||||||
|
timeout=(31, 31),
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
|
||||||
def _send_to_analytics(self, request, method):
|
def _send_to_analytics(self, request, method):
|
||||||
try:
|
try:
|
||||||
headers = self._request_headers(request)
|
headers = self._request_headers(request)
|
||||||
|
|
||||||
self._get_setting('INSIGHTS_TRACKING_STATE', False, ERROR_UPLOAD_NOT_ENABLED)
|
self._get_setting('INSIGHTS_TRACKING_STATE', False, ERROR_UPLOAD_NOT_ENABLED)
|
||||||
|
if method not in ["GET", "POST", "OPTIONS"]:
|
||||||
|
return self._error_response(ERROR_UNSUPPORTED_METHOD, method, remote=False, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||||
url = self._get_analytics_url(request.path)
|
url = self._get_analytics_url(request.path)
|
||||||
try:
|
try:
|
||||||
rh_user = self._get_setting('REDHAT_USERNAME', None, ERROR_MISSING_USER)
|
rh_user = self._get_setting('REDHAT_USERNAME', None, ERROR_MISSING_USER)
|
||||||
rh_password = self._get_setting('REDHAT_PASSWORD', None, ERROR_MISSING_PASSWORD)
|
rh_password = self._get_setting('REDHAT_PASSWORD', None, ERROR_MISSING_PASSWORD)
|
||||||
except MissingSettings:
|
client = OIDCClient(rh_user, rh_password, DEFAULT_OIDC_ENDPOINT, ['api.console'])
|
||||||
rh_user = self._get_setting('SUBSCRIPTIONS_USERNAME', None, ERROR_MISSING_USER)
|
response = client.make_request(
|
||||||
rh_password = self._get_setting('SUBSCRIPTIONS_PASSWORD', None, ERROR_MISSING_PASSWORD)
|
|
||||||
|
|
||||||
if method not in ["GET", "POST", "OPTIONS"]:
|
|
||||||
return self._error_response(ERROR_UNSUPPORTED_METHOD, method, remote=False, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
||||||
else:
|
|
||||||
response = requests.request(
|
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
auth=(rh_user, rh_password),
|
headers=headers,
|
||||||
verify=settings.INSIGHTS_CERT_PATH,
|
verify=settings.INSIGHTS_CERT_PATH,
|
||||||
params=getattr(request, 'query_params', {}),
|
params=getattr(request, 'query_params', {}),
|
||||||
headers=headers,
|
|
||||||
json=getattr(request, 'data', {}),
|
json=getattr(request, 'data', {}),
|
||||||
timeout=(31, 31),
|
timeout=(31, 31),
|
||||||
)
|
)
|
||||||
|
except requests.RequestException:
|
||||||
|
logger.error("Automation Analytics API request failed, trying base auth method")
|
||||||
|
response = self._base_auth_request(request, method, url, rh_user, rh_password, headers)
|
||||||
|
except MissingSettings:
|
||||||
|
rh_user = self._get_setting('SUBSCRIPTIONS_USERNAME', None, ERROR_MISSING_USER)
|
||||||
|
rh_password = self._get_setting('SUBSCRIPTIONS_PASSWORD', None, ERROR_MISSING_PASSWORD)
|
||||||
|
response = self._base_auth_request(request, method, url, rh_user, rh_password, headers)
|
||||||
#
|
#
|
||||||
# Missing or wrong user/pass
|
# Missing or wrong user/pass
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from ansible_base.lib.utils.db import advisory_lock
|
|||||||
from awx.main.models import Job
|
from awx.main.models import Job
|
||||||
from awx.main.access import access_registry
|
from awx.main.access import access_registry
|
||||||
from awx.main.utils import get_awx_http_client_headers, set_environ, datetime_hook
|
from awx.main.utils import get_awx_http_client_headers, set_environ, datetime_hook
|
||||||
|
from awx.main.utils.analytics_proxy import OIDCClient, DEFAULT_OIDC_ENDPOINT
|
||||||
|
|
||||||
__all__ = ['register', 'gather', 'ship']
|
__all__ = ['register', 'gather', 'ship']
|
||||||
|
|
||||||
@@ -370,25 +371,31 @@ def ship(path):
|
|||||||
rh_user = getattr(settings, 'REDHAT_USERNAME', None)
|
rh_user = getattr(settings, 'REDHAT_USERNAME', None)
|
||||||
rh_password = getattr(settings, 'REDHAT_PASSWORD', None)
|
rh_password = getattr(settings, 'REDHAT_PASSWORD', None)
|
||||||
|
|
||||||
if not rh_user or not rh_password:
|
|
||||||
logger.info('REDHAT_USERNAME and REDHAT_PASSWORD are not set, using SUBSCRIPTIONS_USERNAME and SUBSCRIPTIONS_PASSWORD')
|
|
||||||
rh_user = getattr(settings, 'SUBSCRIPTIONS_USERNAME', None)
|
|
||||||
rh_password = getattr(settings, 'SUBSCRIPTIONS_PASSWORD', None)
|
|
||||||
|
|
||||||
if not rh_user:
|
|
||||||
logger.error('REDHAT_USERNAME and SUBSCRIPTIONS_USERNAME are not set')
|
|
||||||
return False
|
|
||||||
if not rh_password:
|
|
||||||
logger.error('REDHAT_PASSWORD and SUBSCRIPTIONS_USERNAME are not set')
|
|
||||||
return False
|
|
||||||
|
|
||||||
with open(path, 'rb') as f:
|
with open(path, 'rb') as f:
|
||||||
files = {'file': (os.path.basename(path), f, settings.INSIGHTS_AGENT_MIME)}
|
files = {'file': (os.path.basename(path), f, settings.INSIGHTS_AGENT_MIME)}
|
||||||
s = requests.Session()
|
s = requests.Session()
|
||||||
s.headers = get_awx_http_client_headers()
|
s.headers = get_awx_http_client_headers()
|
||||||
s.headers.pop('Content-Type')
|
s.headers.pop('Content-Type')
|
||||||
with set_environ(**settings.AWX_TASK_ENV):
|
with set_environ(**settings.AWX_TASK_ENV):
|
||||||
response = s.post(url, files=files, verify=settings.INSIGHTS_CERT_PATH, auth=(rh_user, rh_password), headers=s.headers, timeout=(31, 31))
|
if rh_user and rh_password:
|
||||||
|
try:
|
||||||
|
client = OIDCClient(rh_user, rh_password, DEFAULT_OIDC_ENDPOINT, ['api.console'])
|
||||||
|
response = client.make_request("POST", url, headers=s.headers, files=files, verify=settings.INSIGHTS_CERT_PATH, timeout=(31, 31))
|
||||||
|
except requests.RequestException:
|
||||||
|
logger.error("Automation Analytics API request failed, trying base auth method")
|
||||||
|
response = s.post(url, files=files, verify=settings.INSIGHTS_CERT_PATH, auth=(rh_user, rh_password), headers=s.headers, timeout=(31, 31))
|
||||||
|
elif not rh_user or not rh_password:
|
||||||
|
logger.info('REDHAT_USERNAME and REDHAT_PASSWORD are not set, using SUBSCRIPTIONS_USERNAME and SUBSCRIPTIONS_PASSWORD')
|
||||||
|
rh_user = getattr(settings, 'SUBSCRIPTIONS_USERNAME', None)
|
||||||
|
rh_password = getattr(settings, 'SUBSCRIPTIONS_PASSWORD', None)
|
||||||
|
if rh_user and rh_password:
|
||||||
|
response = s.post(url, files=files, verify=settings.INSIGHTS_CERT_PATH, auth=(rh_user, rh_password), headers=s.headers, timeout=(31, 31))
|
||||||
|
elif not rh_user:
|
||||||
|
logger.error('REDHAT_USERNAME and SUBSCRIPTIONS_USERNAME are not set')
|
||||||
|
return False
|
||||||
|
elif not rh_password:
|
||||||
|
logger.error('REDHAT_PASSWORD and SUBSCRIPTIONS_USERNAME are not set')
|
||||||
|
return False
|
||||||
# Accept 2XX status_codes
|
# Accept 2XX status_codes
|
||||||
if response.status_code >= 300:
|
if response.status_code >= 300:
|
||||||
logger.error('Upload failed with status {}, {}'.format(response.status_code, response.text))
|
logger.error('Upload failed with status {}, {}'.format(response.status_code, response.text))
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ from typing import Optional, Any
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
DEFAULT_OIDC_ENDPOINT = 'https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token'
|
||||||
|
|
||||||
|
|
||||||
class TokenError(requests.RequestException):
|
class TokenError(requests.RequestException):
|
||||||
'''
|
'''
|
||||||
|
|||||||
Reference in New Issue
Block a user