Files
authenticator-rs/webdriver-tools/webdriver-driver.py
2020-09-17 10:22:17 -07:00

208 lines
6.2 KiB
Python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from rich.console import Console
from rich.logging import RichHandler
import argparse
import logging
import requests
console = Console()
log = logging.getLogger("webdriver-driver")
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help="sub-command help")
parser.add_argument(
"--verbose", "-v", help="Be more verbose", action="count", default=0
)
parser.add_argument(
"--url",
default="http://localhost:8080/webauthn/authenticator",
help="webdriver url",
)
def device_add(args):
data = {
"protocol": args.protocol,
"transport": args.transport,
"hasResidentKey": args.residentkey in ["true", "yes"],
"isUserConsenting": args.consent in ["true", "yes"],
"hasUserVerification": args.uv in ["available", "verified"],
"isUserVerified": args.uv in ["verified"],
}
console.print("Adding new device: ", data)
rsp = requests.post(args.url, json=data)
console.print(rsp)
console.print(rsp.json())
parser_add = subparsers.add_parser("add", help="Add a device")
parser_add.set_defaults(func=device_add)
parser_add.add_argument(
"--consent",
choices=["yes", "no", "true", "false"],
default="true",
help="consent automatically",
)
parser_add.add_argument(
"--residentkey",
choices=["yes", "no", "true", "false"],
default="no",
help="indicate a resident key",
)
parser_add.add_argument(
"--uv",
choices=["no", "available", "verified"],
default="no",
help="indicate user verification",
)
parser_add.add_argument(
"--protocol", choices=["ctap1/u2f", "ctap2"], default="ctap1/u2f", help="protocol"
)
parser_add.add_argument("--transport", default="usb", help="transport type(s)")
def device_delete(args):
rsp = requests.delete(f"{args.url}/{args.id}")
console.print(rsp)
console.print(rsp.json())
parser_delete = subparsers.add_parser("delete", help="Delete a device")
parser_delete.set_defaults(func=device_delete)
parser_delete.add_argument("id", type=int, help="device ID to delete")
def device_view(args):
rsp = requests.get(f"{args.url}/{args.id}")
console.print(rsp)
console.print(rsp.json())
parser_view = subparsers.add_parser("view", help="View data about a device")
parser_view.set_defaults(func=device_view)
parser_view.add_argument("id", type=int, help="device ID to view")
def device_update_uv(args):
data = {"isUserVerified": args.uv in ["verified", "yes"]}
rsp = requests.post(f"{args.url}/{args.id}/uv", json=data)
console.print(rsp)
console.print(rsp.json())
parser_update_uv = subparsers.add_parser(
"update-uv", help="Update the User Verified setting"
)
parser_update_uv.set_defaults(func=device_update_uv)
parser_update_uv.add_argument("id", type=int, help="device ID to update")
parser_update_uv.add_argument(
"uv",
choices=["no", "yes", "verified"],
default="no",
help="indicate user verification",
)
def credential_add(args):
data = {
"credentialId": args.credentialId,
"isResidentCredential": args.isResidentCredential in ["true", "yes"],
"rpId": args.rpId,
"privateKey": args.privateKey,
"signCount": args.signCount,
}
if args.userHandle:
data["userHandle"] = (args.userHandle,)
console.print(f"Adding new credential to device {args.id}: ", data)
rsp = requests.post(f"{args.url}/{args.id}/credential", json=data)
console.print(rsp)
console.print(rsp.json())
parser_credential_add = subparsers.add_parser("addcred", help="Add a credential")
parser_credential_add.set_defaults(func=credential_add)
parser_credential_add.add_argument(
"--id", required=True, type=int, help="device ID to use"
)
parser_credential_add.add_argument(
"--credentialId", required=True, help="base64url-encoded credential ID"
)
parser_credential_add.add_argument(
"--isResidentCredential",
choices=["yes", "no", "true", "false"],
default="no",
help="indicate a resident key",
)
parser_credential_add.add_argument("--rpId", required=True, help="RP id (hostname)")
parser_credential_add.add_argument(
"--privateKey", required=True, help="base64url-encoded private key per RFC 5958"
)
parser_credential_add.add_argument("--userHandle", help="base64url-encoded user handle")
parser_credential_add.add_argument(
"--signCount", default=0, type=int, help="initial signature counter"
)
def credentials_get(args):
rsp = requests.get(f"{args.url}/{args.id}/credentials")
console.print(rsp)
console.print(rsp.json())
parser_credentials_get = subparsers.add_parser("getcreds", help="Get credentials")
parser_credentials_get.set_defaults(func=credentials_get)
parser_credentials_get.add_argument("id", type=int, help="device ID to query")
def credential_delete(args):
rsp = requests.delete(f"{args.url}/{args.id}/credentials/{args.credentialId}")
console.print(rsp)
console.print(rsp.json())
parser_credentials_get = subparsers.add_parser("delcred", help="Delete a credential")
parser_credentials_get.set_defaults(func=credential_delete)
parser_credentials_get.add_argument("id", type=int, help="device ID to affect")
parser_credentials_get.add_argument(
"credentialId", help="base64url-encoded credential ID"
)
def credentials_clear(args):
rsp = requests.delete(f"{args.url}/{args.id}/credentials")
console.print(rsp)
console.print(rsp.json())
parser_credentials_get = subparsers.add_parser(
"clearcreds", help="Clear all credentials for a device"
)
parser_credentials_get.set_defaults(func=credentials_clear)
parser_credentials_get.add_argument("id", type=int, help="device ID to affect")
def main():
args = parser.parse_args()
loglevel = logging.INFO
if args.verbose > 0:
loglevel = logging.DEBUG
logging.basicConfig(
level=loglevel, format="%(message)s", datefmt="[%X]", handlers=[RichHandler()]
)
try:
args.func(args)
except requests.exceptions.ConnectionError as ce:
log.error(f"Connection refused to {args.url}: {ce}")
if __name__ == "__main__":
main()