Do not blindly import old API keys
This commit is contained in:
parent
40784ba51e
commit
4003d5e938
|
@ -38,6 +38,11 @@ explicitly. Once we implement them, their usage will be described in the
|
|||
python tools/import_from_mongodb.py mongodb://mongo/obs \
|
||||
--keycloak-users-file /export/users.json
|
||||
```
|
||||
There is an option `--keep-api-keys` which means the users won't have to
|
||||
reconfigure the devices they used their API key in. **However**, please try
|
||||
to avoid this option if at all possible, as the old keys are *very* insecure.
|
||||
The default without this option to generate a new, secure API key for each
|
||||
user.
|
||||
* Shut down the `mongo` service, you can now remove it from docker-compose.yaml
|
||||
* Start `keycloak` and configure it, similarly to how it was configured in the
|
||||
development setup (but choose more secure options). Update the API config
|
||||
|
|
|
@ -10,6 +10,7 @@ import math
|
|||
import aiofiles
|
||||
import random
|
||||
import string
|
||||
import secrets
|
||||
from slugify import slugify
|
||||
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
@ -337,6 +338,13 @@ class User(Base):
|
|||
# migrating *to* the external authentication scheme.
|
||||
match_by_username_email = Column(Boolean, server_default=false())
|
||||
|
||||
def generate_api_key(self):
|
||||
"""
|
||||
Generates a new :py:obj:`api_key` into this instance. The new key is
|
||||
sourced from a secure random source and is urlsafe.
|
||||
"""
|
||||
self.api_key = secrets.token_urlsafe(24)
|
||||
|
||||
def to_dict(self, for_user_id=None):
|
||||
return {
|
||||
"username": self.username,
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import logging
|
||||
import os
|
||||
import binascii
|
||||
|
||||
from sanic.response import json
|
||||
from sanic.exceptions import InvalidUsage
|
||||
|
@ -42,7 +40,7 @@ async def put_user(req):
|
|||
user.are_tracks_visible_for_all = bool(data["areTracksVisibleForAll"])
|
||||
|
||||
if data.get("updateApiKey"):
|
||||
user.api_key = binascii.b2a_hex(os.urandom(16)).decode("ascii")
|
||||
user.generate_api_key()
|
||||
|
||||
await req.ctx.db.commit()
|
||||
return json(user_to_json(req.ctx.user))
|
||||
|
|
|
@ -38,21 +38,37 @@ async def main():
|
|||
default=None,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--keep-api-keys",
|
||||
action="store_true",
|
||||
help="keep the old API keys (very insecure!) instead of generating new ones",
|
||||
default=False,
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.keep_api_keys:
|
||||
log.warning(
|
||||
"Importing users with their old API keys. These keys are very insecure and "
|
||||
"could provide access to user data to third parties. Consider to notify "
|
||||
"your users about the need to generate a new API key through their profile pages."
|
||||
)
|
||||
|
||||
async with connect_db(app.config.POSTGRES_URL):
|
||||
async with make_session() as session:
|
||||
mongo = AsyncIOMotorClient(args.mongodb_url).get_default_database()
|
||||
|
||||
log.debug("Connected to mongodb and postgres.")
|
||||
user_id_map = await import_users(mongo, session, args.keycloak_users_file)
|
||||
user_id_map = await import_users(
|
||||
mongo, session, args.keycloak_users_file, args.keep_api_keys
|
||||
)
|
||||
|
||||
await import_tracks(mongo, session, user_id_map)
|
||||
|
||||
await session.commit()
|
||||
|
||||
|
||||
async def import_users(mongo, session, keycloak_users_file):
|
||||
async def import_users(mongo, session, keycloak_users_file, keep_api_keys):
|
||||
keycloak_users = []
|
||||
|
||||
old_id_by_email = {}
|
||||
|
@ -66,12 +82,16 @@ async def import_users(mongo, session, keycloak_users_file):
|
|||
bio=user.get("bio"),
|
||||
image=user.get("image"),
|
||||
are_tracks_visible_for_all=user.get("areTracksVisibleForAll") or False,
|
||||
api_key=str(user["_id"]),
|
||||
created_at=user.get("createdAt") or datetime.utcnow(),
|
||||
updated_at=user.get("updatedAt") or datetime.utcnow(),
|
||||
match_by_username_email=True,
|
||||
)
|
||||
|
||||
if keep_api_keys:
|
||||
new_user.api_key = str(user["_id"])
|
||||
else:
|
||||
new_user.generate_api_key()
|
||||
|
||||
if keycloak_users_file:
|
||||
needs_email_verification = user.get("needsEmailValidation", True)
|
||||
required_actions = ["UPDATE_PASSWORD"]
|
||||
|
|
Loading…
Reference in a new issue