Let's go back to basics with some beginner-friendly authorization (permissions) administration in SAS Viya.
Out of the box, SAS Viya comes with a Public folder and a Public caslib to which all Authenticated Users have read-write access.
They are intended as fully public places where any user can share something with any other user. For many deployment scenarios, including classroom, lab and proof-of-concept deployments, this is great. But this simple openness is not always appropriate for larger enterprise or production deployments. A bank or government department whose SAS Viya deployment routinely deals with sensitive data and reports can't have places where users can share those things freely with anyone else in the organization - they would see such Public locations as insecure.
So, in this post we'll look at the simple steps you can take to reduce Authenticated Users' access to both the Public folder and the Public caslib to read-only. And since I imagine this will be a pretty routine thing to do in many deployments, let's focus on a scripted way to do that, rather than using the SAS Environment Manager web interface.
To make the scripts much shorter and easier to read, we'll use a couple of tools from our pyviyatools GitHub project. These are a collection of tools that the GEL team have written in python to help us with tasks for our workshop hands-on exercises, and to automate all sorts of useful things that were difficult or not currently possible to do with the SAS Viya 3 sas-admin and SAS Viya 2020.1 and later sas-viya CLIs when we wrote them. (One or two things have since become partially or completely redundant due to enhancements to the official SAS Viya CLIs, but the overwhelming majority still do something useful - to us at least - that you cannot easily do any other way).
You can read more about them in Gerry Nelson's post, Introducing the GEL pyviyatools. We have used or discussed pyviyatools in so many of our GEL posts since the release of SAS Viya, you may find something else interesting by searching the SAS Communities Library for pyviyatools.
Out of the box, when SAS Viya is first deployed, Authenticated Users are granted Read, Add and Remove permissions on the /SAS Content/Public folder itself, and Read, Update, Delete, Add and Remove permissions on the folder's contents:
This basically gives all users full read-write access to the Public folder and all of its contents, including everything in its subfolders. The only things not given to Authenticated Users are Update and Delete permissions to change or delete the Public folder itself, and Secure permission to change permissions on the Public folder or its contents.
For sites that deal with sensitive content, you might prefer to reduce this to simply granting Authenticated Users Read on the folder, and Read on its contents, something like this:
If you do, the Public folder will still exist and its contents will still be readable to everyone, but only SAS Administrators (whose permissions are not shown in the screenshot above) will have permission to put content into it. It's up to them whether they do or not. A SAS Administrator could of course delegate 'write' permissions to this folder to a trusted group.
For those readers who already understand all this, the following example script will change Authenticated Users' permissions on the Public folder from the former to the latter pattern shown above. It assumes several things:
default user geladm password xxx
Here it is:
#!/bin/sh
pyviyadir=/path/to/pyviyatools
$pyviyadir/loginviauthinfo.py
#sasviyacli=/opt/sas/viya/home/bin/sas-admin # Example for Viya 3 users
sasviyacli=/usr/bin/sas-viya # Example for Viya 4 users
#Get "/Public" folder id, store in $id
publicid=$($sasviyacli --output json folders show --path /Public | jq -r '.["id"]')
echo "The /Public ID is" $publicid
# Get the ID of the rule which grants permissions to Authenticated Users on the /Public folder
objruleid=$($pyviyadir/getruleid.py -o json -u /folders/folders/$publicid/** -p "authenticatedusers" | jq -r '.items[].id')
echo $objruleid
# Get the ID of the rule which grants permissions to Authenticated Users on the /Public folder's contents
contruleid=$($pyviyadir/getruleid.py -o json -c /folders/folders/$publicid -p "authenticatedusers" | jq -r '.items[].id')
echo $contruleid
# Show authenticated users’ current permissions on /Public folder itself before we make changes – should grant read, add and remove at this point
$sasviyacli authorization show-rule --id $objruleid --details
# Show authenticated users’ current permissions on /Public folder's contents before we make changes – should grant read, update, delete, add and remove at this point
$sasviyacli authorization show-rule --id $contruleid --details
# Delete both those rules
$sasviyacli authorization remove-rule --id $objruleid
$sasviyacli authorization remove-rule --id $contruleid
# Create a single new rule to grant Authenticated Users Read on the /Public folder and on its contents
$sasviyacli authorization create-rule --authenticated-users -o /folders/folders/$publicid/** --container-uri /folders/folders/$publicid --permissions Read -d "Authenticated users get read-only access to the Public folder and its contents"
# Validate
objruleid=$($pyviyadir/getruleid.py -o json -u /folders/folders/$publicid/** -p "authenticatedusers" | jq -r '.items[].id')
contruleid=$($pyviyadir/getruleid.py -o json -c /folders/folders/$publicid -p "authenticatedusers" | jq -r '.items[].id')
$sasviyacli authorization show-rule --id $objruleid --details
$sasviyacli authorization show-rule --id $contruleid --details
# Note that the rule id for both these tests is the same - they are both the same rule. We didn't really need to test it both ways, but it's reassuring that both tests give the same answer.
If you are familiar with this sort of script, feel free to skip the explanation which follows and move on to the next section which discusses the Public caslib. If not, read on!
To better understand the script above, let's recap how permissions work in the SAS General Authorization system.
Objects like folders and reports are identified by a REST endpoint identifying the type of object concatenated with and a globally unique ID number (a guid). Combined, these identify the object or resource uniquely, and are called a Uniform Resource Identifier, or URI. For example the Public folder in my current SAS Viya deployment is a folder (an object which is handled by the sas-folders service's folders REST endpoint: /folders/folders), and has the object ID dba5473d-afb4-44d4-866a-9671ed5878c2, and thus its objectUri is /folders/folders/dba5473d-afb4-44d4-866a-9671ed5878c2. This guid and URI are basically meaningless in any other context, so I'm not revealing any great secret to show them here.
Most SAS Viya objects do not contain other objects, but a few such as folders do. These objects therefore have associated containers, can be referenced by their containerUri. I don't know if the containerUri has to always be the same as the objectUri, but I have not yet noticed a folder where these URIs differed.
Permissions in the SAS Viya general authorization system are implemented behind the scenes with rules. A SAS Administrator can see the detail of these rules in the Rules page in SAS Environment Manager. Each rule can grant or prohibit (but not a mix of not both) any combination of seven permissions, to a single principle (typically all Authenticated Users, a group or a user), for a single SAS Viya object identified by its objectUri, or for that object's contents, identified by the object's containerUri. Or, in the special case when the permissions are the same for the object and its contents, the rule can target BOTH the object's objectUri and its containerUri at the same time. But a single rule cannot grant one set of permissions on an object itself, and a different set of permissions on the object's contents; to do that requires at least two separate rules (and sometimes, presumably for programmatic convenience, is implemented with more than two rules).
Authorization rules targeting the object's containerUri do not apply to the object itself, they only apply to its contents and to their contents too.
We saw in the screenshot above that the out-of-the box permissions granted to Authenticated Users on the Public folder and on its contents differ: Read, Add, Remove on the folder, Read, Update, Delete, Add and Remove on its contents. Does this pattern of permissions require one rule to implement, or two?
The SAS Viya general authorization system needs two rules to implement those permissions - one rule targeting the folder's Object URI to grant Authenticated Users Read Add and Remove, and a second rule targeting the folder's container URI to grant Authenticated Users Read, Update, Delete, Add and Remove permissions.
In order to secure the Public folder to make it read-only, let us delete both of these rules - we don't want Authenticated Users, or for the moment anyone else other than SAS Administrators, to have read-write access to the Public folder. We then intend to grant Authenticated Users Read access to the Public folder and its contents. Will that require one rule or two? Could we achieve this end result any other way?
The script above gives the answer to the first of those questions, near the end. As for the second question, yes, there are several other ways we could achieve this end result. Let's not worry about those for now, this way is perfectly sensible.
Our script above gets the object ID of the Public folder, and then uses a newly-updated pyviyatool called getruleid.py to get the IDs of general authorization rules targeting the folder's object URI and its container URI - we know now that there must be two separate rules.
It then deletes both rules, using $sasviyacli authorization remove-rule, and creates a single new rule, using $sasviyacli authorization create-rule, which grants Authenticated users the Read permission on both the Public folder, and its contents.
With the Public folder thus locked down, let's turn our attention to the Public caslib.
Out of the box, when SAS Viya is first deployed, Authenticated Users are granted 'Write' level permissions on the Public CAS library (caslib) which means all permissions except AlterCaslib and ManageAccess:
Much like the /SAS Content/Public folder, this basically gives all users full read-write access to the Public CAS library and all of its tables, unless different access controls are defined for any of its tables. The only things Authenticated Users are not allowed to do by default is change the name, path or options for the Public caslib, or alter its access controls.
For sites that deal with sensitive data, you might prefer to reduce this to simply granting Authenticated Users ReadInfo and Select on this caslib and its contents, something like this:
If you do, the Public caslib will still exist and its tables and their data will still be readable to everyone, but only SAS Administrators (whose permissions are not shown in the screenshot above) will have permission to create, update and delete data in its tables. It's up to them whether they do or not. A SAS Administrator could of course delegate content such 'write' permissions to this caslib (and its tables) to a group of trusted users.
For those readers who already understand all this, here's a script that will change Authenticated Users' permissions on the Public caslib from the former to the latter pattern shown above, giving them only 'Read' access. It assumes:
Here it is:
#!/bin/sh
pyviyadir=/path/to/pyviyatools
$pyviyadir/loginviauthinfo.py
#sasviyacli=/opt/sas/viya/home/bin/sas-admin # Example for Viya 3 users
sasviyacli=/usr/bin/sas-viya # Example for Viya 4 users
caslib_name=Public
json_file_cas_read=~/cas_read_permissions.json
read_group_name=* # Authenticated Users is labelled * in CAS authorization
# Show permissions for the group we're going to give Read level permissions to, before we change anything, formatted as text
$sasviyacli --output text cas caslibs list-controls --server cas-shared-default --caslib ${caslib_name} | { head -1 ; grep "${read_group_name} (group)" ;}
# Create a JSON file assigning CAS read-level permissions to the group in $read_group_name
tee ${json_file_cas_read} > /dev/null << EOF
{
"items": [
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "readInfo",
"type": "grant",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "select",
"type": "grant",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "limitedPromote",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "promote",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "createTable",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "dropTable",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "deleteSource",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "insert",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "update",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "delete",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "alterTable",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "alterCaslib",
"type": "deny",
"version": 1
},
{
"identity": "${read_group_name}",
"identityType": "group",
"permission": "manageAccess",
"type": "deny",
"version": 1
}
]
}
EOF
cat ${json_file_cas_read}
# Grant the group read level permissions on their caslib_name, assuming the CAS super-user role (-su)
$sasviyacli cas caslibs add-controls --server cas-shared-default --caslib ${caslib_name} --source-file ${json_file_cas_read} -su
# Expected output:
# The requested access controls in the source file "/home/cloud-user/cas_read_permissions.json" were applied to the caslib "Public".
# Show permissions for the group we just gave Read level permissions to, formatted as text
$sasviyacli --output text cas caslibs list-controls --server cas-shared-default --caslib ${caslib_name} | { head -1 ; grep "${read_group_name} (group)" ;}
To explain this script above, we need to know how permissions work in the SAS CAS Authorization system, which is used only for CAS libraries and tables (and CAS Action Sets, if we're being thorough).
The sas-viya CLI has a cas plug-in, which provides great command-line tools for viewing and changing CAS library and table access controls. After using the loginviyauthinfo.py pyviyatool, which uses the .authinfo file in your home directory to authenticate, the next thing this script does is list the existing access controls on the Public caslib, by running the sas-viya --output text cas caslibs list-controls command with arguments identifying the CAS server and library. It pipes the text-formatted output of this command through a head -1 command to show the header row of the list-controls output, and also through a grep command to filter the rest of the output to only show rows for * (group) which is how Authenticated Users are shown in this output.
The sas-viya (or sas-admin) CLI's cas caslibs subcommand has various options for exporting and importing complete or partial sets of access controls as JSON files. The quickest way to update many access controls at once is by passing in a JSON file, so next we create one, with the 'Read' access level, where all permissions are denied to the chosen group, except for ReadInfo and Select which are granted. This JSON file is called ~/cas_read_permissions.json in the example code above, but you can call it whatever and place it wherever you like - it does not have to go in the current user's home directory (~/). /tmp is another reasonable choice since we use it immediately after creating it and are unlikely to re-use it later without modification.
The example script then runs sas-viya cas caslibs add-controls, to apply the access controls specified in that JSON file to the table, replacing any existing access controls for the same principal (*=Authenticated Users).
Finally, the script lists and formats the access controls for our group (*=Authenticated Users), to show how they are now set.
The end result should be that your Public CAS library has only Read-level permissions for Authenticated Users, as shown in the screenshot earlier in this section.
This seems a reasonable question.
You certainly could just delete the /Public folder and Public caslib, and see what happens: does something in your deployment break because it depends on one of them, or does something re-create them if they are absent (e.g. when a service starts up)? In my experience and limited testing, deleting them caused no issues, but my personal testing definitely did not cover all use cases one could reasonably anticipate! You should not rely on my casual observation for a business-critical deployment.
As 'out of the box' locations, it's possible that some customer-written application or solution they use expects those locations to exist, or may need to use them for a legitimate purpose, for sharing non-sensitive data under the careful eye of a responsible data or content administrator in future. It is also possible that some migration process in future will expect one or both to be present, and fail if they are not.
In any case, I don't think removing the /Public folder and Public caslib completely is really necessary. Making them read-only to Authenticated Users greatly reduces the likelihood they will be used irresponsibly. There is little potential for harm if you put nothing in them, so I would just do that and otherwise leave them be.
See you next time!
Find more articles from SAS Global Enablement and Learning here.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning and boost your career prospects.