def init_multiauth(app, servicetype='HTTP', hostname=gethostname()): """ Configure the GSSAPI service name, and validate the principal in the kerberos keytab. @param app: a flask application @param servicetype: GSSAPI service type @param hostname: hostname service is running on """ global _SERVICE_NAME _SERVICE_NAME = "{0}@{1}".format(servicetype, hostname) global _logger _logger = app.logger global _cfg _cfg = app.config if "KRB5_KTNAME" not in environ: _logger.warn("Please set KRB5_KTNAME to your fully quailified KRB5 ketab file name") return try: principal = kerberos.getServerPrincipalDetails(servicetype, hostname) app.logger.warn("flask_multiauth: server is %s" % principal) except kerberos.KrbError as exc: _logger.warn("flask_multiauth: %s" % exc.message[0])
def _check_hostname(hostname): try: principal = kerberos.getServerPrincipalDetails('HTTP', hostname) except kerberos.KrbError as exc: LOG.warning('kerberos.getServerPrincipalDetails("HTTP", %r) raised %s', hostname, exc) else: LOG.debug('KerberosAuthMiddleware is identifying as %s', principal)
def testServicePrincipal(service, hostname): try: result = kerberos.getServerPrincipalDetails(service, hostname) except kerberos.KrbError as e: print("Kerberos service principal for %s/%s failed: %s" % (service, hostname, e[0])) else: print("Kerberos service principal for %s/%s succeeded: %s" % (service, hostname, result))
def __init__(self, principal=None, serviceType=None, hostname=None): """ @param principal: full Kerberos principal (e.g., 'HTTP/[email protected]'). If C{None} then the type and hostname arguments are used instead. @type principal: str @param serviceType: service type for Kerberos (e.g., 'HTTP'). Must be C{None} if principal used. @type serviceType: str @param hostname: hostname for this server. Must be C{None} if principal used. @type hostname: str """ # Only certain combinations of arguments allowed assert (principal and not serviceType and not hostname) or (not principal and serviceType and hostname) if not principal: # Look up the Kerberos principal given the service type and hostname, and extract # the realm and a service principal value for later use. try: principal = kerberos.getServerPrincipalDetails( serviceType, hostname) except kerberos.KrbError, ex: self.log.error("getServerPrincipalDetails: %s" % (ex[0], )) raise ValueError('Authentication System Failure: %s' % (ex[0], ))
def init_kerberos(app, service='HTTP', hostname=gethostname()): ''' Configure the GSSAPI service name, and validate the presence of the appropriate principal in the kerberos keytab. :param app: a flask application :type app: flask.Flask :param service: GSSAPI service name :type service: str :param hostname: hostname the service runs under :type hostname: str ''' if config['Authentication']['Enabled'] == 'False': return global _SERVICE_NAME _SERVICE_NAME = "%s@%s" % (service, hostname) if 'KRB5_KTNAME' not in environ: app.logger.warn("Kerberos: set KRB5_KTNAME to your keytab file") else: try: principal = kerberos.getServerPrincipalDetails(service, hostname) except kerberos.KrbError as exc: app.logger.warn("Kerberos: %s" % exc.message[0]) else: app.logger.info("Kerberos: server is %s" % principal)
def check_ticket(self, ticket): init_context_res = chech_ticket_res = -1 principal = realm = orig_service = target_name = service = '' try: principal = kerberos.getServerPrincipalDetails( self._service_type, self._hostname) orig_service, realm = self._split_principal(principal) init_context_res, context = kerberos.authGSSServerInit('') chech_ticket_res = kerberos.authGSSServerStep(context, ticket) target_name = kerberos.authGSSServerTargetName(context) service, _ = self._split_principal(target_name) response = kerberos.authGSSServerResponse(context) principal = kerberos.authGSSServerUserName(context) kerberos.authGSSServerClean(context) except kerberos.GSSError: if init_context_res != 1: ERROR("Error init kerberos context") elif chech_ticket_res == -1: ERROR("Ticket is not correct:" + ticket) elif service.lower() != orig_service.lower(): ERROR('Bad credentials: wrong target name ' + target_name) return '', '', '' except kerberos.KrbError: ERROR("Internal kerberos error") return '', '', '' # del kerberos username, realm = principal.split('@') return response, username, realm
def auth_basic(self, auth_header): """ Manages the basic authorization process with kerberos. Returns a username or raises a BasicAuthError. """ # The authorization header is base64 encoded, we need it decoded auth_decoded = base64.decodebytes(auth_header.encode('utf8')).decode() # Decoded format is <username>:<password> so we need to split it userstring, password = auth_decoded.split(':', maxsplit=1) try: # If the user specifies a realm in the username verify # it matches the configured SPNEGO realm so we # don't open ourselves up to KDC spoofing username, realm = userstring.split('@', maxsplit=1) if realm != settings.SPNEGO_REALM: raise NotAuthorized except ValueError: username = userstring kerberos.checkPassword( username, password, kerberos.getServerPrincipalDetails('HTTP', settings.SPNEGO_HOSTNAME), settings.SPNEGO_REALM) return username
def init_kerberos(app, service='HTTP', hostname=gethostname(), principal=None): ''' Configure the GSSAPI service name, and validate the presence of the appropriate principal in the kerberos keytab. :param app: a flask application :type app: flask.Flask :param service: GSSAPI service name :type service: str :param hostname: hostname the service runs under :type hostname: str ''' global _SERVICE_NAME _SERVICE_NAME = "%s@%s" % (service, hostname) if 'KRB5_KTNAME' not in environ: app.logger.error("Kerberos: set KRB5_KTNAME to your keytab file") return False elif principal is None: try: principal = kerberos.getServerPrincipalDetails(service, hostname) except kerberos.KrbError as exc: app.logger.error("Kerberos: %s" % exc.message[0]) app.logger.error("ServiceName: %s" % _SERVICE_NAME) return False app.logger.info("Kerberos: server is %s" % principal) return True
def init_config(self, config): service = config.setdefault('KRB5_SERVICE_NAME', b'HTTP') hostname = config.setdefault('KRB5_HOSTNAME', socket.gethostname()) self._service_name = b'{}@{}'.format(service, hostname) try: principal = kerberos.getServerPrincipalDetails(service, hostname) except kerberos.KrbError: log.warn("Error initializing Kerberos for %s", self._service_name, exc_info=True) else: log.info("Server principal is %s", principal)
def __init__(self, app, hostname=None, unauthorized=None, forbidden=None, auth_required_callback=None): if hostname is None: hostname = socket.gethostname() if unauthorized is None: unauthorized = (b'Unauthorized', 'text/plain') elif isinstance(unauthorized, basestring): unauthorized = (unauthorized, 'text/plain') unauthorized = (ensure_bytestring(unauthorized[0]), unauthorized[1]) if forbidden is None: forbidden = (b'Forbidden', 'text/plain') elif isinstance(forbidden, basestring): forbidden = (forbidden, 'text/plain') forbidden = (ensure_bytestring(forbidden[0]), forbidden[1]) if auth_required_callback is None: auth_required_callback = lambda x: True self.application = app # WSGI Application self.service = 'HTTP@%s' % hostname # GSS Service self.unauthorized = unauthorized # 401 response text/content-type self.forbidden = forbidden # 403 response text/content-type self.auth_required_callback = auth_required_callback if 'KRB5_KTNAME' in os.environ: try: principal = kerberos.getServerPrincipalDetails( 'HTTP', hostname) except kerberos.KrbError as exc: LOG.warning('KerberosAuthMiddleware: %s', exc) else: LOG.debug('KerberosAuthMiddleware is identifying as %s', principal) else: LOG.warning( 'KerberosAuthMiddleware: set KRB5_KTNAME to your keytab file')
def init_app(app): """Initializes application with kerberos""" hostname = app.config.get('SERVER_NAME') if not hostname: hostname = getfqdn() log.info("Kerberos: hostname %s", hostname) service = 'airflow' _KERBEROS_SERVICE.service_name = "{}@{}".format(service, hostname) if 'KRB5_KTNAME' not in os.environ: os.environ['KRB5_KTNAME'] = conf.get('kerberos', 'keytab') try: log.info("Kerberos init: %s %s", service, hostname) principal = kerberos.getServerPrincipalDetails(service, hostname) except kerberos.KrbError as err: log.warning("Kerberos: %s", err) else: log.info("Kerberos API: server is %s", principal)
def init_app(app): global _SERVICE_NAME hostname = app.config.get('SERVER_NAME') if not hostname: hostname = getfqdn() logging.info("Kerberos: hostname {}".format(hostname)) service = 'airflow' _SERVICE_NAME = "{}@{}".format(service, hostname) if 'KRB5_KTNAME' not in os.environ: os.environ['KRB5_KTNAME'] = conf.get('kerberos', 'keytab') try: logging.info("Kerberos init: {} {}".format(service, hostname)) principal = kerberos.getServerPrincipalDetails(service, hostname) except kerberos.KrbError as err: logging.warn("Kerberos: {}".format(err)) else: logging.info("Kerberos API: server is {}".format(principal))
def init_app(app): global _SERVICE_NAME hostname = app.config.get('SERVER_NAME') if not hostname: hostname = getfqdn() log.info("Kerberos: hostname %s", hostname) service = 'airflow' _SERVICE_NAME = "{}@{}".format(service, hostname) if 'KRB5_KTNAME' not in os.environ: os.environ['KRB5_KTNAME'] = conf.get('kerberos', 'keytab') try: log.info("Kerberos init: %s %s", service, hostname) principal = kerberos.getServerPrincipalDetails(service, hostname) except kerberos.KrbError as err: log.warning("Kerberos: %s", err) else: log.info("Kerberos API: server is %s", principal)
def __init__(self, principal=None, type=None, hostname=None): """ @param principal: full Kerberos principal (e.g., 'HTTP/[email protected]'). If C{None} then the type and hostname arguments are used instead. @type service: str @param type: service type for Kerberos (e.g., 'HTTP'). Must be C{None} if principal used. @type type: str @param hostname: hostname for this server. Must be C{None} if principal used. @type hostname: str """ # Only certain combinations of arguments allowed assert (principal and not type and not hostname) or (not principal and type and hostname) if not principal: # Look up the Kerberos principal given the service type and hostname, and extract # the realm and a service principal value for later use. try: principal = kerberos.getServerPrincipalDetails(type, hostname) except kerberos.KrbError, ex: self.log_error("getServerPrincipalDetails: %s" % (ex[0],)) raise ValueError('Authentication System Failure: %s' % (ex[0],))
def __init__(self, app, hostname=None, unauthorized=None, forbidden=None, auth_required_callback=None): if hostname is None: hostname = socket.gethostname() if unauthorized is None: unauthorized = (b'Unauthorized', 'text/plain') elif isinstance(unauthorized, basestring): unauthorized = (unauthorized, 'text/plain') unauthorized = (ensure_bytestring(unauthorized[0]), unauthorized[1]) if forbidden is None: forbidden = (b'Forbidden', 'text/plain') elif isinstance(forbidden, basestring): forbidden = (forbidden, 'text/plain') forbidden = (ensure_bytestring(forbidden[0]), forbidden[1]) if auth_required_callback is None: auth_required_callback = lambda x: True self.application = app # WSGI Application self.service = 'HTTP@%s' % hostname # GSS Service self.unauthorized = unauthorized # 401 response text/content-type self.forbidden = forbidden # 403 response text/content-type self.auth_required_callback = auth_required_callback if 'KRB5_KTNAME' in os.environ: try: principal = kerberos.getServerPrincipalDetails('HTTP', hostname) except kerberos.KrbError as exc: LOG.warning('KerberosAuthMiddleware: %s', exc) else: LOG.debug('KerberosAuthMiddleware is identifying as %s', principal) else: LOG.warning('KerberosAuthMiddleware: set KRB5_KTNAME to your keytab file')
# Vanilla Kerberos provides only username. # AD also embeds PAC (Privilege Attribute Certificate), which # is supposed to be sent via HTTP headers and it contains # the groups user is part of. # Even then we would have to manually look up the e-mail # address eg via LDAP, hence to keep things simple # we simply use Kerberos to authenticate. FQDN = socket.getaddrinfo(socket.gethostname(), 0, flags=socket.AI_CANONNAME)[0][3] if not os.getenv("KRB5_KTNAME"): click.echo("Kerberos keytab not specified, set environment variable 'KRB5_KTNAME'", err=True) exit(250) try: principal = kerberos.getServerPrincipalDetails("HTTP", FQDN) except kerberos.KrbError as exc: click.echo("Failed to initialize Kerberos, reason: %s" % exc, err=True) exit(249) else: click.echo("Kerberos enabled, service principal is HTTP/%s" % FQDN) def login_required(func): def wrapped(resource, req, resp, *args, **kwargs): authorization = req.get_header("Authorization") if not authorization: resp.append_header("WWW-Authenticate", "Negotiate") raise falcon.HTTPUnauthorized("Unauthorized", "No Kerberos ticket offered?") token = ''.join(authorization.split()[1:])
def _getKerberosDetails(self): self._kerberosPrincipal = kerberos.getServerPrincipalDetails("HTTP", config.kerberos_hostname) (self._kerberosServiceType, split1) = self._kerberosPrincipal.split("/", 1) (self._kerberosService, self._kerberosRealm) = split1.split("@", 1)
def test_service_principal(): expected = "HTTP/%s@%s" % (hostname, realm.upper()) actual = kerberos.getServerPrincipalDetails("HTTP", hostname) assert actual == expected, "The returned SPN does not match with test expectations"
# the groups user is part of. # Even then we would have to manually look up the e-mail # address eg via LDAP, hence to keep things simple # we simply use Kerberos to authenticate. FQDN = socket.getaddrinfo(socket.gethostname(), 0, flags=socket.AI_CANONNAME)[0][3] if not os.getenv("KRB5_KTNAME"): click.echo( "Kerberos keytab not specified, set environment variable 'KRB5_KTNAME'", err=True) exit(250) try: principal = kerberos.getServerPrincipalDetails("HTTP", FQDN) except kerberos.KrbError as exc: click.echo("Failed to initialize Kerberos, reason: %s" % exc, err=True) exit(249) else: click.echo("Kerberos enabled, service principal is HTTP/%s" % FQDN) def login_required(func): def wrapped(resource, req, resp, *args, **kwargs): authorization = req.get_header("Authorization") if not authorization: resp.append_header("WWW-Authenticate", "Negotiate") raise falcon.HTTPUnauthorized("Unauthorized", "No Kerberos ticket offered?")
def init_kerberos( app, service="HTTP", hostname=gethostname(), mongodb_uri="mongodb://*****:*****@%s" % (service, hostname) _MAX_CSRF_TIME = max_csrf_time _LOGIN_PAGE = login_page _LOGOUT_PAGE = logout_page _MAX_LOGIN_FAILURES = max_login_failures _PASS_MIN_LEN = pass_min_len _PASS_MAX_LEN = pass_max_len _MONGODB_URI = mongodb_uri logger = logging.getLogger(__name__) # Get mongodb connection try: _c = _auto_reconnect(pymongo.MongoClient(mongodb_uri)) parsed_uri = pymongo.uri_parser.parse_uri(mongodb_uri) mongo_db = parsed_uri.get("database") or "logins" _db = _c[mongo_db] mongo_collection = parsed_uri.get("collection") or "logins" _LOGINS = _db[mongo_collection] except pymongo.errors.PyMongoError as e: logger.error("Error: %s - connecting to database %s!" % (e, mongodb_uri), exc_info=1) if "KRB5_KTNAME" not in environ: logger.warn("Kerberos: set KRB5_KTNAME to your keytab file") else: try: principal = kerberos.getServerPrincipalDetails(service, hostname) except kerberos.KrbError as exc: logger.warn("Kerberos: %s" % exc) else: logger.info("Kerberos: server is %s" % principal) _REALM = principal.split("@")[1] app.mount(_APP_PREFIX, login_app)
def init_kerberos(app, service='HTTP', hostname=gethostname(), mongodb_uri='mongodb://*****:*****@%s" % (service, hostname) _MAX_CSRF_TIME = max_csrf_time _LOGIN_PAGE = login_page _LOGOUT_PAGE = logout_page _MAX_LOGIN_FAILURES = max_login_failures _PASS_MIN_LEN = pass_min_len _PASS_MAX_LEN = pass_max_len _MONGODB_URI = mongodb_uri logger = logging.getLogger(__name__) # Get mongodb connection try: _c = _auto_reconnect(pymongo.MongoClient(mongodb_uri)) parsed_uri = pymongo.uri_parser.parse_uri(mongodb_uri) mongo_db = parsed_uri.get('database') or 'logins' _db = _c[mongo_db] mongo_collection = parsed_uri.get('collection') or 'logins' _LOGINS = _db[mongo_collection] except pymongo.errors.PyMongoError as e: logger.error('Error: %s - connecting to database %s!' % (e, mongodb_uri), exc_info=1) if 'KRB5_KTNAME' not in environ: logger.warn("Kerberos: set KRB5_KTNAME to your keytab file") else: try: principal = kerberos.getServerPrincipalDetails(service, hostname) except kerberos.KrbError as exc: logger.warn("Kerberos: %s" % exc) else: logger.info("Kerberos: server is %s" % principal) _REALM = principal.split('@')[1] app.mount(_APP_PREFIX, login_app)
def _getKerberosDetails(self): self._kerberosPrincipal = kerberos.getServerPrincipalDetails( "HTTP", config.kerberos_hostname) (self._kerberosServiceType, split1) = self._kerberosPrincipal.split("/", 1) (self._kerberosService, self._kerberosRealm) = split1.split("@", 1)