Nevermind, I'm able to test this as well, thanks!

On Friday, June 19, 2020 at 5:39:34 PM UTC-7, Venkata Siva Naga Tatikonda 
wrote:
>
> Hello Mike,
>
> Need another suggestion similar to this:
>
> Instead of fetching password from AWS SecretsManager every time, we want 
> to establish the connection using the cached credentials and it that 
> doesn't work then only we would make AWS API call for secrets.
>
> @event.listens_for(db, "do_connect")
> def receive_do_connect(dialect, conn_rec, cargs, cparams):
>    try:
>      connection = <required method for mysql dialect>
>       return connection
>    except:
>     secret = get_new_secret()
>     cparams['password'] = secret
>     return None
>
> However, I'm not quite sure what DBAPI or sqlalchemy function to use which 
> can return the connection similar to how mysql dialect normally does.
>
> We are creating engine like this, mysql://user:password@host/database. If 
> we don't provide in dialect+driver format, what does sqlalchemy uses by 
> default to establish DBAPI connections ?
>
> Also, need some more clarity about these statements here:
>
> "Return a DBAPI connection to halt further events from invoking; the 
> returned connection will be used."
> Does above return raw/low-level DBAPI connection here for that particular 
> request/operation or this connection still be integrated with QueuePool 
> provider ?
>
>
> "Return None to allow control to pass to the next event handler and 
> ultimately to allow the dialect to connect normally, given the updated 
> arguments."
> How does this work in above case where we just used mysql:// when creating 
> engine? Which backend library it uses to communicate with mysql server for 
> DBAPI connection? Do we have any documentation or link I could use to 
> understand this better? I'm more interested in understanding 'ultimately 
> to allow the dialect to connect normally' this in details on how exactly 
> (like what functions it uses) it works. 
>
> Note:- I've looked at the code for base.py/mysqldb.py in 
> sqlalchemy.dialects.mysql but couldn't quite get it.
>
> Thanks for your help in advance.
>
> Regards,
> Pavan.
>
>
>
>
> On Friday, June 19, 2020 at 6:37:51 AM UTC-7, Mike Bayer wrote:
>>
>> OK great, I was just throwing out assorted debugging techniques to help 
>> you find the problem 
>>
>>
>> On Fri, Jun 19, 2020, at 12:43 AM, Venkata Siva Naga Tatikonda wrote:
>>
>> Thanks Mike, able to achieve the desired results.
>>
>>
>> On Thursday, June 18, 2020 at 12:36:15 PM UTC-7, Mike Bayer wrote:
>>
>>
>>
>> On Wed, Jun 17, 2020, at 8:59 PM, Venkata Siva Naga Tatikonda wrote:
>>
>> Hello Mike,
>>
>> I've embedded the following code within the get_session function where 
>> the get_engine function returns the engine object. However, I'm still 
>> seeing that the rotated database credentials are not being used when 
>> creating new connections
>>
>> def get_engine(args):
>>       # our code to create engine
>>       return engine
>>
>> def get_session(args):
>>       db = get_engine(args)
>>
>>       @event.listens_for(db, "do_connect")
>>       def receive_do_connect(dialect, conn_rec, cargs, cparams):
>>             secret = get_new_secret()  # used our custom code to get 
>> password from secrets manager
>>             cparams['password'] = secret
>>
>>       # create scoped_session using sessionmaker by binding the engine 
>> returned from above
>>       return session
>>
>> We import get_session from the respective module and import it into other 
>> application related modules where it needs database communication.
>>
>>
>> wherever the create_engine() is being called, that's where this event 
>> must be set up.  there must be only exactly one event established on this 
>> Engine object and it must be before the engine has been used to make any 
>> connections.
>>
>> that is, this event listener must be independent of any logic that is 
>> related to per-request / per-session / etc.  must be global to the Engine.
>>
>>
>>
>>
>>
>> Here're the steps I followed for my testing:
>> 1. Initial working database credentials in both database & AWS 
>> SecretsManager
>> 2. Ran tests and all went good (created new connection & checked out from 
>> pool for this step)
>> 3. Closed session (It returned the connection back to pool, did 
>> rollback-on-return)
>> 4. Waited for 6 mins (pool_recycle is 5 mins) and also rotated 
>> credentials in both DB & AWS SecretsManager
>> 5. Right after 6th minute, exceeded timeout; recycling and closed 
>> connection
>> 6. Tried to create new connection but failed, "Error on connect(): (1045, 
>> \"Access denied for user '<username>'@'<host>' (using password: YES)\")" 
>> 7. It kept re-trying as we wait for 3 mins 
>> 8. We reverted the database credentials to old set of user/pass where 
>> tests worked in step#2 and its able to created new connection & checkout 
>> from pool
>> 9. Ran tests again and succeeded this time.
>>
>>
>> Would you be able to take a look at my scenario and provide some insight 
>> on the behavior ?
>>
>> Thanks,
>> Pavan
>>
>> On Wednesday, June 17, 2020 at 3:10:41 PM UTC-7, Venkata Siva Naga 
>> Tatikonda wrote:
>>
>> Basically, within get_session function we call get_engine method and if 
>> an engine already exists it skips the creation and uses it. If an engine 
>> doesn't exist then it will create one and uses it. After that, we create a 
>> sessionmaker object by binding that engine & some other arguments and then 
>> create a scoped_session.
>>
>> Thanks,
>> Pavan
>>
>> On Wednesday, June 17, 2020 at 2:17:35 PM UTC-7, Venkata Siva Naga 
>> Tatikonda wrote:
>>
>> Hello Mike,
>>
>> Thanks for your insight and response.
>>
>> Just want to let you know that, we are using scoped_session with a 
>> session_factory object to db connections. Does this approach still suitable 
>> for connections using session ?
>>
>> Also, we have custom module where we have separate functions for 
>> generating an engine and creating session object and we import this custom 
>> module in other application python files to create and close sessions 
>> accordingly.
>>
>> Thanks,
>> Pavan.
>>
>> On Wednesday, June 17, 2020 at 5:35:59 AM UTC-7, Mike Bayer wrote:
>>
>> We're going to need an FAQ entry for this since this now comes up 
>> regularly for everyone using AWS.
>>
>> There are two methods to manipulate the parameters sent to connect that 
>> are independent of the URL.  They are both described now at 
>> https://docs.sqlalchemy.org/en/13/core/engines.html#custom-dbapi-args 
>> and you probably want to use the "do_connect" event.
>>
>> so you have the pool_recycle, that's good.  the next part is the event is 
>> like this:
>>
>> from sqlalchemy import event
>>
>> db = create_engine('mysql://<aws url>')
>>
>> @event.listens_for(db, "do_connect")
>> def receive_do_connect(dialect, conn_rec, cargs, cparams):
>>     secret = get_new_secret()
>>     cparams['password'] = secret
>>
>> Above assumes you are setting just the password, but "cargs, cparams" are 
>> the literal arguments passed to mysqldb.connect(), so you can put whatever 
>> you need into either of those collections (modify the list and/or 
>> dictionary in place).   I'm assuming you have some function that can 
>> retrieve the latest credentials.
>>
>> On Wed, Jun 17, 2020, at 1:28 AM, Venkata Siva Naga Tatikonda wrote:
>>
>> Hello Everyone, 
>>
>> Need some suggestion/insight on some use case we have:
>>
>> We have python django web application which uses sqlalchemy v1.3.13 
>> (mysqldb) to communicate with AWS Aurora (RDS). This application uses AWS 
>> Secrets Manager for managing database credentials and utilizing sqlalchemy 
>> (w/ mysqldb & queuepool) to read user/password during application start-up 
>> via settings.py/manage.py. 
>>
>> For security reasons, we have to rotate database credentials frequently 
>> and for that we are using AWS Lambda to update in the Aurora DB & secrets 
>> manager. We are using pool_recycle w/ 5 mins and also MYSQL database issues 
>> a disconnect if there is any connection is open & idle for more than 8 
>> hours, so when this happens and pool creates a new connection then it fails 
>> the authentication. We don't see anyway for engine object to 
>> reload/refresh/re-read updated credentials other than re-deploying or 
>> restarting our services for this issue.
>>
>> Is there any documentation on how we could re-create/reload engine or 
>> other mechanisms to handle/address this situation ?
>>
>>
>> Thanks,
>> Pavan.
>>
>>
>> --
>> SQLAlchemy - 
>> The Python SQL Toolkit and Object Relational Mapper
>>  
>> http://www.sqlalchemy.org/
>>  
>> To post example code, please provide an MCVE: Minimal, Complete, and 
>> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
>> description.
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "sqlalchemy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to sqlal...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/sqlalchemy/ed50fe16-f759-4d14-a111-62457f4009c5o%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/sqlalchemy/ed50fe16-f759-4d14-a111-62457f4009c5o%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>>
>>
>> --
>> SQLAlchemy - 
>> The Python SQL Toolkit and Object Relational Mapper
>>  
>> http://www.sqlalchemy.org/
>>  
>> To post example code, please provide an MCVE: Minimal, Complete, and 
>> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
>> description.
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "sqlalchemy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to sqlal...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/sqlalchemy/b08c2722-d1c0-4c65-85c6-61b4e756680bo%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/sqlalchemy/b08c2722-d1c0-4c65-85c6-61b4e756680bo%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>>
>>
>> --
>> SQLAlchemy - 
>> The Python SQL Toolkit and Object Relational Mapper
>>  
>> http://www.sqlalchemy.org/
>>  
>> To post example code, please provide an MCVE: Minimal, Complete, and 
>> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
>> description.
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "sqlalchemy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to sqlal...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/sqlalchemy/95ab9371-73fc-4835-be86-28fe7ae5f93co%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/sqlalchemy/95ab9371-73fc-4835-be86-28fe7ae5f93co%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>>
>>

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/13fda2bc-7806-4281-a9ec-d4c62ed69d08o%40googlegroups.com.

Reply via email to