Discussion (2)1
Log in or sign up to continue

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 operation

If 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")