Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Kerberos auth #2825

Merged
merged 1 commit into from
Jan 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions spark/datadog_checks/spark/data/conf.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ instances:
# username: user
# password: pass

# If your service uses Kerberos authentication, you can optionally
# specify the Kerberos strategy to use.
# See https://github.com/requests/requests-kerberos#mutual-authentication
# kerberos: "required|optional|disabled"
# kerberos_delegate: false
# kerberos_force_initiate: false
# kerberos_hostname: null
# kerberos_principal: null
# kerberos_keytab: /path/to/keytab_file

# SSL configuration.
# ssl_verify: false
# ssl_cert: /path/to/cert.pem
Expand Down
56 changes: 43 additions & 13 deletions spark/datadog_checks/spark/spark.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
# (C) Datadog, Inc. 2010-2017
# (C) Datadog, Inc. 2018
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)
from urlparse import urljoin, urlsplit, urlunsplit, urlparse
import os
from collections import namedtuple

import requests
import requests_kerberos
from requests.exceptions import Timeout, HTTPError, InvalidURL, ConnectionError
from simplejson import JSONDecodeError
from bs4 import BeautifulSoup
from simplejson import JSONDecodeError
from six.moves.urllib.parse import urljoin, urlsplit, urlunsplit, urlparse

from datadog_checks.base import AgentCheck, is_affirmative

from datadog_checks.checks import AgentCheck
from datadog_checks.config import is_affirmative
KERBEROS_STRATEGIES = {
'required': requests_kerberos.REQUIRED,
'optional': requests_kerberos.OPTIONAL,
'disabled': requests_kerberos.DISABLED,
}

# Identifier for cluster master address in `spark.yaml`
MASTER_ADDRESS = 'spark_url'
Expand Down Expand Up @@ -148,7 +155,8 @@
'auth',
'ssl_verify',
'ssl_cert',
'ssl_key'
'ssl_key',
'kerberos_keytab',
]
)

Expand Down Expand Up @@ -199,17 +207,32 @@ def check(self, instance):
message='Connection to ApplicationMaster "%s" was successful' % am_address)

def _get_requests_config(self, instance):
auth = None

# Authenticate our connection to JMX endpoint if required
kerberos = instance.get('kerberos')
username = instance.get('username')
password = instance.get('password')
auth = None
if username is not None and password is not None:
auth = (username, password)
elif kerberos is not None:
if kerberos not in KERBEROS_STRATEGIES:
raise Exception('Invalid Kerberos strategy `{}`'.format(kerberos))

auth = requests_kerberos.HTTPKerberosAuth(
mutual_authentication=KERBEROS_STRATEGIES[kerberos],
delegate=is_affirmative(instance.get('kerberos_delegate', False)),
force_preemptive=is_affirmative(instance.get('kerberos_force_initiate', False)),
hostname_override=instance.get('kerberos_hostname'),
principal=instance.get('kerberos_principal')
)

return RequestsConfig(
auth=auth,
ssl_verify=instance.get('ssl_verify'),
ssl_cert=instance.get('ssl_cert'),
ssl_key=instance.get('ssl_key'),
kerberos_keytab=instance.get('kerberos_keytab'),
)

def _get_master_address(self, instance):
Expand Down Expand Up @@ -606,14 +629,11 @@ def _set_metric(self, metric_name, metric_type, value, tags=None):
else:
self.log.error('Metric type "{}" unknown'.format(metric_type))

def _rest_request(self, address, object_path, service_name, requests_config, tags, *args, **kwargs):
def _rest_request(self, url, object_path, service_name, requests_config, tags, *args, **kwargs):
'''
Query the given URL and return the response
'''
response = None
service_check_tags = ['url:%s' % self._get_url_base(address)] + tags

url = address
service_check_tags = ['url:%s' % self._get_url_base(url)] + tags

if object_path:
url = self._join_url_dir(url, object_path)
Expand Down Expand Up @@ -642,6 +662,11 @@ def _rest_request(self, address, object_path, service_name, requests_config, tag
query = '&'.join(['{0}={1}'.format(key, value) for key, value in kwargs.iteritems()])
url = urljoin(url, '?' + query)

old_keytab_path = None
if requests_config.kerberos_keytab:
old_keytab_path = os.getenv('KRB5_CLIENT_KTNAME')
os.environ['KRB5_CLIENT_KTNAME'] = requests_config.kerberos_keytab

try:
self.log.debug('Spark check URL: %s' % url)
response = requests.get(
Expand Down Expand Up @@ -677,7 +702,12 @@ def _rest_request(self, address, object_path, service_name, requests_config, tag
message=str(e))
raise

return response
else:
return response

finally:
if old_keytab_path is not None:
os.environ['KRB5_CLIENT_KTNAME'] = old_keytab_path

def _rest_request_to_json(self, address, object_path, service_name, requests_config, tags, *args, **kwargs):
'''
Expand Down
3 changes: 1 addition & 2 deletions spark/requirements.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@

beautifulsoup4==4.5.1

requests-kerberos==0.12.0
2 changes: 1 addition & 1 deletion spark/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def get_requirements(fpath):
return f.readlines()


CHECKS_BASE_REQ = 'datadog_checks_base'
CHECKS_BASE_REQ = 'datadog-checks-base>=4.2.0'

setup(
name='datadog-spark',
Expand Down