Merge pull request #3414 from charhate/membership
Configurable user memberships endpoint
This commit is contained in:
commit
6fd7684d2d
@ -712,6 +712,33 @@ For more information about how to use social logins, see: `Satellizer <https://g
|
||||
|
||||
PING_AUTH_ENDPOINT = "https://<yourpingserver>/oauth2/authorize"
|
||||
|
||||
.. data:: PING_USER_MEMBERSHIP_URL
|
||||
:noindex:
|
||||
|
||||
An optional additional endpoint to learn membership details post the user validation.
|
||||
|
||||
::
|
||||
|
||||
PING_USER_MEMBERSHIP_URL = "https://<yourmembershipendpoint>"
|
||||
|
||||
.. data:: PING_USER_MEMBERSHIP_TLS_PROVIDER
|
||||
:noindex:
|
||||
|
||||
A custom TLS session provider plugin name
|
||||
|
||||
::
|
||||
|
||||
PING_USER_MEMBERSHIP_TLS_PROVIDER = "slug-name"
|
||||
|
||||
.. data:: PING_USER_MEMBERSHIP_SERVICE
|
||||
:noindex:
|
||||
|
||||
Membership service name used by PING_USER_MEMBERSHIP_TLS_PROVIDER to create a session
|
||||
|
||||
::
|
||||
|
||||
PING_USER_MEMBERSHIP_SERVICE = "yourmembershipservice"
|
||||
|
||||
.. data:: OAUTH2_SECRET
|
||||
:noindex:
|
||||
|
||||
|
@ -285,6 +285,17 @@ The `ExportPlugin` object requires the implementation of one function::
|
||||
Support of various formats sometimes relies on external tools system calls. Always be mindful of sanitizing any input to these calls.
|
||||
|
||||
|
||||
Custom TLS Provider
|
||||
------
|
||||
|
||||
Managing TLS at the enterprise scale could be hard and often organizations offer custom wrapper implementations. It could
|
||||
be ideal to use those while making calls to internal services. The `TLSPlugin` would help to achieve this. It requires the
|
||||
implementation of one function which creates a TLS session::
|
||||
|
||||
def session(self, server_application):
|
||||
# return active session
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
:license: Apache, see LICENSE for more details.
|
||||
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
|
||||
"""
|
||||
import json
|
||||
|
||||
import jwt
|
||||
import base64
|
||||
import requests
|
||||
@ -23,7 +25,7 @@ from lemur.roles import service as role_service
|
||||
from lemur.logs import service as log_service
|
||||
from lemur.auth.service import create_token, fetch_token_header, get_rsa_public_key
|
||||
from lemur.auth import ldap
|
||||
|
||||
from lemur.plugins.base import plugins
|
||||
|
||||
mod = Blueprint("auth", __name__)
|
||||
api = Api(mod)
|
||||
@ -138,6 +140,47 @@ def retrieve_user(user_api_url, access_token):
|
||||
return user, profile
|
||||
|
||||
|
||||
def retrieve_user_memberships(user_api_url, user_membership_api_url, access_token):
|
||||
user, profile = retrieve_user(user_api_url, access_token)
|
||||
|
||||
if user_membership_api_url is None:
|
||||
return user, profile
|
||||
"""
|
||||
Potentially, below code can be made more generic i.e., plugin driven. Unaware of the usage of this
|
||||
code across the community, current implementation is config driven. Without user_membership_api_url
|
||||
configured, it is backward compatible.
|
||||
"""
|
||||
tls_provider = plugins.get(current_app.config.get("PING_USER_MEMBERSHIP_TLS_PROVIDER"))
|
||||
|
||||
# put user id in url
|
||||
user_membership_api_url = user_membership_api_url.replace("%user_id%", profile["userId"])
|
||||
|
||||
session = tls_provider.session(current_app.config.get("PING_USER_MEMBERSHIP_SERVICE"))
|
||||
headers = {"Content-Type": "application/json"}
|
||||
data = {"relation": "DIRECT_ONLY", "groupFilter": {"type": "GOOGLE"}, "size": 500}
|
||||
user_membership = {"email": profile["email"],
|
||||
"thumbnailPhotoUrl": profile["thumbnailPhotoUrl"],
|
||||
"googleGroups": []}
|
||||
while True:
|
||||
# retrieve information about the current user memberships
|
||||
r = session.post(user_membership_api_url, data=json.dumps(data), headers=headers)
|
||||
|
||||
if r.status_code == 200:
|
||||
response = r.json()
|
||||
membership_details = response["data"]
|
||||
for membership in membership_details:
|
||||
user_membership["googleGroups"].append(membership["membership"]["name"])
|
||||
|
||||
if "nextPageToken" in response and response["nextPageToken"]:
|
||||
data["nextPageToken"] = response["nextPageToken"]
|
||||
else:
|
||||
break
|
||||
else:
|
||||
current_app.logger.error(f"Response Code:{r.status_code} {r.text}")
|
||||
break
|
||||
return user, user_membership
|
||||
|
||||
|
||||
def create_user_roles(profile):
|
||||
"""Creates new roles based on profile information.
|
||||
|
||||
@ -156,7 +199,7 @@ def create_user_roles(profile):
|
||||
description="This is a google group based role created by Lemur",
|
||||
third_party=True,
|
||||
)
|
||||
if not role.third_party:
|
||||
if (group != 'admin') and (not role.third_party):
|
||||
role = role_service.set_third_party(role.id, third_party_status=True)
|
||||
roles.append(role)
|
||||
else:
|
||||
@ -375,7 +418,6 @@ class Ping(Resource):
|
||||
|
||||
# you can either discover these dynamically or simply configure them
|
||||
access_token_url = current_app.config.get("PING_ACCESS_TOKEN_URL")
|
||||
user_api_url = current_app.config.get("PING_USER_API_URL")
|
||||
|
||||
secret = current_app.config.get("PING_SECRET")
|
||||
|
||||
@ -391,7 +433,12 @@ class Ping(Resource):
|
||||
error_code = validate_id_token(id_token, args["clientId"], jwks_url)
|
||||
if error_code:
|
||||
return error_code
|
||||
user, profile = retrieve_user(user_api_url, access_token)
|
||||
|
||||
user, profile = retrieve_user_memberships(
|
||||
current_app.config.get("PING_USER_API_URL"),
|
||||
current_app.config.get("PING_USER_MEMBERSHIP_URL"),
|
||||
access_token
|
||||
)
|
||||
roles = create_user_roles(profile)
|
||||
update_user(user, profile, roles)
|
||||
|
||||
|
@ -3,3 +3,4 @@ from .issuer import IssuerPlugin # noqa
|
||||
from .source import SourcePlugin # noqa
|
||||
from .notification import NotificationPlugin, ExpirationNotificationPlugin # noqa
|
||||
from .export import ExportPlugin # noqa
|
||||
from .tls import TLSPlugin # noqa
|
||||
|
20
lemur/plugins/bases/tls.py
Normal file
20
lemur/plugins/bases/tls.py
Normal file
@ -0,0 +1,20 @@
|
||||
"""
|
||||
.. module: lemur.plugins.bases.tls
|
||||
:platform: Unix
|
||||
:copyright: (c) 2021 by Netflix Inc., see AUTHORS for more
|
||||
:license: Apache, see LICENSE for more details.
|
||||
|
||||
.. moduleauthor:: Sayali Charhate <scharhate@netflix.com>
|
||||
"""
|
||||
from lemur.plugins.base import Plugin
|
||||
|
||||
|
||||
class TLSPlugin(Plugin):
|
||||
"""
|
||||
This is the base class from which all supported
|
||||
tls session providers will inherit from.
|
||||
"""
|
||||
type = "tls"
|
||||
|
||||
def session(self, server_application):
|
||||
raise NotImplementedError
|
Loading…
Reference in New Issue
Block a user