As the SAS team providing the operations of the SAS applications that have been installed in the company server, we have a requirement to be able to provide a view of who has what access to each SAS VA report in SAS Viya.
This would allow the "owner" of the VA report to be able to audit the report permissions set within Viya if we then made that available to them through VA. So first, we need to create a data source containing the data (VA report, username, groups , authorisation created on dd/mm/yy....)
Is there a CAS procedure or a SAS program for extracting these information ? I know about the program for extracting these information about datasets (data sources) and I would like to know if it can be done for SAS VA reports too.
To demonstrate what I'm proposing...
Script to pull the report permissions into a file called reportauths-<epoch>.txt (I could probably do more error checking here, it does need curl, jq, and the sas-admin CLI with the authorization plugin to work):
#!/bin/bash # Script that builds a list of reports defined in Viya # and then for each one extracts its applied permissions to a file. # Author: Greg Wootton Date: 22NOV2021 # Check for jq echo "NOTE: Checking if jq is installed." RPMV=$(jq --version) RC=$? if [ $RC != "0" ] then echo >&2 "ERROR: This script requires the jq package." exit 1 fi echo "jq is installed, continuing..." # Check for sas-admin command -v sas-admin >/dev/null 2>&1 rc=$? # If it isn't in PATH, check in the default location for sas-admin # If it isn't there, ask for it's location. if [ $rc -ne 0 ] then if [ -x "/opt/sas/viya/home/bin/sas-admin" ] then admincli="/opt/sas/viya/home/bin/sas-admin" else read -p "Enter path to sas-admin cli: " admincli if [ ! -x "$admincli" ] then echo "ERROR: $admincli is not a path we have permission to execute." exit 1 fi fi else admincli="sas-admin" fi # Gather authentication credentials read -p "Enter sas-admin profile (leave blank to use default): " profile if [ -z "$profile" ] then profile="Default" fi baseurl=$(jq -r --arg profile $profile '.[$profile]."sas-endpoint"' ~/.sas/config.json) if [ -z "$baseurl" ] || ( [ "${baseurl%://*}" != "http" ] && [ "${baseurl%://*}" != "https" ] ) then echo "ERROR: Failed to successfully acquire the URL from profile $profile." exit 1 fi read -p "Enter username: " user read -s -p "Enter password: " pass && echo # Now use sas-admin to log in. $admincli --profile $profile auth login -p $pass -u $user # Get an access token token=$(jq -r --arg profile $profile '.[$profile]."access-token"' ~/.sas/credentials.json) # Make a temporary file to store these objects reports=$(mktemp) # Perform a search curl -s -L "$baseurl/reports/reports?limit=10" --header 'Content-Type: application/json' --header "Authorization: Bearer $token" > $reports # Add all the entries into an array reportids=( $(jq -r '.items[].id' $reports) ) # Check for a next link next=$(jq -r '.links[]|select(.rel == "next")| .href' $reports) # Hit next link and add the report ids to the array and pull the next next link. while [ -n "$next" ] do curl -s -L "$baseurl$next" --header 'Content-Type: application/json' --header "Authorization: Bearer $token" > $reports reportids+=( $(jq -r '.items[].id' $reports) ) next=$(jq -r '.links[]|select(.rel == "next")| .href' $reports) done # We should now have an array of all the report ids. # Then call authorization plugin to get the rules for each report fn=reportauth-$(date +%s) for id in ${reportids[@]} do curl -s -L "$baseurl/reports/reports/$id" --header 'Content-Type: application/json' --header "Authorization: Bearer $token" | jq -r '"Report: " + .name'>> $fn.txt $admincli --profile $profile authorization explain --target-uri "/reports/reports/$id" >> $fn.txt done
SAS Program that reads this into a data set:
filename repperm "/path/to/reportauth-<epoch>.txt";
data auth;
length uri $ 54 name principal $ 255 read update delete secure add remove create $ 12;
infile repperm;
input;
if length(_infile_) > 8 then do;
if substr(_infile_,1,7)="Report:" then do;
name=substr(_infile_,9);
end;
else if substr(_infile_,1,8)="Resource" then do;
uri=substr(_infile_,11);
end;
else if substr(_infile_,1,10)="Principal" then;
else do;
principal=scan(_infile_,1);
if principal="authenticatedUsers" or principal="guest" then do;
read=scan(_infile_,2);
update=scan(_infile_,3);
delete=scan(_infile_,4);
secure=scan(_infile_,5);
add=scan(_infile_,6);
remove=scan(_infile_,7);
create=scan(_infile_,8);
end;
else do;
read=scan(_infile_,3);
update=scan(_infile_,4);
delete=scan(_infile_,5);
secure=scan(_infile_,6);
add=scan(_infile_,7);
remove=scan(_infile_,8);
create=scan(_infile_,9);
end;
output;
end;
end;
retain uri name;
run;
Resulting data set:
Sorry for misunderstanding your question.
The sas-admin CLI's authorization plug-in has a "explain" command that would return the permissions for a given endpoint, and the reports plug-in has a list command. So you could get the reports from sas-admin reports list and then get the permissions for each one from sas-admin authorization explain --target-uri /reports/reports/<id>.
[grwoot@cldlgn02 ~]$ sas-admin --profile viya35 reports list Name Folder Report ID Application Activity /Products/SAS Environment Manager/Dashboard Items ecec39ad-994f-4055-8e40-4360f410bc6e ... More reports are available. [grwoot@cldlgn02 ~]$ sas-admin --profile viya35 authorization explain --target-uri /reports/reports/ecec39ad-994f-4055-8e40-4360f410bc6e Resource: /reports/reports/ecec39ad-994f-4055-8e40-4360f410bc6e Principal Read Update Delete Secure Add Remove Create SASAdministrators (group) conditional conditional conditional conditional conditional conditional conditional authenticatedUsers conditional conditional conditional conditional conditional conditional conditional
To demonstrate what I'm proposing...
Script to pull the report permissions into a file called reportauths-<epoch>.txt (I could probably do more error checking here, it does need curl, jq, and the sas-admin CLI with the authorization plugin to work):
#!/bin/bash # Script that builds a list of reports defined in Viya # and then for each one extracts its applied permissions to a file. # Author: Greg Wootton Date: 22NOV2021 # Check for jq echo "NOTE: Checking if jq is installed." RPMV=$(jq --version) RC=$? if [ $RC != "0" ] then echo >&2 "ERROR: This script requires the jq package." exit 1 fi echo "jq is installed, continuing..." # Check for sas-admin command -v sas-admin >/dev/null 2>&1 rc=$? # If it isn't in PATH, check in the default location for sas-admin # If it isn't there, ask for it's location. if [ $rc -ne 0 ] then if [ -x "/opt/sas/viya/home/bin/sas-admin" ] then admincli="/opt/sas/viya/home/bin/sas-admin" else read -p "Enter path to sas-admin cli: " admincli if [ ! -x "$admincli" ] then echo "ERROR: $admincli is not a path we have permission to execute." exit 1 fi fi else admincli="sas-admin" fi # Gather authentication credentials read -p "Enter sas-admin profile (leave blank to use default): " profile if [ -z "$profile" ] then profile="Default" fi baseurl=$(jq -r --arg profile $profile '.[$profile]."sas-endpoint"' ~/.sas/config.json) if [ -z "$baseurl" ] || ( [ "${baseurl%://*}" != "http" ] && [ "${baseurl%://*}" != "https" ] ) then echo "ERROR: Failed to successfully acquire the URL from profile $profile." exit 1 fi read -p "Enter username: " user read -s -p "Enter password: " pass && echo # Now use sas-admin to log in. $admincli --profile $profile auth login -p $pass -u $user # Get an access token token=$(jq -r --arg profile $profile '.[$profile]."access-token"' ~/.sas/credentials.json) # Make a temporary file to store these objects reports=$(mktemp) # Perform a search curl -s -L "$baseurl/reports/reports?limit=10" --header 'Content-Type: application/json' --header "Authorization: Bearer $token" > $reports # Add all the entries into an array reportids=( $(jq -r '.items[].id' $reports) ) # Check for a next link next=$(jq -r '.links[]|select(.rel == "next")| .href' $reports) # Hit next link and add the report ids to the array and pull the next next link. while [ -n "$next" ] do curl -s -L "$baseurl$next" --header 'Content-Type: application/json' --header "Authorization: Bearer $token" > $reports reportids+=( $(jq -r '.items[].id' $reports) ) next=$(jq -r '.links[]|select(.rel == "next")| .href' $reports) done # We should now have an array of all the report ids. # Then call authorization plugin to get the rules for each report fn=reportauth-$(date +%s) for id in ${reportids[@]} do curl -s -L "$baseurl/reports/reports/$id" --header 'Content-Type: application/json' --header "Authorization: Bearer $token" | jq -r '"Report: " + .name'>> $fn.txt $admincli --profile $profile authorization explain --target-uri "/reports/reports/$id" >> $fn.txt done
SAS Program that reads this into a data set:
filename repperm "/path/to/reportauth-<epoch>.txt";
data auth;
length uri $ 54 name principal $ 255 read update delete secure add remove create $ 12;
infile repperm;
input;
if length(_infile_) > 8 then do;
if substr(_infile_,1,7)="Report:" then do;
name=substr(_infile_,9);
end;
else if substr(_infile_,1,8)="Resource" then do;
uri=substr(_infile_,11);
end;
else if substr(_infile_,1,10)="Principal" then;
else do;
principal=scan(_infile_,1);
if principal="authenticatedUsers" or principal="guest" then do;
read=scan(_infile_,2);
update=scan(_infile_,3);
delete=scan(_infile_,4);
secure=scan(_infile_,5);
add=scan(_infile_,6);
remove=scan(_infile_,7);
create=scan(_infile_,8);
end;
else do;
read=scan(_infile_,3);
update=scan(_infile_,4);
delete=scan(_infile_,5);
secure=scan(_infile_,6);
add=scan(_infile_,7);
remove=scan(_infile_,8);
create=scan(_infile_,9);
end;
output;
end;
end;
retain uri name;
run;
Resulting data set: