bitwardentools
项目描述
与 vaultwarden/bitwarden (_rs) 和 vaultier 一起工作的工具
此包包含一个python3+客户端,用于bitwarden,它使用原生python实现,同时也包装了官方的npm @bitwarden/cli
。
最终目标是当然只依赖于python实现,针对 vaultwarden/bitwarden_rs 服务器实现。
功能
- 可由api控制的客户端
- 在组织、集合、密钥、用户(也可禁用/启用)和附件上创建、读取、更新、删除
- 将密钥附加到组织集合
- 在组织、集合和用户级别设置访问权限。
- 向宝库和组织下载/上传附件
- 客户端还集成了对官方npm CLI的薄包装(请参阅
call
方法) - 阅读 api 获取更多详细信息
作为Python库安装
pip install bitwardentools
在开发模式下运行
配置
cp .env.dist .env
cp .env.local.dist .env.local
printf "USER_UID=$(id -u)\nUSER_GID=$(id -g)\n">>.env
构建
eval $(egrep -hv '^#|^\s*$' .env .env.local|sed -e "s/^/export /g"| sed -e "s/=/='/" -e "s/$/'/g"|xargs)
COMPOSE_FILE="docker-compose.yml:docker-compose-build.yml" docker-compose build
运行
docker-compose run --rm app bash
sed -i -e "/COMPOSE_FILE/d" .env
echo "COMPOSE_FILE=docker-compose.yml:docker-compose-dev.yml" >> .env
docker-compose up -d --force-recreate
docker-compose exec -u app app bash
运行测试
sed -i -e "/COMPOSE_FILE/d" .env
echo "COMPOSE_FILE=docker-compose.yml:docker-compose-dev.yml:docker-compose-test.yml" >> .env
docker-compose exec -u app app tox -e linting,coverage
致谢和参考文献
- gnunux 优秀文章:1 2 3
- https://github.com/dani-garcia/vaultwarden/(旧:https://github.com/dani-garcia/bitwarden_rs/ )
- https://github.com/doy/rbw/tree/master/src
- https://github.com/bitwarden/jslib
- https://github.com/birlorg/bitwarden-cli/tree/trunk/python/bitwarden
- https://github.com/jcs/rubywarden
文档
另请参阅 USAGE(或在下文PyPI上阅读)
变更记录
1.0.57
- QA & CI/CD修复 [kiorky]
- 修复较新版本的vaultwarden补丁 [kiorky]
- 修复较新版本的vaultwarden添加用户 [kiorky]
- 修复较新版本的vaultwarden创建组织 [kiorky]
- 修复较新版本的vaultwarden设置组织访问 [kiorky]
1.0.56
- 自定义身份验证负载支持(双因素、API身份验证)[Markus Kötter koetter@cispa.de]
1.0.55
- 确保requests包含在需求中 [kiorky]
1.0.54
- 修复:排除folderId进行加密 [托马斯·克里希鲍默尔 thomas@kriechbaumer.name]
1.0.53
- kdfIterations有效负载更改修复 [kiorky]
- 添加delete_user [kiorky]
1.0.51
- 确认用户不需要私钥 [迪迪埃 'OdyX' 拉博德 didier.raboud@liip.ch]
1.0.49
- 完成vaultier
AS_SINGLE_ORG=false
acls - 使用全局
accessAll=true
用户,同时提供收藏集访问。
1.0.47
- Vaultier迁移:添加通知脚本
- Vaultier迁移:完成循环
- 添加组织/收藏集成员管理方法
- 重命名tokens属性
- 改进错误消息
- 优化登录和令牌管理
- 缓存重整和因式分解
- Vaultier AsOneOrganization导入变体
- 阐明文档
1.0.46
- 与bitwarden_rs
1.20
的兼容性遗留问题。
1.0.45
- 与bitwarden_rs
1.20
的兼容性(以前是1.18
)。
1.0.44
- 初始发布
发布版本
./release.sh $version
用法
client = Client(server, email, password)
client.sync()
#
# direct object creation methods
# organization
client.create_organization('foo', 'foo@foo.com')
# collection
client.create_collection('bar', orga='foo')
# default item/login
payload = {
"notes": "supernote",
"login": {
"totp": "aze",
'username': "alice", "password": "rabbit",
"uris": [{"match": None, "uri": "http://a"}]
}
}
client.create_item("sec5", orga, collections=[col], **payload)
# if orga is None cipher will go inside user vault
client.create_item("secpersonal", **payload)
## is a synoym: client.create_login
# identity
# title": "Mr/Mrs/Ms/Dr"
payload = {
"identity": {
"address1": "foo", "address2": "foo", "address3": "foo", "city": "foo", "postalCode": "foo",
"country": "foo", "state": "foo", "username": "foo", "company": "foo",
"phone": "foo", "email": "foo",
"title": "Mrs", "firstName": "foo", "lastName": "foo", "middleName": "foo",
"ssn": "foo", "licenseNumber": "foo", "passportNumber": "foo",
},
"notes": "foo",
}
client.create_identity("sec1", orga, collections=[col], **payload)
# note
payload = {
"fields": [{"name": "thisisabool", "type": 2, "value": False}],
"notes": "notenote",
"secureNote": {"type": 0},
}
client.create_securenote("sec2", orga, collections=[col], **payload)
# card
payload = {
"card": {"brand": "sec", "cardholderName": "foo",
"number": "aaa", "code": "123456",
"expMonth": "10", "expYear": "2013"},
"fields": [{"name": "aaa", "type": 0, "value": "aaa"}],
"notes": "aaa"
}
client.create_card("sec4", orga, collections=[col], **payload)
#
# create only with json payloads
orga = client.create(**{
'object': 'organization',
'name': "org",
'email': email})
# Create a collection
col = client.create(**{
'object': 'org-collection',
'name': "testcol",
'organizationId': client.item_or_id(orga)})
col2 = client.create(**{
'object': 'org-collection',
'name': "testcol2",
'organizationId': client.item_or_id(orga)})
# Create a login within an organization, collectionIds is mandatory on bitwarden_rs 1.19+
cipher = client.create(**{
"name": "test",
"object": "item",
"organizationId": orga.id,
"notes": "supernote",
"login": {'username': "alice", "password": "rabbit"},
"collectionIds": [col2.id],})
# Create a login within your personal vault
cipher = client.create(**{
"name": "test",
"object": "item",
"notes": "supernote",
"login": {'username': "alice", "password": "rabbit"})
#
# Patch existing objects
testorg = client.get_organization("org")
client.edit_organization(testorg, name='fooorg')
#
testcol = client.get_collection("testcol")
client.edit_orgcollection(testcol, name='foocol')
#
# Play with ciphers
all_ciphers = client.get_ciphers()
cipher = client.get_cipher("test", collection=col, orga=orga)
# Put cipther in collection col2
client.link(cipher, col2)
#
# Attachments
client.attach(sec, "/path/to/foo.zip")
# reload cipher with it's new attachment
# default dir in current working directory, default filename is uploaded filename
client.download(sec.attachments[0],
directory='/w/data/titi/toto',
filename='tata.zip')
client.delete_attachments(sec)
#
# users management
#
users = client.get_users() # > {"emails": {}, "ids": {}, "names": {}} users indexed dicts
# search one user
user = client.get_user(email="foo@bar.com")
user = client.get_user(name="foo")
user = client.get_user(id="424242424-4242-4242-4242-424242424242")
# enable/delete/disable methods can take id/email/name or user instances as kwargs:
client.disable_user(email="foo@bar.com")
client.disable_user(id="424242424-4242-4242-4242-424242424242")
client.disable_user(name="foo")
client.disable_user(user=user)
# other methods
client.enable_user(user=/name=/id=/email=)
client.delete_user(user=/name=/id=/email=)
# if not password, it will be autogenerated and in the return tuple
user, pw = client.create_user('foo@bar.com', password=, passwordhint=, name=)
# If you use bitwarden_rs and you setted up the bitwarden rs key,
# the user will be automatically validated
# you can manually validate an account with:
user = client.validate('foo@bar.com')
# you can also manage orgs invitations
acl = client.accept_invitation('foo@bar.com', orga) # need bitwarden server private key
acl = client.confirm_invitation('foo@bar.com', orga) # need bitwarden server private key
# you can also manage collection permissions
## add user to orga
c.add_user_to_organization(user, orga, collections=col)
## set them at orga level (will add to orga if not already member)
c.set_organization_access(user, orga, collections=col, hidepasswords=False, readOnly=True/False)
c.set_organization_access(user, orga, {"collection": col, "hidePasswords": False}, hidepasswords=True)
## add them at collection level
c.set_collection_access(user, col, hidepasswords=True/False, readOnly=True/False)
## remove from collection: col
c.set_organization_access(user, orga, {"collection": col, "remove": True})
### or
c.set_collection_access(user, {"collection": col, "remove": True})
## get acls infos
c.get_accesses(orga)
c.get_accesses(col)
c.get_accesses({"user": user, "collection": col})
c.get_accesses({"user": user, "orga": orga})
## remove from collection
c.remove_user_from_collection(userOrEmail, colc)
## remove from orga
c.remove_user_from_organization(userOrEmail, orga)
通过回调(2Factor)操作登录数据结构
这允许其他登录机制,如totp或API密钥
示例1
def mfa2fa(loginpayload):
totp = pyotp.TOTP(otpseed)
loginpayload.update(
{
"twoFactorToken": str(totp.now()),
"twoFactorProvider": "0",
"twoFactorRemember": "0"
}
)
return loginpayload
client = Client(server, email, password, authentication_cb=mfa2fa)
示例1
def api_key(loginpayload):
loginpayload.update(
{
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"scope": "api",
"grant_type": "client_credentials"
}
)
return loginpayload
client = Client(server, email, password, authentication_cb=api_key)
自动验证用户的vaultwarden/bitwarden_rs密钥编码
base64 $BITWARDEN_RS_SERVER_DATA/rsa_key.der|tr -d '\n'
=> copy paste the result in your .env.local this way
BITWARDEN_PRIVATE_KEY=MIIxxx
从vaultier迁移到bitwarden笔记
VAULTIER_KEY=$(echo $(base64 ~/vaultier_key.bin|tr -d '\n')
cat >>.env << EOF
VAULTIER_KEY=${VAULTIER_KEY}
# if your vauiltier has aditionnal httpauth
# VAULTIER_HTTP_PASSWORD=htpasswd
# VAULTIER_HTTP_USER=user
VAULTIER_EMAIL=myvaultier.email@d.com
VAULTIER_URL=https://vaultier.foo.net
VAULTIER_JSON=data/export/vaultierfile.json
BW_ORGA_NAME=MyBitwardenOrga
BITWARDEN_PW=MasterPassword
BITWARDEN_SERVER=https://bitwd.foo.net
BITWARDEN_EMAIL=foo@foo.com
将vaultier数据导出为json文件,用于卡片和文件附件
- 它将生成数据/export/vaultname.json
- 并下载data/export/secret$id/中的附件
time python src/bitwardentools/vaultier/export.py
将vaultier序列化的json vaults/cards加载到bitwarden orga/collections
由于bitwarden只有2个文件夹,而vaultier有3个,因此卡片迁移到bitwarden,并命名为$vault $card
;这是两个系统之间的链接,请不要在您想要继续迁移的同时重命名卡片,否则将重复内容。
time python src/bitwardentools/vaultier/import_structure.py
同步秘密
time python src/bitwardentools/vaultier/sync_secrets.py
将vaultier的json成员加载为bitwarden用户配置文件,并将其与其秘密关联
python src/bitwardentools/vaultier/invite.py
通知用户其账户
python src/bitwardentools/vaultier/notify.py --dry-run=0
安全注意事项
我们提供了一个bitwardentools.client.bust_cache
方法来使内存中的任何缓存失效,请在完成访问您的秘密后使用它。
from bitwardentools.client import bust_cache
bust_cache()
项目详情
下载文件
下载适合您平台的应用程序。如果您不确定要选择哪个,请了解更多关于安装包的信息。
源分布
bitwardentools-1.0.57.tar.gz (53.7 kB 查看散列)
构建分布
bitwardentools-1.0.57-py3-none-any.whl (55.6 kB 查看散列)