BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
sassy7
Obsidian | Level 7

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.

1 ACCEPTED SOLUTION

Accepted Solutions
gwootton
SAS Super FREQ

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:

gwootton_0-1637598417979.png

 

 

--
Greg Wootton | Principal Systems Technical Support Engineer

View solution in original post

7 REPLIES 7
gwootton
SAS Super FREQ
These might be helpful:

How auditing works, where the reports are, etc:

SAS® Viya® 3.5 Administration: Auditing
https://go.documentation.sas.com/doc/en/calcdc/3.5/calaudit/titlepage.htm

How to set up auditing to capture successful reads as well as the failures captured by default:

Usage Note 62355: How to audit SAS® Visual Analytics reports in SAS® Viya®
https://support.sas.com/kb/62/355.html
--
Greg Wootton | Principal Systems Technical Support Engineer
sassy7
Obsidian | Level 7
Hi gwootton,
Unfortunately we are not interested in the activity (Audit) done in SAS VA, but only who has what access to each SAS VA report in SAS Viya.
gwootton
SAS Super FREQ

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

--
Greg Wootton | Principal Systems Technical Support Engineer
sassy7
Obsidian | Level 7
Hi gwootton,
that's interesting 🙂 and it's the kind of information we would need! Do you know if it's possible to get the same data through a CAS procedure (for example like proc cas)?
gwootton
SAS Super FREQ
There are CAS actions to view the permissions on cas libraries and tables, but the permissions assigned to objects are not stored there. You could write SAS code to engage the /authorization/decisions endpoint for each report URI for the "explain" output, but the response is pretty detailed as it returns things like contributing rules and conditions for each permission. That's what the sas-admin CLI is doing under the covers. You could perhaps write a script to pull this information using sas-admin into a file and then parse that file with SAS if you want it in a SAS data set.
--
Greg Wootton | Principal Systems Technical Support Engineer
gwootton
SAS Super FREQ

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:

gwootton_0-1637598417979.png

 

 

--
Greg Wootton | Principal Systems Technical Support Engineer
sassy7
Obsidian | Level 7
Hi Greg,
this is exactly the kind of information regarding usernames that the company is looking for! Thank you for providing me the two scripts 🙂

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

Discussion stats
  • 7 replies
  • 2527 views
  • 3 likes
  • 2 in conversation