Users in write only
i got a particular application where i want that a user could only write to a DB without the reading permission. is this possible?
Comments
Hi Pietro,
this depends on your application.
In general, you cannot define DB write access without having read access.
This said, you can though define a user that only has SQL insert rights to specific tables without select rights.
I have not tested this though, but SMP allows this type of setup.
Best Regards
Timo
If the access is via SQL (INSERT, UPDATE), it is possible.
You can create a role with RW access to the database resource and grant INSERT privileges without the SELECT privilege.
If the access is via Global (SET), it is not so simple. Because you need to grant RW permission to the Database Resource and, consequently, the user will be able to read the data from the global resource.
For example, you create the logs_w role and grant it to the user
%SYS>do ##class(Security.Roles).Create("logs_w", "", "%DB_LOGS:RW")
%SYS>do ##class(%SQL.Statement).%ExecDirect(,"GRANT logs_w TO appuser")
%SYS>set $NAMESPACE="LOGS"
LOGS>do ##class(%SQL.Statement).%ExecDirect(,"GRANT INSERT ON app.Log TO logs_w")If the user tries to execute a SELECT they will receive an error
LOGS>do $SYSTEM.Security.Login("appuser")
LOGS>do $SYSTEM.SQL.Shell()
[SQL]LOGS>>SELECT * FROM app.Log
ERROR #5540: SQLCODE: -99 Message: User appuser is not privileged for the operationIf the user tries to execute an INSERT, it will succeed.
[SQL]LOGS>>INSERT INTO app.Log VALUES ('Test 1')
1. INSERT INTO app.Log VALUES ('Test 1')
1 Row Affected
---------------------------------------------------------------------------But this permission is not valid for globals, the user will be able to read
LOGS>zw ^app.LogD
^app.LogD=1
^app.LogD(1)=$lb("","Test 1")In this case you can follow other strategies, such as Applications and Privilege Escalation. Here you isolate the database and the user does not have default access when logging in. Access is granted temporarily when executing a method/routine. A simple example:
In a database to which the user has default access, create a method that receives temporary privileges to write to the protected database
Class service.Log
{
ClassMethod write(msg As %String) As %Status
{
do $SYSTEM.Security.AddRoles("grant_logs_w")
new $NAMESPACE
set $NAMESPACE="LOGS"
do ##class(%SQL.Statement).%ExecDirect(,"INSERT INTO app.Log VALUES (?)", msg)
return 1
}
}Create a Privileged Routine Applications for this method
set p("Name") = "grant_logs_w"
set p("CookiePath") = "grant_logs_w/"
set p("Description") = "Applications and Privilege Escalation"
set p("Type") = 4
set p("Resource") = "%Development"
set p("AutheEnabled") = 64
set p("Enabled") = 1
set p("MatchRoles") = ":logs_w"
set p("Routines") = "service.Log:APP:1"
do ##class(Security.Applications).Create("grant_logs_w", .p)The user does not have access to the LOGS database, but can execute the write method with temporary privileges.
APP>w $ROLES
%Developer,%DB_APP
APP>do ##class(service.Log).write("Test 2")Write to a DataBase with no Read is not possible by principle.
Think if indices and other information for structural maintenance.
BUT:
You may create your own WRITE in a method, function, background job, ...
that elevates to RW access and drops it at completion.
details: Privileged Routine Applications