migrate to secret manager, closes #45
This commit is contained in:
parent
de23eb0065
commit
c7fe8fada5
@ -4,6 +4,7 @@ from music.model.user import User
|
||||
from music.model.config import Config
|
||||
from music.auth.jwt_keys import generate_key
|
||||
from music.api.decorators import no_cache
|
||||
from music.cloud import SPOT_CLIENT_URI, SPOT_SECRET_URI
|
||||
|
||||
from urllib.parse import urlencode, urlunparse
|
||||
import datetime
|
||||
@ -11,11 +12,14 @@ from datetime import timedelta
|
||||
from numbers import Number
|
||||
import logging
|
||||
from base64 import b64encode
|
||||
|
||||
from google.cloud import secretmanager
|
||||
import requests
|
||||
|
||||
blueprint = Blueprint('authapi', __name__)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
secret_client = secretmanager.SecretManagerServiceClient()
|
||||
|
||||
|
||||
@blueprint.route('/login', methods=['GET', 'POST'])
|
||||
@ -194,10 +198,10 @@ def auth():
|
||||
|
||||
if 'username' in session:
|
||||
|
||||
config = Config.collection.get("config/music-tools")
|
||||
spot_client = secret_client.access_secret_version(request={"name": SPOT_CLIENT_URI})
|
||||
params = urlencode(
|
||||
{
|
||||
'client_id': config.spotify_client_id,
|
||||
'client_id': spot_client.payload.data.decode("UTF-8"),
|
||||
'response_type': 'code',
|
||||
'scope': 'playlist-modify-public playlist-modify-private playlist-read-private '
|
||||
'user-read-playback-state user-modify-playback-state user-library-read',
|
||||
@ -221,10 +225,11 @@ def token():
|
||||
flash('authorization failed')
|
||||
return redirect('app_route')
|
||||
else:
|
||||
config = Config.collection.get("config/music-tools")
|
||||
spot_client = secret_client.access_secret_version(request={"name": SPOT_CLIENT_URI})
|
||||
spot_secret = secret_client.access_secret_version(request={"name": SPOT_SECRET_URI})
|
||||
|
||||
idsecret = b64encode(
|
||||
bytes(config.spotify_client_id + ':' + config.spotify_client_secret, "utf-8")
|
||||
bytes(spot_client.payload.data.decode("UTF-8") + ':' + spot_secret.payload.data.decode("UTF-8"), "utf-8")
|
||||
).decode("ascii")
|
||||
headers = {'Authorization': 'Basic %s' % idsecret}
|
||||
|
||||
|
@ -1,17 +1,15 @@
|
||||
from datetime import timedelta, datetime, timezone
|
||||
import jwt
|
||||
from music.cloud import JWT_SECRET_URI
|
||||
from music.model.user import User
|
||||
from music.model.config import Config
|
||||
|
||||
from google.cloud import secretmanager
|
||||
|
||||
secret_client = secretmanager.SecretManagerServiceClient()
|
||||
|
||||
|
||||
def get_jwt_secret_key() -> str:
|
||||
|
||||
config = Config.collection.get("config/music-tools")
|
||||
|
||||
if config.jwt_secret_key is None or len(config.jwt_secret_key) == 0:
|
||||
raise KeyError("no jwt secret key found")
|
||||
|
||||
return config.jwt_secret_key
|
||||
return secret_client.access_secret_version(request={"name": JWT_SECRET_URI}).payload.data.decode("UTF-8")
|
||||
|
||||
|
||||
def generate_key(user: User, timeout: datetime | timedelta = timedelta(minutes=60)) -> str:
|
||||
|
@ -10,6 +10,12 @@ from .tasks import run_user_playlist_task
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
SPOT_CLIENT_URI = "projects/sarsooxyz/secrets/spotify-client/versions/latest"
|
||||
SPOT_SECRET_URI = "projects/sarsooxyz/secrets/spotify-secret/versions/latest"
|
||||
LASTFM_CLIENT_URI = "projects/sarsooxyz/secrets/lastfm-client/versions/latest"
|
||||
JWT_SECRET_URI = "projects/sarsooxyz/secrets/jwt-secret/versions/latest"
|
||||
COOKIE_SECRET_URI = "projects/sarsooxyz/secrets/cookie-secret/versions/latest"
|
||||
|
||||
|
||||
def queue_run_user_playlist(username: str, playlist_name: str):
|
||||
config = Config.collection.get("config/music-tools")
|
||||
|
@ -7,9 +7,13 @@ from spotframework.net.network import Network as SpotifyNetwork, SpotifyNetworkE
|
||||
from spotframework.net.user import NetworkUser
|
||||
from fmframework.net.network import Network as FmNetwork
|
||||
from music.model.user import User
|
||||
from music.model.config import Config
|
||||
|
||||
from music.cloud import SPOT_CLIENT_URI, SPOT_SECRET_URI, LASTFM_CLIENT_URI
|
||||
|
||||
from google.cloud import secretmanager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
secret_client = secretmanager.SecretManagerServiceClient()
|
||||
|
||||
|
||||
def refresh_token_database_callback(user: User) -> None:
|
||||
@ -50,10 +54,11 @@ def get_authed_spotify_network(user: User) -> Optional[SpotifyNetwork]:
|
||||
|
||||
if user is not None:
|
||||
if user.spotify_linked:
|
||||
config = Config.collection.get("config/music-tools")
|
||||
spot_client = secret_client.access_secret_version(request={"name": SPOT_CLIENT_URI})
|
||||
spot_secret = secret_client.access_secret_version(request={"name": SPOT_SECRET_URI})
|
||||
|
||||
user_obj = DatabaseUser(client_id=config.spotify_client_id,
|
||||
client_secret=config.spotify_client_secret,
|
||||
user_obj = DatabaseUser(client_id=spot_client.payload.data.decode("UTF-8"),
|
||||
client_secret=spot_secret.payload.data.decode("UTF-8"),
|
||||
refresh_token=user.refresh_token,
|
||||
user_id=user.username,
|
||||
access_token=user.access_token)
|
||||
@ -92,8 +97,9 @@ def get_authed_lastfm_network(user: User) -> Optional[FmNetwork]:
|
||||
|
||||
if user is not None:
|
||||
if user.lastfm_username:
|
||||
config = Config.collection.get("config/music-tools")
|
||||
return FmNetwork(username=user.lastfm_username, api_key=config.last_fm_client_id)
|
||||
lastfm_client = secret_client.access_secret_version(request={"name": LASTFM_CLIENT_URI})
|
||||
|
||||
return FmNetwork(username=user.lastfm_username, api_key=lastfm_client.payload.data.decode("UTF-8"))
|
||||
else:
|
||||
logger.error(f'{user.username} has no last.fm username')
|
||||
else:
|
||||
|
@ -11,14 +11,8 @@ class Config(Model):
|
||||
"""Set correct path in Firestore
|
||||
"""
|
||||
|
||||
spotify_client_id = TextField()
|
||||
spotify_client_secret = TextField()
|
||||
last_fm_client_id = TextField()
|
||||
|
||||
playlist_cloud_operating_mode = TextField() # task, function
|
||||
"""Determines whether playlist and tag update operations are done by Cloud Tasks or Functions
|
||||
"""
|
||||
secret_key = TextField()
|
||||
jwt_secret_key = TextField()
|
||||
jwt_max_length = NumberField()
|
||||
jwt_default_length = NumberField()
|
||||
|
@ -1,4 +1,5 @@
|
||||
from flask import Flask, render_template, redirect, session, flash, url_for
|
||||
from google.cloud import secretmanager
|
||||
|
||||
import logging
|
||||
import os
|
||||
@ -6,9 +7,10 @@ import os
|
||||
from music.auth import auth_blueprint
|
||||
from music.api import api_blueprint, player_blueprint, fm_blueprint, \
|
||||
spotfm_blueprint, spotify_blueprint, admin_blueprint, tag_blueprint
|
||||
from music.model.config import Config
|
||||
from music.cloud import COOKIE_SECRET_URI
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
secret_client = secretmanager.SecretManagerServiceClient()
|
||||
|
||||
|
||||
def create_app():
|
||||
@ -20,11 +22,7 @@ def create_app():
|
||||
|
||||
app = Flask(__name__, static_folder=os.path.join(os.path.dirname(__file__), '..', 'build'), template_folder="templates")
|
||||
|
||||
config = Config.collection.get("config/music-tools")
|
||||
if config is not None:
|
||||
app.secret_key = config.secret_key
|
||||
else:
|
||||
logger.error('no config returned, skipping secret key')
|
||||
app.secret_key = secret_client.access_secret_version(request={"name": COOKIE_SECRET_URI}).payload.data.decode("UTF-8")
|
||||
|
||||
app.register_blueprint(auth_blueprint, url_prefix='/auth')
|
||||
app.register_blueprint(api_blueprint, url_prefix='/api')
|
||||
|
23
poetry.lock
generated
23
poetry.lock
generated
@ -291,6 +291,23 @@ protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4
|
||||
[package.extras]
|
||||
libcst = ["libcst (>=0.3.10)"]
|
||||
|
||||
[[package]]
|
||||
name = "google-cloud-secret-manager"
|
||||
version = "2.12.6"
|
||||
description = "Secret Manager API API client library"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
google-api-core = {version = ">=1.32.0,<2.0.0 || >=2.8.0,<3.0.0dev", extras = ["grpc"]}
|
||||
grpc-google-iam-v1 = ">=0.12.4,<1.0.0dev"
|
||||
proto-plus = ">=1.22.0,<2.0.0dev"
|
||||
protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev"
|
||||
|
||||
[package.extras]
|
||||
libcst = ["libcst (>=0.2.5)"]
|
||||
|
||||
[[package]]
|
||||
name = "google-cloud-tasks"
|
||||
version = "2.10.4"
|
||||
@ -835,7 +852,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "~3.10"
|
||||
content-hash = "fef135789689e4ab5a67d8e37ce0da3ca5b772a500a3ce9ac69ac5b2876b5175"
|
||||
content-hash = "ab592da5f6b73bd51841928689b332bdd994e188398b85a1d5e48cc402c89dac"
|
||||
|
||||
[metadata.files]
|
||||
alabaster = [
|
||||
@ -923,6 +940,10 @@ google-cloud-pubsub = [
|
||||
{file = "google-cloud-pubsub-2.13.10.tar.gz", hash = "sha256:3e746a1a97c96bdc63fc5499529ed7262f1464f6de8c8bae6238c12200919ac0"},
|
||||
{file = "google_cloud_pubsub-2.13.10-py2.py3-none-any.whl", hash = "sha256:1a29795265ddb2eff23b4e4c2c4594a56f5a861827fe1cc72c53de42a3a13def"},
|
||||
]
|
||||
google-cloud-secret-manager = [
|
||||
{file = "google-cloud-secret-manager-2.12.6.tar.gz", hash = "sha256:7aaba2997f43f8c3b35903efc54c389a802f39853ba81e81e1190f093420ecf6"},
|
||||
{file = "google_cloud_secret_manager-2.12.6-py2.py3-none-any.whl", hash = "sha256:585e2ccd05038526b39eeabfe6932a7398341a76770ee0dd797c8581313e5212"},
|
||||
]
|
||||
google-cloud-tasks = [
|
||||
{file = "google-cloud-tasks-2.10.4.tar.gz", hash = "sha256:650f4f43be725841103727ea3bc13227ae9ebaa2f99dadaad53888831cfc1d70"},
|
||||
{file = "google_cloud_tasks-2.10.4-py2.py3-none-any.whl", hash = "sha256:d5bc498eff25b145bd0a2d67ee466814dc9baf259a5ee8c4187aef267f4d83d4"},
|
||||
|
@ -19,6 +19,7 @@ Flask = "^2.1.3"
|
||||
google-cloud-firestore = "<=2.3.4"
|
||||
google-cloud-logging = "^3.2.1"
|
||||
google-cloud-pubsub = "^2.13.4"
|
||||
google-cloud-secret-manager = "^2.12.6"
|
||||
google-cloud-tasks = "^2.10.0"
|
||||
requests = "^2.28.1"
|
||||
PyJWT = "^2.4.0"
|
||||
|
Loading…
Reference in New Issue
Block a user