Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ADR about division of concerns between Perl and PL/pgSQL #8622

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ehuelsmann
Copy link
Member

No description provided.


For example: the Perl layer will need to provide an entire GL transaction
to be saved, in a single call. The called PL/pgSQL will then verify aspects
such as balancedness and minimally required reporting units.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A way to marshall such data structures is by using JSON.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording of your example seems to imply that when adding or updating a database row, the perl layer must always provide the complete row. I think it is extremely likely that the PL/pgSQL layer can simplify the perl call in certain circumstances when data has defaults, references, etc. Or when the call is used in a lot of places. I don't agree that the perl to PL/pgSQL mapping is 1:1 (i.e. "entire transaction")

Now it may be the case that the business logic around GL Transactions implies that the entire GL transaction will be provided when it is added, but not in other cases.

In this case, I would say something along the lines of "When adding a new GL transaction, the Perl layer will provide all columns needed by PL/pgSQL layer, but when updating a GL transaction the Perl layer may only provide the needed update data."

Maybe I am not clear what the reason for this example, because I can also understand it without the example. But if you are going to have examples, I think you need more than 1 to get the point across.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording of your example seems to imply that when adding or updating a database row, the perl layer must always provide the complete row.

Actually, the example proposes something even stronger: it proposes that for a transaction, the Perl side delivers the "header" (i.e. the ar/ap/gl table record) and the journal lines. Only this way, the Pg side can validate that a complete transaction (as far as the values are applicable) is being sent by the Perl side. Obviously, it would also be possible to have the Perl side only send the modified journal lines, but then the Pg side will have to construct the entire transaction and verify that - with the changes - it's still balanced. By the way, currently, "user__save", "credit_account__save" e.a. also provide the entire saved record (just not a hierarchical structure).

I'm open to ideas on how to maintain consistency in the hierarchical structure of records that the functional concept of "journal transaction" is, because the above is what I could come up with...

These recent developments beg for clarity on the concerns to be fulfilled by
the active layer in PostgreSQL (PL/pgSQL) and the Perl layer.

## Decision
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The decision doesn't state what should happen on the security side of things. Should the schema enforce this way of working by granting EXECUTE on the procedural interface and revoking INSERT access on the relevant tables? Given our fine-grained security model and our use of CURRENT_USER to create audit trails, SECURITY DEFINER should only be used for bits that don't cause audit logs. (Even if the owner isn't set to a super user, it'll cause changes to CURRENT_USER and/or SESSION_USER.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with your comment. Will the database or perl enforce security? This is important to clarify.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In our current model at least the database has to enforce security: the database is what we have fallen back on until now and I think that's not such a bad principle. The question at hand is whether the user will be allowed to insert anything in the tables governed by the stored procedures. My initial idea was "no"; which then means we need separate roles for inserting data in the tables (to which the stored procedure is "escalated" using SECURITY DEFINER), however, it also means that the code triggered by the INSERTs in the stored procedure cannot trace back to the calling user, because SECURITY DEFINER overrules (both?) CURRENT_USER and SESSION_USER.

Just looked it up; https://www.postgresql.org/docs/15//sql-set-session-authorization.html : SESSION_USER isn't modified. Which is a good thing, because we could then use that for audit trail tracking... In that case, we have a trail back to the authenticated user and we may actually use SECURITY DEFINER to escalate privileges to a level only available to the stored procedure (for inserting the rows).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants