Skip to content
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

password manager #35

Open
wants to merge 2 commits into
base: main
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
46 changes: 46 additions & 0 deletions password-manager/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Password manager

Password manager takes an existing cape encrypted input and returns the specified account and password.

## Using the password manager
To keep track of a list of passwords the best way is to use your own auth token.
Encryption of sensitive data is reliant on Cape encrypt.


## Local format
The local format for your password store is:

Account|Label|encrypted output|


## App
We can just use a simple echo app to return the password in plaintext.

### Commands

There are a couple of commands that we can use to interact with the password manager app.
The syntax for interacting with the app is `<identifier>:<keyword>`.

**name**
Specify the name of the account and password.

**tag**
Returns all the secrets with the corresponding tag.

**all**
Returns all the secrets stored in the password vault.


## Alternative design
We can encrypt the entire password store and pass two separate values one after the other.
In the form of password vault + tag/account and it will return a password.

If we do this then one deployed webapp can work for everyone.

However, if you want to add a new account you will have to decode everything and modify
the output. The first one design makes it easy to add an account. However, it requires
more code to run on the client side and doesn't offer storage on Cape.

## Alternative design 2
Embed the data in the function. Require a custom app to run this, lots more work on the user.

85 changes: 85 additions & 0 deletions password-manager/manager/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import json

FILE_PATH = "./secret.json"


def open_secret(path=FILE_PATH):
with open(path) as f:
try:
data = json.load(f)
except Exception:
return None
return data


def store_secret(data, path=FILE_PATH):
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)


def filter_by_identifier(vault, key, value):
ret = []
for i in vault:
if i[key] == value:
ret.append(i)
return ret


def cape_handler(arg):
# Try to see if secret exists, if it does, process user input as string an non-json.
secret = open_secret()
if secret == None:
try:
user_input = json.loads(arg)
# Cache the secret in enclave storage
store_secret(user_input)

except TypeError:
raise TypeError(
"expected secrets vault to passed in first in json format [{name, tag, username, password}]"
)

else:
if type(arg) is not str:
raise TypeError(f"expected input to be string, got {type(arg)}")

if arg == "all":
return json.dumps(secret, indent=4)

# Try to split the string to get key, value.
identifier = arg.split(":")
if len(identifier) != 2:
raise ValueError(
f"expected input of the form `name:<identifier>`, or `tag:<identifier>`, got: {arg}"
)
cmd = identifier[0].strip()

if cmd == "name":
# iterage over secret and find a name match
return json.dumps(
filter_by_identifier(secret, "name", identifier[1].strip()), indent=4
)

elif cmd == "tag":
return json.dumps(
filter_by_identifier(secret, "tag", identifier[1].strip()), indent=4
)

else:
return ValueError(
f"unknown command: {identifier[0]}, please use `all`, `name:<identifier>`, or `tag:<identifier>`"
)


if __name__ == "__main__":
vault = [
{"name": "aws", "tag": "grocery", "username": "bob", "password": "B013Pass"},
{"name": "shop", "tag": "grocery", "username": "bob", "password": "B013Pass"},
]
serialized = json.dumps(vault)

# print(cape_handler(serialized))
print(cape_handler("all"))

print(cape_handler("name: aws"))
print(cape_handler("tag: grocery"))
Empty file.