<!-- 
RSS generated by JIRA (1001.0.0-SNAPSHOT#100246-sha1:7a5c50119eb0633d306e14180817ddef5e80c75d) at Thu Feb 08 23:15:57 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary add field=key&field=summary to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>FOLIO Jira</title>
    <link>https://folio-org.atlassian.net</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>1001.0.0-SNAPSHOT</version>
        <build-number>100246</build-number>
        <build-date>07-02-2024</build-date>
    </build-info>

<item>
            <title>[FOLIO-1794] SPIKE: db connection provision and pooling</title>
                <link>https://folio-org.atlassian.net/browse/FOLIO-1794</link>
                <project id="10290" key="FOLIO">FOLIO</project>
                    <description>&lt;p&gt;When a module is deployed it gets DB connection params (user/pass/db) in environment variables. In practice, this means a given module instance is able to connect to a single DB instance only. RMB based modules use this database user/role to create a separate schema for each tenant and a dedicated user/role to access this schema..&lt;/p&gt;

&lt;p&gt;The main benefit of this approach is that it allows for a single connection pool (Postgres connections cost ~ 10mb) to be maintained for the module instance, across all tenants. &lt;/p&gt;

&lt;p&gt;The disadvantage, is that it does not provide access isolation between tenants &amp;#8211; e.g a connection retrieved from the pool by tenant A has rights to access schema owned by tenant B. It&apos;s not currently possible, for a selected tenant to use different connection params and, in effect, connect to a physically separate database instance or constrain access to a particular schema only.&lt;/p&gt;

&lt;p&gt;We need to consider how to improve this to allow for better access isolation.&lt;/p&gt;

&lt;p&gt;Factors to account for:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;scalability (e.g ability to share connections, ability to shard, ability to load balance with tools like PGBouncer)&lt;/li&gt;
	&lt;li&gt;security (tenant isolation)&lt;/li&gt;
	&lt;li&gt;deployment flexibility (e.g due to data privacy requirements)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Notes: FOLIO uses schema-level tenant isolation. Postgres allows for multiple schemas per database.&lt;/p&gt;

&lt;p&gt;For each combination of tenant and module RMB creates a separate schema and a dedicated user/role for that schema. Currently RMB has a pool for each combination of tenant and module, and a database connection is NOT reused for a different tenant. Changing the user requires re-establishing a new connection.&lt;/p&gt;

&lt;p&gt;However, RMB might implement reusing connections across tenants. PostgreSQL schemas can be authorized to specific roles (users) but to avoid resetting connections, the connecting user needs all roles to be granted and needs to escalate/de-escalte its role when executing statements&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.postgresql.org/docs/current/sql-set-role.html&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;SET ROLE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;or&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.postgresql.org/docs/current/sql-set-session-authorization.html&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;SET SESSION AUTHORIZATION&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;(similar to sudo). This obviously does not protect against malicious modules wanting to perform cross-tenant modifications but is a good protection from unintended DB modifications.&lt;/p&gt;

&lt;p&gt;Managing connections in Postgres: &lt;a href=&quot;https://brandur.org/postgres-connections&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;https://brandur.org/postgres-connections&lt;/a&gt;&lt;br/&gt;
 Switching roles after the connection has been established: &lt;a href=&quot;https://stackoverflow.com/questions/2998597/switch-role-after-connecting-to-database&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;https://stackoverflow.com/questions/2998597/switch-role-after-connecting-to-database&lt;/a&gt;&lt;br/&gt;
 Connection pooling in Postgres: &lt;a href=&quot;https://www.citusdata.com/blog/2017/05/10/scaling-connections-in-postgres/&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;https://www.citusdata.com/blog/2017/05/10/scaling-connections-in-postgres/&lt;/a&gt;&lt;br/&gt;
 Tuning &lt;tt&gt;max_connections&lt;/tt&gt; in PostgreSQL: &lt;a href=&quot;https://www.cybertec-postgresql.com/en/tuning-max_connections-in-postgresql/&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;https://www.cybertec-postgresql.com/en/tuning-max_connections-in-postgresql/&lt;/a&gt;&lt;/p&gt;</description>
                <environment></environment>
        <key id="79468">FOLIO-1794</key>
            <summary>SPIKE: db connection provision and pooling</summary>
                <type id="10003" iconUrl="https://folio-org.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium">Task</type>
                                            <priority id="10002" iconUrl="https://dev.folio.org/assets/jira-priority/jira-p3.svg">P3</priority>
                        <status id="1" iconUrl="https://folio-org.atlassian.net/images/icons/statuses/open.png" description="The issue is open and ready for the assignee to start work on it.">Open</status>
                    <statusCategory id="2" key="new" colorName="blue-gray"/>
                                    <resolution id="-1">Unresolved</resolution>
                                                        <assignee accountid="-1">Unassigned</assignee>
                                                                <reporter accountid="557058:b8e64633-1f7c-402d-9caf-9959a5ba5d0d">Jakub Skoczen</reporter>
                                    <labels>
                            <label>platform-backlog</label>
                    </labels>
                <created>Fri, 8 Feb 2019 21:10:37 +0000</created>
                <updated>Tue, 15 Nov 2022 15:16:42 +0000</updated>
                                                                                <due></due>
                            <votes>0</votes>
                                    <watches>5</watches>
                                                                <comments>
                                                            <comment id="191812" author="5ee89462f7aa140abd82d11d" created="Mon, 11 Feb 2019 14:45:18 +0000"  >&lt;p&gt;If an attacker can switch the role that attack continues to be successful when we reuse connections only for the same tenant and not for other tenants. We don&apos;t get more security but require more connections.&lt;/p&gt;</comment>
                                                            <comment id="191814" author="5ee89462f7aa140abd82d11d" created="Fri, 15 Feb 2019 15:13:37 +0000"  >&lt;p&gt;This is the unit test that checks that the schema-level tenant isolation works: &lt;a href=&quot;https://github.com/folio-org/raml-module-builder/blob/v23.5.0/domain-models-runtime/src/test/java/org/folio/rest/persist/PostgresClientIT.java#L373-L387&quot; class=&quot;external-link&quot; rel=&quot;nofollow noreferrer&quot;&gt;https://github.com/folio-org/raml-module-builder/blob/v23.5.0/domain-models-runtime/src/test/java/org/folio/rest/persist/PostgresClientIT.java#L373-L387&lt;/a&gt;&lt;/p&gt;</comment>
                                                            <comment id="189062" author="63e2a2771b13d42998e4e706" created="Mon, 14 Dec 2020 09:01:48 +0000"  >&lt;blockquote&gt;&lt;p&gt;The standard way DB connections are set up in FOLIO at this point (when using RMB) is that a single module instance shares the DB connection params (user/pass/db) across all tenants.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;I thought that RAML Module Builder generated a user for each tenant and used that to connect to the database based upon the tenant provided in the API request.&lt;/p&gt;

&lt;p&gt;Have I misunderstood that or has that changed?&lt;/p&gt;</comment>
                                                            <comment id="189072" author="5ee89462f7aa140abd82d11d" created="Wed, 11 Aug 2021 08:13:50 +0000"  >&lt;p&gt;No, RMB creates a user for each tenant and uses that to connect to the database.&lt;/p&gt;

&lt;p&gt;Currently the database connection is used by a single database user only.&lt;/p&gt;

&lt;p&gt;This Jira suggest to allow a single database connection to be re-used by different database users.&lt;/p&gt;</comment>
                                                            <comment id="189078" author="63e2a2771b13d42998e4e706" created="Wed, 11 Aug 2021 08:44:01 +0000"  >&lt;p&gt;&lt;a href=&quot;https://folio-org.atlassian.net/secure/ViewProfile.jspa?accountId=5ee89462f7aa140abd82d11d&quot; class=&quot;user-hover&quot; rel=&quot;5ee89462f7aa140abd82d11d&quot; data-account-id=&quot;5ee89462f7aa140abd82d11d&quot; accountid=&quot;5ee89462f7aa140abd82d11d&quot; rel=&quot;noreferrer&quot;&gt;Julian Ladisch&lt;/a&gt; Thank you for responding to my question.&lt;/p&gt;

&lt;p&gt;Let me try to check my understanding of the current behaviour:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;RMB creates a new database user for each tenant (using the provided admin database user)&lt;/li&gt;
	&lt;li&gt;Those tenant specific database users are used when making database requests for a specific tenant&lt;/li&gt;
	&lt;li&gt;Each database connection only uses one of these tenant specific users, meaning that connections are not shared between tenants (and connection pools are per tenant)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;What parts of that have I misunderstood?&lt;/p&gt;</comment>
                                                            <comment id="189084" author="5ee89462f7aa140abd82d11d" created="Wed, 11 Aug 2021 08:49:10 +0000"  >&lt;p&gt;None.&lt;/p&gt;

&lt;p&gt;You&apos;ve asked:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Have I misunderstood that or has that changed?&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I&apos;ve answered &quot;No&quot; to both parts of your questions.&lt;/p&gt;

&lt;p&gt;&#160;&lt;/p&gt;</comment>
                                                            <comment id="189087" author="63e2a2771b13d42998e4e706" created="Wed, 11 Aug 2021 09:22:20 +0000"  >&lt;p&gt;&lt;a href=&quot;https://folio-org.atlassian.net/secure/ViewProfile.jspa?accountId=5ee89462f7aa140abd82d11d&quot; class=&quot;user-hover&quot; rel=&quot;5ee89462f7aa140abd82d11d&quot; data-account-id=&quot;5ee89462f7aa140abd82d11d&quot; accountid=&quot;5ee89462f7aa140abd82d11d&quot; rel=&quot;noreferrer&quot;&gt;Julian Ladisch&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;None.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Ok. Thank you for clarifying my understanding. Apologies for the inconvenience and the confusion caused by the original comment.&lt;/p&gt;</comment>
                                                            <comment id="189090" author="5ee89462f7aa140abd82d11d" created="Wed, 11 Aug 2021 09:27:20 +0000"  >&lt;p&gt;I&apos;ve reworded the first paragraph of this issue&apos;s description to avoid some misunderstanding it may have caused.&lt;/p&gt;</comment>
                                                            <comment id="189093" author="63e2a2771b13d42998e4e706" created="Wed, 11 Aug 2021 10:54:21 +0000"  >&lt;p&gt;&lt;a href=&quot;https://folio-org.atlassian.net/secure/ViewProfile.jspa?accountId=5ee89462f7aa140abd82d11d&quot; class=&quot;user-hover&quot; rel=&quot;5ee89462f7aa140abd82d11d&quot; data-account-id=&quot;5ee89462f7aa140abd82d11d&quot; accountid=&quot;5ee89462f7aa140abd82d11d&quot; rel=&quot;noreferrer&quot;&gt;Julian Ladisch&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;I&apos;ve reworded the first paragraph of this issue&apos;s description to avoid some misunderstanding it may have caused.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Thank you, I appreciate that, it reads to me much better and more specifically now.&lt;/p&gt;</comment>
                                                            <comment id="189095" author="5ee89462f7aa140abd82d11d" created="Tue, 15 Nov 2022 15:16:42 +0000"  >&lt;p&gt;The &quot;SET ROLE&quot; solution has been implemented by 
    &lt;span class=&quot;jira-issue-macro resolved&quot; data-jira-key=&quot;RMB-664&quot; &gt;
                &lt;a href=&quot;https://folio-org.atlassian.net/browse/RMB-664&quot; class=&quot;jira-issue-macro-key issue-link&quot;  title=&quot;PoC: implement one connection pool for all tenants&quot; &gt;
            &lt;img class=&quot;icon&quot; src=&quot;https://folio-org.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10322?size=medium&quot; /&gt;
            RMB-664
        &lt;/a&gt;
                                                    &lt;span class=&quot;aui-lozenge aui-lozenge-subtle aui-lozenge-success jira-macro-single-issue-export-pdf&quot;&gt;Closed&lt;/span&gt;
            &lt;/span&gt;
 = 
    &lt;span class=&quot;jira-issue-macro&quot; data-jira-key=&quot;UXPROD-3209&quot; &gt;
                &lt;a href=&quot;https://folio-org.atlassian.net/browse/UXPROD-3209&quot; class=&quot;jira-issue-macro-key issue-link&quot;  title=&quot;Implement one connection pool per RMB module for all tenants&quot; &gt;
            &lt;img class=&quot;icon&quot; src=&quot;https://folio-org.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10309?size=medium&quot; /&gt;
            UXPROD-3209
        &lt;/a&gt;
                                                    &lt;span class=&quot;aui-lozenge aui-lozenge-subtle aui-lozenge-complete jira-macro-single-issue-export-pdf&quot;&gt;Open&lt;/span&gt;
            &lt;/span&gt;
 and can be enabled by setting DB_MAXSHAREDSPOOLSIZE env variable.&lt;/p&gt;</comment>
                    </comments>
                <issuelinks>
                            <issuelinktype id="10003">
                    <name>Relates</name>
                                            <outwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="57296">RMB-664</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="79900">FOLIO-1935</issuekey>
        </issuelink>
                            </outwardlinks>
                                                                <inwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="56684">RMB-680</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="79655">FOLIO-2031</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="12032">UXPROD-3209</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="57295">RMB-663</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="57401">RMB-739</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="13076">UXPROD-1819</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                    </issuelinks>
                <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <customfield id="customfield_10000" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummarycf">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10057" key="com.atlassian.jira.plugin.system.customfieldtypes:select">
                        <customfieldname>Development Team</customfieldname>
                        <customfieldvalues>
                                <customfieldvalue key="10144"><![CDATA[Core: Platform]]></customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        <customfield id="customfield_10019" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|i01zn2:r</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_10020" key="com.pyxis.greenhopper.jira:gh-sprint">
                        <customfieldname>Sprint</customfieldname>
                        <customfieldvalues>
                                <customfieldvalue id="994">CP: ready for planning</customfieldvalue>
    <customfieldvalue id="773">CP: Roadmap backlog</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                            <customfield id="customfield_10044" key="com.atlassian.jira.plugin.system.customfieldtypes:float">
                        <customfieldname>Story Points</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>5.0</customfieldvalue>
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <customfield id="customfield_10024" key="com.atlassian.jira.ext.charting:firstresponsedate">
                        <customfieldname>[CHART] Date of First Response</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>Mon, 11 Feb 2019 14:45:18 +0000</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                </customfields>
    </item>
</channel>
</rss>