Skip to content

Added client to use the API and updated README #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
52 changes: 52 additions & 0 deletions .deepsource.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
version = 1

[[analyzers]]
name = "python"
enabled = true

[analyzers.meta]
runtime_version = "3.x.x"

[[analyzers]]
name = "test-coverage"
enabled = true

[[analyzers]]
name = "secrets"
enabled = true

[[transformers]]
name = "prettier"
enabled = true

[[transformers]]
name = "standardjs"
enabled = true

[[transformers]]
name = "rubocop"
enabled = true

[[transformers]]
name = "black"
enabled = true

[[transformers]]
name = "gofmt"
enabled = true

[[transformers]]
name = "yapf"
enabled = true

[[transformers]]
name = "autopep8"
enabled = true

[[transformers]]
name = "isort"
enabled = true

[[transformers]]
name = "standardrb"
enabled = true
37 changes: 27 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/18b28c1dda31468196190062cf9ddb8a)](https://app.codacy.com/gh/Pitenager/passbolt-python-api?utm_source=github.com&utm_medium=referral&utm_content=Pitenager/passbolt-python-api&utm_campaign=Badge_Grade)
[![DeepSource](https://deepsource.io/gh/Pitenager/passbolt-python-api.svg/?label=active+issues&show_trend=true)](https://deepsource.io/gh/Pitenager/passbolt-python-api/?ref=repository-badge)

# Passbolt-python-API

## Installation

$pip install passbolt-python-api
$git clone https://github.com/Pitenager/passbolt-python-api.git
$cd passbolt-python-api.git/
$pip install passbolt-python-api

## Dependencies

- Python3
- GPG (also known as GnuPG) software
- Python3
- GPG (also known as GnuPG) software

## Configuration

Create a config file with the following contents.
Fill the config.ini file with the following contents.

[PASSBOLT]
SERVER = http://<server_ip or domain>
Expand All @@ -21,15 +26,28 @@ Create a config file with the following contents.
USER_PRIVATE_KEY_FILE = <optional: passbolt_private.asc>
PASSPHRASE = <passbolt_password>

## Usage
## CLI usage

usage: passbolt_manager.py [-h] [-c CHANGE] [-u UPLOAD] [-d DELETE] [-r READ]

Client to operate Stratio's Passbolt server

optional arguments:
-h, --help show this help message and exit
-c CHANGE, --change CHANGE Change an existing password in Passbolt
-u UPLOAD, --upload UPLOAD Upload new password to Passbolt
-d DELETE, --delete DELETE Delete an existing password in Passbolt
-r READ, --read READ Read an existing password in Passbolt

## API Usage

>>>import passboltapi
>>>passbolt = passboltapi.PassboltAPI(config_path="config.ini")

# Now you may do any get, post, put and delete request.
>>>r = passbolt.get(url="/resources.json?api-version=v2")
>>>r = passbolt.post(self.server_url + url, json=data)

# One can also use it as context manager
>>>with passboltapi.PassboltAPI(config_path="config.ini") as passbolt:

Expand All @@ -42,19 +60,18 @@ To import new keys:

>>>import passboltapi
>>>passbolt = passboltapi.PassboltAPI(config_path="config.ini", new_keys=True)

To delete old keys and import only the new ones.

>>>import passboltapi
>>>passbolt = passboltapi.PassboltAPI(config_path="config.ini", new_keys=True, delete_old_keys=True)

Recommended to do: Do not keep private and public files.
Recommended to do: Do not keep private and public files.
Rather just import them using gpg command one time and delete those files.

$gpg --import public.asc
$gpg --batch --import private.asc


### Passbolt API

For more API related questions, visit Passbolt API documentation:
Expand Down
7 changes: 7 additions & 0 deletions config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[PASSBOLT]
SERVER = https://<your server>
SERVER_PUBLIC_KEY_FILE = <optional: server_public.asc>
USER_FINGERPRINT = <user fingerprint>
USER_PUBLIC_KEY_FILE = <passbolt_public.asc>
USER_PRIVATE_KEY_FILE = <passbolt_private.asc>
PASSPHRASE = <login password>
226 changes: 226 additions & 0 deletions passbolt_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import argparse
import random
import string
import sys
import time

from colorama import Fore, init

import passboltapi


def banner():
print(Fore.CYAN + """
_ _ _
_ __ __ _ ___ ___| |__ ___ | | |_
| '_ \ / _` / __/ __| '_ \ / _ \| | __|
| |_) | (_| \__ \__ \ |_) | (_) | | |_
| .__/ \__,_|___/___/_.__/ \___/|_|\__|____
|_| |_____|
_ __ ___ __ _ _ __ __ _ __ _ ___ _ __
| '_ ` _ \ / _` | '_ \ / _` |/ _` |/ _ \ '__|
| | | | | | (_| | | | | (_| | (_| | __/ |
|_| |_| |_|\__,_|_| |_|\__,_|\__, |\___|_|
|___/ @Pitenager
""")

time.sleep(0.5)


def login():
try:
print(Fore.CYAN +
"[*] Trying to authenticate against Passbolt server...")

passbolt = passboltapi.PassboltAPI(config_path="config.ini",
new_keys=True,
delete_old_keys=True)
uuid = passbolt.get(
url="/resources.json?api-version=v2")["header"]["id"]

print(Fore.GREEN + "[-] Authenticated")
return passbolt, uuid

except Exception as e:
print(Fore.RED + "[!] Error: " + str(e))
sys.exit(1)


def generate_password():
try:
print(Fore.CYAN + "[*] Generating random password...")

# Create alphanumerical from string constants
printable = f"{string.ascii_letters}{string.digits}{string.punctuation}"

# Convert printable from string to list and shuffle
printable = list(printable)
random.shuffle(printable)

# Generate random password and convert to string
random_password = random.choices(printable, k=16)
random_password = "".join(random_password)

return random_password

except Exception as e:
print(Fore.RED + "[!] Error: " + str(e))
sys.exit(1)


def read(passbolt, name):
try:
print(Fore.CYAN + f"[*] Reading resource {name}...")

for i in passbolt.get(url="/resources.json?api-version=v2")["body"]:
if i["name"] == name:
resource = passbolt.get(
"/secrets/resource/{}.json?api-version=v2".format(i["id"]))
i["password"] = passbolt.decrypt(resource["body"]["data"])
print(i)
break

except Exception as e:
print(Fore.RED + "[!] Error: " + str(e))
sys.exit(1)


def upload(passbolt, uuid, name):
try:
pwd = generate_password()
encrypted_pass = passbolt.encrypt(pwd)

json_data = {
"name": name,
"description": f"(Automated) {name} password",
"secrets": [{
"user_id": uuid,
"data": encrypted_pass
}],
}

print(Fore.CYAN + "[*] Uploading new password...")
passbolt.post(url="/resources.json?api-version=v2", data=json_data)
print(Fore.GREEN + "[-] Password uploaded")

except Exception as e:
print(Fore.RED + "[!] Error: " + str(e))
sys.exit(1)


def change(passbolt, name):
try:
pwd = generate_password()
encrypted_pass = passbolt.encrypt(pwd)

print(Fore.CYAN + f"[*] Changing password of resource {name}...")

for i in passbolt.get(url="/resources.json?api-version=v2")["body"]:
if i["name"] == name:
json_data = {
"name":
name,
"description":
f"(Automated) {name} password",
"secrets": [{
"user_id": i["created_by"],
"data": encrypted_pass
}],
}
resourceId = i["id"]
passbolt.put(
url=f"/resources/{resourceId}.json?api-version=v2",
data=json_data)

print(Fore.GREEN + "[-] Password changed")

except Exception as e:
print(Fore.RED + "[!] Error: " + str(e))
sys.exit(1)


def delete(passbolt, name):
try:
print(Fore.CYAN + f"[*] Deleting resource {name}...")
for i in passbolt.get(url="/resources.json?api-version=v2")["body"]:
if i["name"] == name:
resourceId = i["id"]
break
passbolt.delete(url=f"/resources/{resourceId}.json?api-version=v2")
print(Fore.GREEN + f"[-] Resource {name} deleted")
except Exception as e:
print(Fore.RED + "[!] Error: " + str(e))
sys.exit(1)


def main(args):
try:
if len(sys.argv) <= 1:
print(Fore.RED + "[!] Error: Should specify at least one argument")
sys.exit(1)
else:
passbolt, uuid = login()
if args.change:
change(passbolt, args.change)
elif args.upload:
upload(passbolt, uuid, args.upload)
elif args.delete:
delete(passbolt, args.delete)
elif args.read:
read(passbolt, args.read)
else:
print(Fore.RED + "[!] Error: Invalid argument")
sys.exit(1)

print(Fore.CYAN + "[*] Closing session, exiting...")
passbolt.close_session()
print(Fore.GREEN + "[-] Session closed. Finished successfully")
sys.exit(0)

except Exception as e:
print(Fore.RED + "[!] Error: " + str(e))
sys.exit(1)


if __name__ == "__main__":
init(autoreset=True)
banner()

# Parameters
parser = argparse.ArgumentParser(
description="Client to operate Stratio's Passbolt server")
parser.add_argument(
"-c",
"--change",
metavar="CHANGE",
dest="change",
default=False,
help="Change an existing password in Passbolt",
)
parser.add_argument(
"-u",
"--upload",
metavar="UPLOAD",
dest="upload",
default=False,
help="Upload new password to Passbolt",
)
parser.add_argument(
"-d",
"--delete",
metavar="DELETE",
dest="delete",
default=False,
help="Delete an existing password in Passbolt",
)
parser.add_argument(
"-r",
"--read",
metavar="READ",
dest="read",
default=False,
help="Read an existing password in Passbolt",
)
args = parser.parse_args()

main(args)
Loading