feat: add auth0 lib, update cli and improve code

This commit is contained in:
Eduardo Chiarotti
2024-08-21 15:16:49 -03:00
parent 5d1f655229
commit 3b0286f592
6 changed files with 194 additions and 35 deletions

117
poetry.lock generated
View File

@@ -253,6 +253,24 @@ docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphi
tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
[[package]]
name = "auth0-python"
version = "4.7.1"
description = ""
optional = false
python-versions = ">=3.8"
files = [
{file = "auth0_python-4.7.1-py3-none-any.whl", hash = "sha256:5bdbefd582171f398c2b686a19fb5e241a2fa267929519a0c02e33e5932fa7b8"},
{file = "auth0_python-4.7.1.tar.gz", hash = "sha256:5cf8be11aa807d54e19271a990eb92bea1863824e4863c7fc8493c6f15a597f1"},
]
[package.dependencies]
aiohttp = ">=3.8.5,<4.0.0"
cryptography = ">=42.0.4,<43.0.0"
pyjwt = ">=2.8.0,<3.0.0"
requests = ">=2.31.0,<3.0.0"
urllib3 = ">=2.0.7,<3.0.0"
[[package]] [[package]]
name = "autoflake" name = "autoflake"
version = "2.3.1" version = "2.3.1"
@@ -851,6 +869,60 @@ pytube = ">=15.0.0,<16.0.0"
requests = ">=2.31.0,<3.0.0" requests = ">=2.31.0,<3.0.0"
selenium = ">=4.18.1,<5.0.0" selenium = ">=4.18.1,<5.0.0"
[[package]]
name = "cryptography"
version = "42.0.8"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false
python-versions = ">=3.7"
files = [
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"},
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"},
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"},
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"},
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"},
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"},
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"},
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"},
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"},
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"},
{file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"},
{file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"},
{file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"},
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"},
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"},
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"},
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"},
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"},
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"},
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"},
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"},
{file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"},
{file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"},
{file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"},
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"},
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"},
{file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"},
{file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"},
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"},
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"},
{file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"},
{file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"},
]
[package.dependencies]
cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""}
[package.extras]
docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"]
nox = ["nox"]
pep8test = ["check-sdist", "click", "mypy", "ruff"]
sdist = ["build"]
ssh = ["bcrypt (>=3.1.5)"]
test = ["certifi", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
test-randomorder = ["pytest-randomly"]
[[package]] [[package]]
name = "cssselect2" name = "cssselect2"
version = "0.7.0" version = "0.7.0"
@@ -4230,6 +4302,23 @@ files = [
[package.extras] [package.extras]
windows-terminal = ["colorama (>=0.4.6)"] windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pyjwt"
version = "2.9.0"
description = "JSON Web Token implementation in Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"},
{file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"},
]
[package.extras]
crypto = ["cryptography (>=3.4.0)"]
dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"]
docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
[[package]] [[package]]
name = "pylance" name = "pylance"
version = "0.9.18" version = "0.9.18"
@@ -5478,22 +5567,23 @@ files = [
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "1.26.19" version = "2.2.2"
description = "HTTP library with thread-safe connection pooling, file post, and more." description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" python-versions = ">=3.8"
files = [ files = [
{file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
{file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
] ]
[package.dependencies] [package.dependencies]
PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""}
[package.extras] [package.extras]
brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] h2 = ["h2 (>=4,<5)"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"]
[[package]] [[package]]
name = "uvicorn" name = "uvicorn"
@@ -5567,23 +5657,20 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)"
[[package]] [[package]]
name = "vcrpy" name = "vcrpy"
version = "6.0.1" version = "5.1.0"
description = "Automatically mock your HTTP interactions to simplify and speed up testing" description = "Automatically mock your HTTP interactions to simplify and speed up testing"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "vcrpy-6.0.1.tar.gz", hash = "sha256:9e023fee7f892baa0bbda2f7da7c8ac51165c1c6e38ff8688683a12a4bde9278"}, {file = "vcrpy-5.1.0-py2.py3-none-any.whl", hash = "sha256:605e7b7a63dcd940db1df3ab2697ca7faf0e835c0852882142bafb19649d599e"},
{file = "vcrpy-5.1.0.tar.gz", hash = "sha256:bbf1532f2618a04f11bce2a99af3a9647a32c880957293ff91e0a5f187b6b3d2"},
] ]
[package.dependencies] [package.dependencies]
PyYAML = "*" PyYAML = "*"
urllib3 = {version = "<2", markers = "platform_python_implementation == \"PyPy\""}
wrapt = "*" wrapt = "*"
yarl = "*" yarl = "*"
[package.extras]
tests = ["Werkzeug (==2.0.3)", "aiohttp", "boto3", "httplib2", "httpx", "pytest", "pytest-aiohttp", "pytest-asyncio", "pytest-cov", "pytest-httpbin", "requests (>=2.22.0)", "tornado", "urllib3"]
[[package]] [[package]]
name = "virtualenv" name = "virtualenv"
version = "20.26.3" version = "20.26.3"
@@ -6073,4 +6160,4 @@ tools = ["crewai-tools"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = ">=3.10,<=3.13" python-versions = ">=3.10,<=3.13"
content-hash = "91ba982ea96ca7be017d536784223d4ef83e86de05d11eb1c3ce0fc1b726f283" content-hash = "8327a37f807d35d0851e9cc46960e8df0d06924938b2c5354b09951fa54f15e3"

View File

@@ -29,6 +29,7 @@ jsonref = "^1.1.0"
agentops = { version = "^0.3.0", optional = true } agentops = { version = "^0.3.0", optional = true }
embedchain = "^0.1.114" embedchain = "^0.1.114"
json-repair = "^0.25.2" json-repair = "^0.25.2"
auth0-python = "^4.7.1"
[tool.poetry.extras] [tool.poetry.extras]
tools = ["crewai-tools"] tools = ["crewai-tools"]

View File

@@ -185,7 +185,7 @@ def deploy():
@deploy.command(name="up") @deploy.command(name="up")
@click.option("-u", "--uuid", type=Optional[str], help="Crew UUID parameter") @click.option("-u", "--uuid", type=str, help="Crew UUID parameter")
def deploy_up(uuid: Optional[str]): def deploy_up(uuid: Optional[str]):
"""Deploy the crew.""" """Deploy the crew."""
deploy_cmd.deploy(uuid=uuid) deploy_cmd.deploy(uuid=uuid)
@@ -204,21 +204,24 @@ def deploy_list():
@deploy.command(name="status") @deploy.command(name="status")
def deply_status(): @click.option("-u", "--uuid", type=str, help="Crew UUID parameter")
def deply_status(uuid: Optional[str]):
"""Get the status of a deployment.""" """Get the status of a deployment."""
deploy_cmd.get_crew_status() deploy_cmd.get_crew_status(uuid=uuid)
@deploy.command(name="logs") @deploy.command(name="logs")
def deploy_logs(): @click.option("-u", "--uuid", type=str, help="Crew UUID parameter")
def deploy_logs(uuid: Optional[str]):
"""Get the logs of a deployment.""" """Get the logs of a deployment."""
deploy_cmd.get_crew_logs() deploy_cmd.get_crew_logs(uuid=uuid)
@deploy.command(name="remove") @deploy.command(name="remove")
def deploy_remove(): @click.option("-u", "--uuid", type=str, help="Crew UUID parameter")
def deploy_remove(uuid: Optional[str]):
"""Remove a deployment.""" """Remove a deployment."""
deploy_cmd.remove_crew() deploy_cmd.remove_crew(uuid=uuid)
@deploy.command(name="signup") @deploy.command(name="signup")

View File

@@ -0,0 +1,3 @@
ALGORITHMS = ["RS256"]
AUTH0_DOMAIN = "dev-jzsr0j8zs0atl5ha.us.auth0.com"
AUTH0_CLIENT_ID = "CZtyRHuVW80HbLSjk4ggXNzjg4KAt7Oe"

View File

@@ -1,14 +1,19 @@
import time
import webbrowser
from os import getenv from os import getenv
from typing import Optional from typing import Optional
import requests
from rich.console import Console from rich.console import Console
from .api import CrewAPI from .api import CrewAPI
from .constants import AUTH0_CLIENT_ID, AUTH0_DOMAIN
from .utils import ( from .utils import (
fetch_and_json_env_file, fetch_and_json_env_file,
get_auth_token, get_auth_token,
get_git_remote_url, get_git_remote_url,
get_project_name, get_project_name,
validate_token,
) )
console = Console() console = Console()
@@ -175,16 +180,56 @@ class DeployCommand:
def signup(self) -> None: def signup(self) -> None:
console.print("Signing Up", style="bold blue") console.print("Signing Up", style="bold blue")
response = self.client.signup()
# signup_command(response["signup_link"]) device_code_payload = {
if response.status_code == 200: "client_id": AUTH0_CLIENT_ID,
data = response.json() "scope": "openid profile email",
console.print(f"Temporary credentials: {data['token']}") "audience": "https://dev-jzsr0j8zs0atl5ha.us.auth0.com/api/v2/",
console.print( }
"We are trying to open the following signup link below.\n" device_code_response = requests.post(
"If it doesn't open for you, copy-and-paste into your browser to proceed." f"https://{AUTH0_DOMAIN}/oauth/device/code",
data=device_code_payload,
)
if device_code_response.status_code != 200:
console.print("Error generating the device code")
raise
device_code_data = device_code_response.json()
console.print(
"1. Navigate to: ",
device_code_data["verification_uri_complete"],
)
console.print("2. Enter the following code: ", device_code_data["user_code"])
webbrowser.open(device_code_data["verification_uri_complete"])
token_payload = {
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
"device_code": device_code_data["device_code"],
"client_id": AUTH0_CLIENT_ID,
}
authenticated = False
while not authenticated:
token_response = requests.post(
f"https://{AUTH0_DOMAIN}/oauth/token", data=token_payload
) )
console.print(f"\n{data['signup_link']}", style="underline blue")
else: token_data = token_response.json()
console.print(response.text, style="bold red") if token_response.status_code == 200:
validate_token(token_data["id_token"])
# current_user = jwt.decode(
# token_data["id_token"],
# algorithms=ALGORITHMS,
# options={"verify_signature": False},
# )
authenticated = True
console.print("\nWelcome to CrewAI+ !!", style="green")
elif token_data["error"] not in ("authorization_pending", "slow_down"):
console.print(token_data["error_description"])
raise
else:
time.sleep(device_code_data["interval"])

View File

@@ -1,8 +1,13 @@
import os
import re import re
import subprocess import subprocess
import tomllib import tomllib
from auth0.authentication.token_verifier import (
AsymmetricSignatureVerifier,
TokenVerifier,
)
from .constants import AUTH0_CLIENT_ID, AUTH0_DOMAIN
def get_git_remote_url(): def get_git_remote_url():
@@ -82,5 +87,20 @@ def fetch_and_json_env_file(env_file_path: str = ".env") -> dict:
return {} return {}
def validate_token(id_token: str) -> None:
"""
Verify the token and its precedence
:param id_token:
"""
jwks_url = f"https://{AUTH0_DOMAIN}/.well-known/jwks.json"
issuer = f"https://{AUTH0_DOMAIN}/"
signature_verifier = AsymmetricSignatureVerifier(jwks_url)
token_verifier = TokenVerifier(
signature_verifier=signature_verifier, issuer=issuer, audience=AUTH0_CLIENT_ID
)
token_verifier.verify(id_token)
def get_auth_token(): def get_auth_token():
return os.environ.get("TOKEN", "<YOUR_API_KEY>") return ""