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

[HOLD] move backoff settings, send email, and create client to config #1181

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
126 changes: 126 additions & 0 deletions fence/config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import os

import requests
from yaml import safe_load as yaml_load
import urllib.parse

Expand All @@ -7,6 +9,12 @@

from cdislogging import get_logger

from fence import get_SQLAlchemyDriver
from fence.utils import log_backoff_retry, log_backoff_giveup, exception_do_not_retry, generate_client_credentials, \
logger
from fence.models import Client, User, query_for_user
from fence.errors import NotFound

logger = get_logger(__name__)

DEFAULT_CFG_PATH = os.path.join(
Expand Down Expand Up @@ -175,3 +183,121 @@ def _validate_parent_child_studies(dbgap_configs):


config = FenceConfig(DEFAULT_CFG_PATH)
DEFAULT_BACKOFF_SETTINGS = {
"on_backoff": log_backoff_retry,
"on_giveup": log_backoff_giveup,
"max_tries": config["DEFAULT_BACKOFF_SETTINGS_MAX_TRIES"],
"giveup": exception_do_not_retry,
}


def send_email(from_email, to_emails, subject, text, smtp_domain):
"""
Send email to group of emails using mail gun api.

https://app.mailgun.com/

Args:
from_email(str): from email
to_emails(list): list of emails to receive the messages
text(str): the text message
smtp_domain(dict): smtp domain server

{
"smtp_hostname": "smtp.mailgun.org",
"default_login": "[email protected]",
"api_url": "https://api.mailgun.net/v3/mailgun.planx-pla.net",
"smtp_password": "password", # pragma: allowlist secret
"api_key": "api key" # pragma: allowlist secret
}

Returns:
Http response

Exceptions:
KeyError

"""
if smtp_domain not in config["GUN_MAIL"] or not config["GUN_MAIL"].get(
smtp_domain
).get("smtp_password"):
raise NotFound(
"SMTP Domain '{}' does not exist in configuration for GUN_MAIL or "
"smtp_password was not provided. "
"Cannot send email.".format(smtp_domain)
)

api_key = config["GUN_MAIL"][smtp_domain].get("api_key", "")
email_url = config["GUN_MAIL"][smtp_domain].get("api_url", "") + "/messages"

return requests.post(
email_url,
auth=("api", api_key),
data={"from": from_email, "to": to_emails, "subject": subject, "text": text},
)


def create_client(
DB,
username=None,
urls=[],
name="",
description="",
auto_approve=False,
is_admin=False,
grant_types=None,
confidential=True,
arborist=None,
policies=None,
allowed_scopes=None,
expires_in=None,
):
client_id, client_secret, hashed_secret = generate_client_credentials(confidential)
if arborist is not None:
arborist.create_client(client_id, policies)
driver = get_SQLAlchemyDriver(DB)
auth_method = "client_secret_basic" if confidential else "none"

allowed_scopes = allowed_scopes or config["CLIENT_ALLOWED_SCOPES"]
if not set(allowed_scopes).issubset(set(config["CLIENT_ALLOWED_SCOPES"])):
raise ValueError(
"Each allowed scope must be one of: {}".format(
config["CLIENT_ALLOWED_SCOPES"]
)
)

if "openid" not in allowed_scopes:
allowed_scopes.append("openid")
logger.warning('Adding required "openid" scope to list of allowed scopes.')

with driver.session as s:
user = None
if username:
user = query_for_user(session=s, username=username)
if not user:
user = User(username=username, is_admin=is_admin)
s.add(user)

if s.query(Client).filter(Client.name == name).first():
if arborist is not None:
arborist.delete_client(client_id)
raise Exception("client {} already exists".format(name))

client = Client(
client_id=client_id,
client_secret=hashed_secret,
user=user,
redirect_uris=urls,
allowed_scopes=" ".join(allowed_scopes),
description=description,
name=name,
auto_approve=auto_approve,
grant_types=grant_types,
is_confidential=confidential,
token_endpoint_auth_method=auth_method,
expires_in=expires_in,
)
s.add(client)
s.commit()

return client_id, client_secret
3 changes: 1 addition & 2 deletions fence/resources/audit/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
import requests
import traceback

from fence.config import config
from fence.config import config, DEFAULT_BACKOFF_SETTINGS
from fence.errors import InternalError
from fence.resources.audit.utils import is_audit_enabled
from fence.utils import DEFAULT_BACKOFF_SETTINGS


class AuditServiceClient:
Expand Down
4 changes: 2 additions & 2 deletions fence/resources/google/access_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import fence
from cdislogging import get_logger

from fence.config import config
from fence.config import config, DEFAULT_BACKOFF_SETTINGS
from fence.errors import NotFound, NotSupported, UserError
from fence.models import (
User,
Expand All @@ -33,7 +33,7 @@
get_monitoring_service_account_email,
is_google_managed_service_account,
)
from fence.utils import get_valid_expiration_from_request, DEFAULT_BACKOFF_SETTINGS
from fence.utils import get_valid_expiration_from_request

logger = get_logger(__name__)

Expand Down
4 changes: 1 addition & 3 deletions fence/resources/google/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from userdatamodel.user import GoogleProxyGroup, User, AccessPrivilege

from fence.auth import current_token
from fence.config import config
from fence.config import config, DEFAULT_BACKOFF_SETTINGS
from fence.errors import NotSupported, InternalError, UserError
from fence.models import (
GoogleServiceAccount,
Expand All @@ -38,8 +38,6 @@

from cdislogging import get_logger

from fence.utils import DEFAULT_BACKOFF_SETTINGS

logger = get_logger(__name__)


Expand Down
3 changes: 1 addition & 2 deletions fence/resources/openid/ras_oauth2.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from gen3authz.client.arborist.errors import ArboristError


from fence.config import config
from fence.config import config, DEFAULT_BACKOFF_SETTINGS
from fence.models import (
GA4GHVisaV1,
IdentityProvider,
Expand All @@ -26,7 +26,6 @@
create_user,
)
from fence.jwt.validate import validate_jwt
from fence.utils import DEFAULT_BACKOFF_SETTINGS
from fence.errors import InternalError
from .idp_oauth2 import Oauth2ClientBase

Expand Down
3 changes: 1 addition & 2 deletions fence/scripting/fence_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@
get_client_expires_at,
)
from fence.scripting.google_monitor import email_users_without_access, validation_check
from fence.config import config
from fence.config import config, create_client
from fence.sync.sync_users import UserSyncer
from fence.utils import (
create_client,
get_valid_expiration,
generate_client_credentials,
get_SQLAlchemyDriver,
Expand Down
5 changes: 3 additions & 2 deletions fence/scripting/google_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from cdislogging import get_logger

import fence.config
from fence.resources.google.validity import (
GoogleProjectValidity,
GoogleServiceAccountValidity,
Expand Down Expand Up @@ -514,7 +515,7 @@ def _send_emails_informing_service_account_removal(
for reason in removal_reasons:
content += "\n\t\t\t - {}".format(reason)

return utils.send_email(from_email, to_emails, subject, content, domain)
return fence.config.send_email(from_email, to_emails, subject, content, domain)


def _get_users_without_access(db, auth_ids, user_emails, check_linking):
Expand Down Expand Up @@ -609,7 +610,7 @@ def email_user_without_access(user_email, projects, google_project_id):
text = config["PROBLEM_USER_EMAIL_NOTIFICATION"]["content"]
content = text.format(google_project_id, ",".join(projects))

return utils.send_email(from_email, to_emails, subject, content, domain)
return fence.config.send_email(from_email, to_emails, subject, content, domain)


def email_users_without_access(
Expand Down
4 changes: 2 additions & 2 deletions fence/sync/sync_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from sqlalchemy.exc import IntegrityError
from sqlalchemy import func

from fence.config import config
from fence.config import config, DEFAULT_BACKOFF_SETTINGS
from fence.models import (
AccessPrivilege,
AuthorizationProvider,
Expand All @@ -43,7 +43,7 @@
from fence.resources.google.access_utils import GoogleUpdateException
from fence.sync import utils
from fence.sync.passport_sync.ras_sync import RASVisa
from fence.utils import get_SQLAlchemyDriver, DEFAULT_BACKOFF_SETTINGS
from fence.utils import get_SQLAlchemyDriver


def _format_policy_id(path, privilege):
Expand Down
Loading
Loading