Allow use of API keys as alternative to account auth token for Twilio credentials

This commit is contained in:
Michael Derynck 2022-10-11 14:47:16 -06:00
parent de3f45929b
commit bc16795fa8
4 changed files with 66 additions and 8 deletions

View file

@ -35,6 +35,8 @@ class LiveSetting(models.Model):
AVAILABLE_NAMES = (
"TWILIO_ACCOUNT_SID",
"TWILIO_AUTH_TOKEN",
"TWILIO_API_KEY_SID",
"TWILIO_API_KEY_SECRET",
"TWILIO_NUMBER",
"TWILIO_VERIFY_SERVICE_SID",
"TELEGRAM_TOKEN",
@ -80,14 +82,24 @@ class LiveSetting(models.Model):
"after you update them."
),
"TWILIO_ACCOUNT_SID": (
"Twilio username to allow amixr send sms and make phone calls, "
"Twilio account SID/username to allow OnCall send sms and make phone calls, "
"<a href='https://support.twilio.com/hc/en-us/articles/223136027-Auth-Tokens-and-How-to-Change-Them' target='_blank'>"
"more info</a>."
"more info</a>. Required."
),
"TWILIO_API_KEY_SID": (
"Twilio API key SID/username to allow OnCall send sms and make phone calls, "
"<a href='https://www.twilio.com/docs/iam/keys/api-key' target='_blank'>"
"more info</a>. Either (TWILIO_API_KEY_SID + TWILIO_API_KEY_SECRET) or TWILIO_AUTH_TOKEN is required."
),
"TWILIO_API_KEY_SECRET": (
"Twilio API key secret/password to allow OnCall send sms and make phone calls, "
"<a href='https://www.twilio.com/docs/iam/keys/api-key' target='_blank'>"
"more info</a>. Either (TWILIO_API_KEY_SID + TWILIO_API_KEY_SECRET) or TWILIO_AUTH_TOKEN is required."
),
"TWILIO_AUTH_TOKEN": (
"Twilio password to allow amixr send sms and make calls, "
"Twilio password to allow OnCall send sms and make calls, "
"<a href='https://support.twilio.com/hc/en-us/articles/223136027-Auth-Tokens-and-How-to-Change-Them' target='_blank'>"
"more info</a>."
"more info</a>. Either (TWILIO_API_KEY_SID + TWILIO_API_KEY_SECRET) or TWILIO_AUTH_TOKEN is required."
),
"TWILIO_NUMBER": (
"Number from which you will receive calls and SMS, "

View file

@ -50,24 +50,63 @@ class LiveSettingValidator:
check_fn = getattr(self, check_fn_name)
return check_fn(self.live_setting.value)
@classmethod
def _check_twilio_api_key_sid(cls, twilio_api_key_sid):
if live_settings.TWILIO_AUTH_TOKEN:
return
try:
Client(
twilio_api_key_sid, live_settings.TWILIO_API_KEY_SECRET, live_settings.TWILIO_ACCOUNT_SID
).api.applications.list(limit=1)
except Exception as e:
return cls._prettify_twilio_error(e)
@classmethod
def _check_twilio_api_key_secret(cls, twilio_api_key_secret):
if live_settings.TWILIO_AUTH_TOKEN:
return
try:
Client(
live_settings.TWILIO_API_KEY_SID, twilio_api_key_secret, live_settings.TWILIO_ACCOUNT_SID
).api.applications.list(limit=1)
except Exception as e:
return cls._prettify_twilio_error(e)
@classmethod
def _check_twilio_account_sid(cls, twilio_account_sid):
try:
Client(twilio_account_sid, live_settings.TWILIO_AUTH_TOKEN).api.accounts.list(limit=1)
if live_settings.TWILIO_API_KEY_SID and live_settings.TWILIO_API_KEY_SECRET:
Client(
live_settings.TWILIO_API_KEY_SID, live_settings.TWILIO_API_KEY_SECRET, twilio_account_sid
).api.applications.list(limit=1)
else:
Client(twilio_account_sid, live_settings.TWILIO_AUTH_TOKEN).api.applications.list(limit=1)
except Exception as e:
return cls._prettify_twilio_error(e)
@classmethod
def _check_twilio_auth_token(cls, twilio_auth_token):
if live_settings.TWILIO_API_KEY_SID and live_settings.TWILIO_API_KEY_SECRET:
return
try:
Client(live_settings.TWILIO_ACCOUNT_SID, twilio_auth_token).api.accounts.list(limit=1)
Client(live_settings.TWILIO_ACCOUNT_SID, twilio_auth_token).api.applications.list(limit=1)
except Exception as e:
return cls._prettify_twilio_error(e)
@classmethod
def _check_twilio_verify_service_sid(cls, twilio_verify_service_sid):
try:
twilio_client = Client(live_settings.TWILIO_ACCOUNT_SID, live_settings.TWILIO_AUTH_TOKEN)
if live_settings.TWILIO_API_KEY_SID and live_settings.TWILIO_API_KEY_SECRET:
twilio_client = Client(
live_settings.TWILIO_API_KEY_SID,
live_settings.TWILIO_API_KEY_SECRET,
live_settings.TWILIO_ACCOUNT_SID,
)
else:
twilio_client = Client(live_settings.TWILIO_ACCOUNT_SID, live_settings.TWILIO_AUTH_TOKEN)
twilio_client.verify.services(twilio_verify_service_sid).rate_limits.list(limit=1)
except Exception as e:
return cls._prettify_twilio_error(e)

View file

@ -17,7 +17,12 @@ logger = logging.getLogger(__name__)
class TwilioClient:
@property
def twilio_api_client(self):
return Client(live_settings.TWILIO_ACCOUNT_SID, live_settings.TWILIO_AUTH_TOKEN)
if live_settings.TWILIO_API_KEY_SID and live_settings.TWILIO_API_KEY_SECRET:
return Client(
live_settings.TWILIO_API_KEY_SID, live_settings.TWILIO_API_KEY_SECRET, live_settings.TWILIO_ACCOUNT_SID
)
else:
return Client(live_settings.TWILIO_ACCOUNT_SID, live_settings.TWILIO_AUTH_TOKEN)
@property
def twilio_number(self):

View file

@ -56,6 +56,8 @@ FEATURE_WEB_SCHEDULES_ENABLED = getenv_boolean("FEATURE_WEB_SCHEDULES_ENABLED",
GRAFANA_CLOUD_ONCALL_HEARTBEAT_ENABLED = getenv_boolean("GRAFANA_CLOUD_ONCALL_HEARTBEAT_ENABLED", default=True)
GRAFANA_CLOUD_NOTIFICATIONS_ENABLED = getenv_boolean("GRAFANA_CLOUD_NOTIFICATIONS_ENABLED", default=True)
TWILIO_API_KEY_SID = os.environ.get("TWILIO_API_KEY_SID")
TWILIO_API_KEY_SECRET = os.environ.get("TWILIO_API_KEY_SECRET")
TWILIO_ACCOUNT_SID = os.environ.get("TWILIO_ACCOUNT_SID")
TWILIO_AUTH_TOKEN = os.environ.get("TWILIO_AUTH_TOKEN")
TWILIO_NUMBER = os.environ.get("TWILIO_NUMBER")