From dd06fd9decadd5cb177bf48479fe7722959bfdea Mon Sep 17 00:00:00 2001 From: Kamran Ali Date: Mon, 30 May 2022 21:09:05 +0100 Subject: [PATCH] Add Docker and tidy up --- .dockerignore | 3 +++ Dockerfile | 19 +++++++++++++++++++ auther/cli.py | 4 ++-- auther/exceptions.py | 6 ++++++ auther/providers/BaseProvider.py | 18 ++++++++++++------ auther/providers/adfs.py | 3 +++ auther/providers/azuread.py | 6 +++--- auther/providers/helpers/azuread.py | 11 ++++++++++- setup.py | 2 +- 9 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0f8f1c8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +venv +.git +*.egg-info/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..602118a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.9-alpine + +RUN apk add --no-cache \ + udev \ + ttf-freefont \ + chromium \ + && rm -rf /usr/include \ + && rm -rf /var/cache/apk/* /usr/share/man /tmp/* + +ENV CHROME_BIN="/usr/bin/chromium-browser" + +COPY . /auther +WORKDIR /auther + +RUN pip install -r requirements.txt + +RUN pip install . + +ENTRYPOINT [ "auther" ] \ No newline at end of file diff --git a/auther/cli.py b/auther/cli.py index ad56016..b15b50d 100644 --- a/auther/cli.py +++ b/auther/cli.py @@ -10,7 +10,7 @@ def main(): pass -@main.command('configure') +@main.command('configure', help='Configure a chosen identiy provider for use') @click.option('--aws-config', default=f'{Path.home()}/.aws/config', help='The path to your AWS config file', required=False) @click.option('--profile', default='default', help='The name of the AWS profile', required=False) @click.option('--region', default='eu-west-1', help='Your prefered AWS region', required=False) @@ -46,7 +46,7 @@ def configure(**kwargs): getattr(globals()[provider], f'{provider.replace("_", "").title()}Provider').write_config(options, kwargs['profile'], kwargs['aws_config']) -@main.command() +@main.command('login', help='Authenticate using a specified identity provider') @click.option('--provider', default='azuread', help='The federated provider', required=False) @click.option('--profile', default='default', help='The name of the AWS profile', required=False) @click.option('--aws-config', default=f'{Path.home()}/.aws/config', help='The path to your AWS config file', required=False) diff --git a/auther/exceptions.py b/auther/exceptions.py index 9cf21f9..5201246 100644 --- a/auther/exceptions.py +++ b/auther/exceptions.py @@ -5,4 +5,10 @@ class ProviderNotConfigured(Exception): pass class ProviderAuthenticationError(Exception): + pass + +class ProviderNotImplementedError(Exception): + pass + +class RoleDurationError(Exception): pass \ No newline at end of file diff --git a/auther/providers/BaseProvider.py b/auther/providers/BaseProvider.py index 3b1cb07..f3d5596 100644 --- a/auther/providers/BaseProvider.py +++ b/auther/providers/BaseProvider.py @@ -4,6 +4,7 @@ from datetime import datetime from auther.exceptions import * +from botocore.exceptions import ClientError class BaseProvider: @staticmethod @@ -105,12 +106,17 @@ def assume_role(self, provider, profile, role, duration): print(f'Assuming role {role[1]}') - result = client.assume_role_with_saml( - RoleArn=role[1], - PrincipalArn=role[2], - SAMLAssertion=role[0], - DurationSeconds=duration, - ) + try: + result = client.assume_role_with_saml( + RoleArn=role[1], + PrincipalArn=role[2], + SAMLAssertion=role[0], + DurationSeconds=duration, + ) + except ClientError as ex: + if 'The requested DurationSeconds exceeds the MaxSessionDuration set for this role' in str(ex): + raise RoleDurationError(f'{int(duration / 60 / 60)} hour(s) is too high for this role. Try a lower value.') + raise ex creds = { 'aws_access_key_id': result["Credentials"]["AccessKeyId"], diff --git a/auther/providers/adfs.py b/auther/providers/adfs.py index e02687b..1b69851 100644 --- a/auther/providers/adfs.py +++ b/auther/providers/adfs.py @@ -1,12 +1,15 @@ import configparser import requests +from auther.exceptions import ProviderNotImplementedError from auther.providers.BaseProvider import BaseProvider class AdfsProvider(BaseProvider): def __init__(self, idp_url): self.idp_url = f'https://{idp_url}/adfs/ls/IdpInitiatedSignOn.aspx?loginToRp=urn:amazon:webservices' + raise ProviderNotImplementedError('The provider adfs is not currently implemented') + def login(self, username, password): pass diff --git a/auther/providers/azuread.py b/auther/providers/azuread.py index 56f52b2..0316e6b 100644 --- a/auther/providers/azuread.py +++ b/auther/providers/azuread.py @@ -1,8 +1,8 @@ import configparser import requests +import auther.providers.helpers.azuread as helper from auther.providers.BaseProvider import BaseProvider -from auther.providers.helpers.azuread import * class AzureadProvider(BaseProvider): def __init__(self, options): @@ -12,8 +12,8 @@ def __init__(self, options): # login to Azure AD, overwrite value of self.password and del it once used def login(self): - url = create_login_url(self.app_id, self.tenant_id) - roles = do_login(url, username=self.username, password=self.password) + url = helper.create_login_url(self.app_id, self.tenant_id) + roles = helper.do_login(url, username=self.username, password=self.password) # destroy password self.password = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' diff --git a/auther/providers/helpers/azuread.py b/auther/providers/helpers/azuread.py index be2daa0..2aa63cd 100644 --- a/auther/providers/helpers/azuread.py +++ b/auther/providers/helpers/azuread.py @@ -11,6 +11,7 @@ import pyppeteer import asyncio import getpass +import os import xml.etree.ElementTree from datetime import datetime @@ -42,7 +43,15 @@ def create_login_url(app_id, tenant_id): async def _load_login(url, headless): launch_options = {"headless": headless} - browser = await pyppeteer.launch(options=launch_options) + chromium_exe = os.environ.get('CHROME_BIN', '') + + browser = await pyppeteer.launch(executablePath=chromium_exe , options=launch_options, args=[ + '--no-sandbox', + '--single-process', + '--disable-dev-shm-usage', + '--disable-gpu', + '--no-zygote' + ]) page = await browser.newPage() response = await page.goto( url, diff --git a/setup.py b/setup.py index cb2a0d1..fe9a58c 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name="auther", - version="0.0.3", + version="0.0.4", author="Kamran Ali", author_email="auther@trewq34.com", description="Command line tool for AWS CLI authentication",