Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fd92366
Initial commit - add_team_to_repo command
Nov 9, 2017
ee31539
fix typo and reference team by name instead of id
Nov 9, 2017
320a362
Change to more accurate function name
Nov 9, 2017
f9a9e26
Apply changes and add team_must_exist decorator
Nov 21, 2017
6253c8b
replace inline checks with decorator
Nov 21, 2017
079e74a
fix decorator and remove redundant calls to find_team_by_name
Nov 22, 2017
1eebda1
Merge pull request #78 from yaron-idan/issue28
mikegrima Nov 22, 2017
ac4241f
Implemented #57. This allows batch outside collaborator repo adding.
Nov 27, 2017
c3516ae
Merge pull request #79 from mikegrima/issue57
mikegrima Nov 27, 2017
9aa5804
Added multiple-domain DUO support.
Nov 30, 2017
c53e42b
Merge pull request #80 from mikegrima/issue77
mikegrima Dec 3, 2017
be4bb47
Fixed bug #81.
Dec 5, 2017
d43ce54
Merge pull request #82 from mikegrima/issue81
mikegrima Dec 5, 2017
a2ad149
Build app entirely frmo Dockerfile
Dec 20, 2017
4880ea5
fix rm of tar file
Dec 20, 2017
775c21c
change deprecated MAINTAINER to label
Dec 20, 2017
82d1cbf
Merge pull request #85 from yaron-idan/issue84
mikegrima Dec 28, 2017
85da716
Added more threads to duo error messages
Jan 15, 2018
47377c5
Merge pull request #86 from mikegrima/duo_thread
mikegrima Jan 15, 2018
25849f4
Update for exit status
sbalagopal Feb 22, 2018
d56f2fc
Merge pull request #89 from sbalagopal/patch-1
mikegrima Feb 26, 2018
ce8e0fe
Addresses #83
Jul 5, 2018
b3eba1c
Merge pull request #91 from mikegrima/docupdate
mikegrima Jul 5, 2018
f79da51
Properly removes all macOS "Smart Quotes".
Jul 5, 2018
bfed674
Merge pull request #92 from mikegrima/issue87
mikegrima Jul 5, 2018
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
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ sudo: required
language: python

python:
- "3.5"
- "3.6"

install:
Expand Down
19 changes: 9 additions & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
FROM ubuntu:xenial

# Mostly Mike Grima: [email protected]
MAINTAINER NetflixOSS <[email protected]>

# Install the Python RTM bot itself:
ARG RTM_VERSION
ADD python-rtmbot-${RTM_VERSION}.tar.gz /
LABEL maintainer="[email protected]"

RUN \
# Install Python:
apt-get update && \
apt-get upgrade -y && \
apt-get install python3 python3-venv nano -y
apt-get install python3 python3-venv nano curl -y

# Install the Python RTM bot itself:
ARG RTM_VERSION="0.4.0"
ARG RTM_PATH="python-rtmbot-${RTM_VERSION}"
RUN curl -L https://github.com/slackhq/python-rtmbot/archive/${RTM_VERSION}.tar.gz > /${RTM_PATH}.tar.gz && tar xvzf python-rtmbot-0.4.0.tar.gz


# Add all the other stuff to the plugins:
COPY / /python-rtmbot-${RTM_VERSION}/hubcommander
Expand All @@ -20,19 +22,16 @@ COPY / /python-rtmbot-${RTM_VERSION}/hubcommander
RUN \
# Rename the rtmbot:
mv /python-rtmbot-${RTM_VERSION} /rtmbot && \

# Set up the VENV:
pyvenv /venv && \

# Install all the deps:
/bin/bash -c "source /venv/bin/activate && pip install --upgrade pip" && \
/bin/bash -c "source /venv/bin/activate && pip install --upgrade setuptools" && \
/bin/bash -c "source /venv/bin/activate && pip install wheel" && \
/bin/bash -c "source /venv/bin/activate && pip install /rtmbot/hubcommander" && \

# The launcher script:
mv /rtmbot/hubcommander/launch_in_docker.sh / && chmod +x /launch_in_docker.sh && \
rm /rtmbot/hubcommander/python-rtmbot-${RTM_VERSION}.tar.gz
rm /python-rtmbot-${RTM_VERSION}.tar.gz

# DEFINE YOUR ENV VARS FOR SECRETS HERE:
ENV SLACK_TOKEN="REPLACEMEINCMDLINE" \
Expand Down
31 changes: 21 additions & 10 deletions auth_plugins/duo/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,46 @@ class DuoPlugin(BotAuthPlugin):
def __init__(self):
super().__init__()

self.client = None
self.clients = {}

def setup(self, secrets, **kwargs):
if not secrets.get("DUO_IKEY") or not secrets.get("DUO_SKEY") or not secrets.get("DUO_HOST"):
raise NoSecretsProvidedError("Must provide secrets to enable authentication.")
for variable, secret in secrets.items():
if "DUO_" in variable:
domain, host, ikey, skey = secret.split(",")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems incorrect. All 3 of the variables must be provided for DUO to work.

I would suggest keeping the old code here.

self.clients[domain] = Client(ikey, skey, host)

self.client = Client(secrets["DUO_IKEY"], secrets["DUO_SKEY"], secrets["DUO_HOST"])
if not len(self.clients):
raise NoSecretsProvidedError("Must provide secrets to enable authentication.")

def authenticate(self, data, user_data, **kwargs):
# Which domain does this user belong to?
domain = user_data["profile"]["email"].split("@")[1]
if not self.clients.get(domain):
send_error(data["channel"], "💀 @{}: Duo in this bot is not configured for the domain: `{}`. It needs "
"to be configured for you to run this command."
.format(user_data["name"], domain), markdown=True, thread=data["ts"])
return False

send_info(data["channel"], "🎟 @{}: Sending a Duo notification to your device. You must approve!"
.format(user_data["name"]), markdown=True, ephemeral_user=user_data["id"])

try:
result = self._perform_auth(user_data)
result = self._perform_auth(user_data, self.clients[domain])
except InvalidDuoResponseError as idre:
send_error(data["channel"], "💀 @{}: There was a problem communicating with Duo. Got this status: {}. "
"Aborting..."
.format(user_data["name"], str(idre)), markdown=True)
.format(user_data["name"], str(idre)), thread=data["ts"], markdown=True)
return False

except CantDuoUserError as _:
send_error(data["channel"], "💀 @{}: I can't Duo authenticate you. Please consult with your identity team."
" Aborting..."
.format(user_data["name"]), markdown=True)
.format(user_data["name"]), thread=data["ts"], markdown=True)
return False

except Exception as e:
send_error(data["channel"], "💀 @{}: I encountered some issue with Duo... Here are the details: ```{}```"
.format(user_data["name"], str(e)), markdown=True)
.format(user_data["name"], str(e)), thread=data["ts"], markdown=True)
return False

if not result:
Expand All @@ -71,14 +82,14 @@ def authenticate(self, data, user_data, **kwargs):
.format(user_data["name"]), markdown=True, ephemeral_user=user_data["id"])
return True

def _perform_auth(self, user_data):
def _perform_auth(self, user_data, client):
# Push to devices:
duo_params = {
"username": user_data["profile"]["email"],
"factor": "push",
"device": "auto"
}
response, data = self.client.api_call("POST", "/auth/v2/auth", duo_params)
response, data = client.api_call("POST", "/auth/v2/auth", duo_params)
result = json.loads(data.decode("utf-8"))

if response.status != 200:
Expand Down
9 changes: 5 additions & 4 deletions bot_components/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,10 @@ def perform_additional_verification(plugin_obj, args, **kwargs):
elif argument.get("lowercase", True):
args[real_arg_name] = args[real_arg_name].lower()

# Perform cleanups? This will remove things like the annoying macOS "smart quotes",
# and the <>, {}, &lt;&gt; from the variables if `cleanup=False` not set.
# Perform cleanups? Removes <>, {}, &lt;&gt; from the variables if `cleanup=False` not set.
if argument.get("cleanup", True):
args[real_arg_name] = args[real_arg_name].replace("<", "") \
.replace(">", "").replace("{", "").replace("}", "") \
.replace(u'\u201C', "\"").replace(u'\u201D', "\"") \
.replace(u'\u2018', "\'").replace(u'\u2019', "\'") \
.replace("[", "").replace("]", "") \
.replace("&lt;", "").replace("&gt;", "")

Expand Down Expand Up @@ -140,6 +137,10 @@ def decorated_command(plugin_obj, data, user_data):

parser.add_argument(argument["name"], **argument["properties"])

# Remove all the macOS "Smart Quotes":
data["text"] = data["text"].replace(u'\u201C', "\"").replace(u'\u201D', "\"") \
.replace(u'\u2018', "\'").replace(u'\u2019', "\'")

# Remove the command from the command string:
split_args = shlex.split(data["text"])[1:]
try:
Expand Down
18 changes: 18 additions & 0 deletions bot_components/parse_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,24 @@ def extract_repo_name(plugin_obj, reponame, **kwargs):
return split_repo.replace(">", "")


def extract_multiple_repo_names(plugin_obj, repos, **kwargs):
"""
Does what the above does, but does it for a comma separated list of repos.
:param plugin_obj:
:param repos:
:param kwargs:
:return:
"""
repo_list = repos.split(",")

parsed_repos = []

for repo in repo_list:
parsed_repos.append(extract_repo_name(plugin_obj, repo, **kwargs))

return parsed_repos


def parse_toggles(plugin_obj, toggle, toggle_type="toggle", **kwargs):
"""
Parses typical toggle values, like off, on, enabled, disabled, true, false, etc.
Expand Down
13 changes: 10 additions & 3 deletions build_docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ if [ -z ${BUILD_TAG} ]; then
BUILD_TAG="latest"
fi

# If this is running in Travis, AND the Python version IS NOT 3.5, then don't build
# If this is running in Travis, AND the Python version IS NOT 3.6, then don't build
# the Docker image:
if [ $TRAVIS ]; then
PYTHON_VERSION=$( python --version )
if [[ $PYTHON_VERSION != *"3.5"* ]]; then
echo "This only builds Docker images in the Python 3.5 Travis job"
if [[ $PYTHON_VERSION != *"3.6"* ]]; then
echo "This only builds Docker images in the Python 3.6 Travis job"
exit 0
fi
fi
Expand All @@ -55,5 +55,12 @@ echo "[-->] Now building the Docker image..."
# Build that Docker image...
docker build -t netflixoss/hubcommander:${BUILD_TAG} --rm=true . --build-arg RTM_VERSION=${RTM_VERSION}

cmd_st="$?"
if [ $cmd_st -gt 0 ]
then
echo "Error building image. Exiting."
exit $cmd_st
fi

echo
echo "DONE!"
39 changes: 33 additions & 6 deletions command_plugins/github/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,38 @@
from hubcommander.bot_components.slack_comm import send_error


def repo_must_exist(org_arg="org", repo_arg="repo"):
def repo_must_exist(org_arg="org"):
def command_decorator(func):
def decorated_command(github_plugin, data, user_data, *args, **kwargs):
# Just 1 repo -- or multiple?
if kwargs.get("repo"):
repos = [kwargs["repo"]]
else:
repos = kwargs["repos"]

# Check if the specified GitHub repo exists:
if not github_plugin.check_if_repo_exists(data, user_data, kwargs[repo_arg], kwargs[org_arg]):
return
for repo in repos:
if not github_plugin.check_if_repo_exists(data, user_data, repo, kwargs[org_arg]):
return

# Run the next function:
return func(github_plugin, data, user_data, *args, **kwargs)

return decorated_command

return command_decorator


def team_must_exist(org_arg="org", team_arg="team"):
def command_decorator(func):
def decorated_command(github_plugin, data, user_data, *args, **kwargs):
# Check if the specified GitHub team exists:
kwargs['team_id'] = github_plugin.find_team_id_by_name(kwargs[org_arg], kwargs[team_arg])
if not kwargs.get("team_id"):
send_error(data["channel"], "@{}: The GitHub team: {} does not exist.".format(user_data["name"],
kwargs[team_arg]),
thread=data["ts"])
return
# Run the next function:
return func(github_plugin, data, user_data, *args, **kwargs)

Expand All @@ -33,13 +58,15 @@ def decorated_command(github_plugin, data, user_data, *args, **kwargs):

if not found_user:
send_error(data["channel"], "@{}: The GitHub user: {} does not exist.".format(user_data["name"],
kwargs[user_arg]))
kwargs[user_arg]),
thread=data["ts"])
return

except Exception as e:
send_error(data["channel"],
"@{}: A problem was encountered communicating with GitHub to verify the user's GitHub "
"id. Here are the details:\n{}".format(user_data["name"], str(e)))
"id. Here are the details:\n{}".format(user_data["name"], str(e)),
thread=data["ts"])
return

# Run the next function:
Expand All @@ -66,7 +93,7 @@ def decorated_command(github_plugin, data, user_data, *args, **kwargs):
send_error(data["channel"],
"@{}: This repository does not have the branch: `{}`.".format(user_data["name"],
kwargs[branch_arg]),
markdown=True)
markdown=True, thread=data["ts"])
return

# Run the next function:
Expand Down
Loading