Examples: DATA Step Functions for Metadata Security Administration

Overview

These examples are self-contained. Specify your own connection options, and submit the code in a SAS session.
To create security reports about authorization, use the macros that SAS provides. The macros extract authorization information into SAS data sets that you can use to create security reports. For more information, see the SAS Intelligence Platform: Security Administration Guide.
CAUTION:
Do not run examples against a production metadata server.
The examples create objects and identities to demonstrate the use of ACTs. Making changes to security settings poses a risk to a production environment. Be sure to run these examples in an experimental, nonproduction environment.
CAUTION:
Do not use this code as an example of creating PhysicalTable and Person objects.
The PhysicalTable and Person objects that are created and deleted in these examples are not usable by SAS products because they do not have the appropriate attributes and associations. For information about attributes and associations, see SAS Metadata Model: Reference. For information about metadata administration tasks, see the SAS Intelligence Platform: System Administration Guide.
Note: A caller must have administrative access to the metadata server in order to create and delete user definitions.

Example: Begin and End Transaction Context

options metaserver="myserver"
        metaport=8561
        metauser="myuser"
        metapass="mypwd"
        metarepository="Foundation";

/* Get macro variable bit flags. */
%mdseccon();

data _null_;
   format tc $20.;
   length uri $256;
   tc = "";
   uri="";

   /* Create a PhysicalTable object. */
   rc=metadata_newobj("PhysicalTable",
                      uri,
                      "My Demo Table for METASEC");

   /* Start transaction on object created above using the URI. */
   rc=METASEC_BEGTRAN(uri,0,tc); 
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   /* ... other operations using the TC ... */

   /* End the transaction and commit any changes made to */
   /* the transaction since it was started.              */
   rc=METASEC_ENDTRAN(uri,tc, &_SECAD_COMMIT_TC ); 
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   /* Delete the PhysicalTable */
   rc=metadata_delobj(uri);

run;

Example: Working with ACTs

options metaserver="myserver"
        metaport=8561
        metauser="myuser"
        metapass="mypwd"
        metarepository="Foundation";

/* Get macro variable bit flags. */
%mdseccon();

/*--------------------------------------*/
/* Create a new user for demo purposes. */
/*--------------------------------------*/

data _null_;
    length uri $256;
    rc=0;
    
    /* Create a new Person object. */
    rc=metadata_newobj("Person",
                       uri,
                       "Demo User for METASEC");
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;
   put "The new user's URI is " uri;
run;


/*-------------------------------------------------------------*/
/* Create a new ACT that denies PUBLIC ReadMetadata and grants */
/* SASUSERS ReadMetadata. Grant WriteMetadata and Readmetadata */
/* to a specific person to show the ACT working.               */
/*-------------------------------------------------------------*/
data _null_;
   format tc $20.;
   length uri $256
          act_uri $256
          repos_uri $256
          type $60
          id $17;

   tc = "";
   uri="";

   /* Start transaction - No URI specified because the ACT does not exist. */
   rc=METASEC_BEGTRAN("",0, tc); 
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   /* build the uri for the foundation repository */
   rc=metadata_resolve("omsobj:RepositoryBase?@Name='Foundation'",type,id);
   tmpstr = substr(id, length(id)-7, 8);
   repos_uri="REPOSID:" || tmpstr;

   /* create the ACT */
   rc=METASEC_NEWACT(tc,repos_uri, "Name", "Grant SASUSERS ACT",
                     "Desc", "ACT that denies PUBLIC but grants SASUSERS.");
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   /* The URI parameter is blank because the ACT has not been written yet.  */
   /* Note the use of &_SECAD_ACT_CONTENTS to indicate that this is setting
*/
   /* the content of the ACT rather than security on the ACT.               */
   rc = METASEC_SETAUTH(tc, "","IdentityGroup", "SASUSERS",
                        "Grant", "ReadMetadata","",&_SECAD_ACT_CONTENTS);
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   rc = METASEC_SETAUTH(tc, "","IdentityGroup", "PUBLIC",
                        "Deny","ReadMetadata","",&_SECAD_ACT_CONTENTS );
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   rc = METASEC_SETAUTH(tc, "","Person", "Demo User for METASEC",
                        "Grant", "WriteMetadata","", &_SECAD_ACT_CONTENTS);
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   rc = METASEC_SETAUTH(tc, "","Person", "Demo User for METASEC",
                        "Grant", "ReadMetadata","", &_SECAD_ACT_CONTENTS);
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   /* Protect the ACT so the public cannot edit the ACT. */
		/* The unrestricted user will be the only one who can */
   /* modify the ACT.                                    */
   rc = METASEC_SETAUTH(tc, "","IdentityGroup", "PUBLIC",
                        "Grant","ReadMetadata","");
   rc = METASEC_SETAUTH(tc, "","IdentityGroup", "PUBLIC",
                        "Deny","WriteMetadata","");
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   /* Commit the transaction and write the ACT. */
   rc=METASEC_ENDTRAN("",tc, &_SECAD_COMMIT_TC ); 
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;
   else
      put "Transaction creating the ACT has been committed.";
run;

/*--------------------------------------------*/
/* Start a new DATA step to exercise the ACT. */
/*--------------------------------------------*/

data _null_;
   format tc $20.;
   length uri $256
          act_uri $256
          identitytype $60
          identityname $60
          act_uri2 $256
          actname $60
          actdesc $60
          auth $ 18
          permission $ 60
          condval $ 100
          authorization $30
          authint 8
          type $60
          id $17
          attrname $60
          attrvalue $256;

   tc="";
   uri="";
   attrname="";
   attrvalue="";

   /* Create a PhysicalTable object. */
   rc=metadata_newobj("PhysicalTable",
                      uri,
                      "Demo Table 2 for METASEC");

   /* Start transaction on the object using the object's URI. */
   rc=METASEC_BEGTRAN(uri,0, tc); 
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   /* In the SAS log, list the object's URI. */
   put "The object's URI is: " uri;

   /* In the SAS log, list the identities (both inherited and explicit) */
   /* that have access controls related to the object in the TC.        */

   put "These identities (both inherited and explicit) have access controls
related to the object:";
   n=1;
   rc =1;
   do while (rc > 0) ;
      identitytype="";
      identityname="";
      rc=metasec_getnid(tc, uri, n, identitytype, identityname);
      if (rc < 0 ) then do;
         sysmsg = sysmsg();
         put sysmsg;
         end;
      else do;
         put n= identitytype= identityname=;
         n=n+1;
         end;
      end;

   /* Get list of ACTs on the object. */

   put "ACT or ACTs on the object:";
   n=1;
   rc =1;
   do while (rc > 0) ;
      act_uri2="";
      actname="";
      actdesc="";
      rc=metasec_getnact(tc, uri, n, act_uri2, actname, actdesc);
      if (rc < 0 ) then do;
         sysmsg = sysmsg();
         put sysmsg;
         end;
      else do;
         put n= act_uri2= actname= actdesc=;
         n=n+1;
         end;
      end;

   /* Get the URI for the ACT that was created above.          */
   /* For best performance, resolve URI into an ID instance to */
   /* exploit object caching. (See the best practices topic.)  */

   id="";
   type="";
   rc=metadata_resolve("omsobj:AccessControlTemplate?@Name='Grant SASUSERS
ACT'",
                       type,id);
   act_uri="omsobj:AccessControlTemplate/" || id;

   /*---------------------------------*/
   /* Apply the ACT to the object.    */
   /*---------------------------------*/
   rc = METASEC_APPLYACT(tc, uri, act_uri);


   /* In the SAS log, list the identities (both inherited and explicit) */
   /* that have access controls related to the object in the TC.        */

   put "After ACT has been applied, these identities have access controls
related to the object:";
   n=1;
   rc =1;
   do while (rc > 0) ;
      identitytype="";
      identityname="";
      rc=metasec_getnid(tc, uri, n, identitytype, identityname);
      if (rc < 0 ) then do;
         sysmsg = sysmsg();
         put sysmsg;
         end;
      else do;
         put n= identitytype= identityname=;
         n=n+1;
         end;
      end;

   /* Get list of ACTs on the object. */

   put "After ACT has been applied, ACT or ACTs on the object:";
   n=1;
   rc =1;
   do while (rc > 0) ;
      act_uri2="";
      actname="";
      actdesc="";
      rc=metasec_getnact(tc, uri, n, act_uri2, actname, actdesc);
      if (rc < 0 ) then do;
         sysmsg = sysmsg();
         put sysmsg;
         end;
      else do;
         put n= act_uri2= actname= actdesc=;
         n=n+1;
         end;
      end;

   /*-------------------------------------------------------------*/
   /* Next in the log, list all the authorizations on the object. */
   /* Authorizations will be returned in a loop.  The Auth output */
   /* parameter is a bit field that returns much information.     */
   /* It contains bit fields indicating if grants and denies are  */
   /* explicit, from an ACT, or indirect (group or inheritance).  */
   /* Use the macro variable defined in %mdseccon() to determine  */
   /* what is in the fields.                                      */
   /* To create security reports about authorization, use the     */
   /* macros that SAS provides. See information above.            */
   /*-------------------------------------------------------------*/

   put "These are authorizations on the object:";
   rc = 0;
   n=1;
   do while (rc = 0) ;
      condval="";
      auth="";
      identityname="";
      identitytype="";
      authorization="";
      permission="";

      rc=metasec_getnauth(tc, uri,n,
                          identitytype,identityname,auth,permission,condval);
      if (rc = 0 )then do;
         n=n+1;
         authint = input(auth, 16.);

         /* The comparisons below must be done in the proper order */
         /* to assure precedence is honored.                       */
         authorization = "Neither Granted nor Denied"; 
         if (band(authint, &_SECAD_PERM_EXPM) ) then do;
            if (band(authint,&_SECAD_PERM_EXPD )) then
               authorization = "Denied Explicitly"; 
            else
               authorization = "Granted Explicitly"; 
            end;
         else if (band(authint, &_SECAD_PERM_ACTM) ) then do;
            if (band(authint,&_SECAD_PERM_ACTD )) then
               authorization = "Denied by ACT"; 
            else
               authorization = "Granted by ACT"; 
            end;
         else if (band(authint, &_SECAD_PERM_NDRM) ) then do;
            if (band(authint,&_SECAD_PERM_NDRD )) then
               authorization = "Denied Indirectly"; 
            else
               authorization = "Granted Indirectly"; 
            end;

         put identityname= permission= authorization=;
         end; /* if rc =0 */
      end; /* while */

   /* Commit the transaction and write the ACT. */
   rc=METASEC_ENDTRAN("",tc, &_SECAD_COMMIT_TC ); 
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;
   else
      put "Transaction has been committed.";
      put ;
   
   /*----------------------------------------------------------------*/
   /* The ACT calls below will be made without a transaction handle. */
   /* Changes will be immediate.                                     */
   /* This code shows how to change the description of an ACT        */
   /*----------------------------------------------------------------*/

   /* Get the Desc attribute */
   attrvalue  = "";
   rc = METASEC_GETACTA("",act_uri,"Desc", attrvalue); 
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;
   else
      put "Existing ACT Description:" attrvalue;


   /* change the ACT description */
   rc = METASEC_SETACTA("",act_uri,"Desc",
                        "ACT that denies PUBLIC and grants SASUSERS"); 
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   /* Get the Desc attribute */
   attrvalue  = "";
   rc = METASEC_GETACTA("",act_uri,"Desc", attrvalue); 
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;
   else
      put "New ACT Description:" attrvalue;

   /* list all the attributes on the ACT */
   put "These are the new attributes on the ACT:";
   
   n=1;
   rc =1;
   do while (rc > 0) ;
      attrname="";
      attrvalue="";
      rc=metasec_getnacta("", act_uri, n, attrname, attrvalue);
      if (rc < 0 ) then do;
         sysmsg = sysmsg();
         put sysmsg;
         end;
      else do;
         put "Attribute #" n "Name=" attrname "Value=" attrvalue;
         n=n+1;
         end;
      end;

run;
If you issue the METABROWSE command to open the Metadata Browser window, you can see the new ACT, "My Demo ACT for METASEC." It is associated with the new table, "My Demo Table 2 for METASEC."
The following code shows how to remove the ACT from the object. The calls in the code are submitted without a transaction context, so the changes are made immediately.
With METASEC_REMACT, you must specify the ID instance form of URI for the ACT. Use the METADATA_RESOLVE function to find the ID. You can specify the search form for the object from which you remove the ACT.
data _null_;
   length type $60 
          id $17;
   type='';
   id='';
   rc=metadata_resolve("omsobj:AccessControlTemplate?@Name='Grant SASUSERS
ACT'",
                       type,id);
   rc2 = METASEC_REMACT("",
                       "omsobj:PhysicalTable?@Name='Demo Table 2 for METASEC'", 
                       "omsobj:AccessControlTemplate/"||id,
                       "0");
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;
run;
If you look at the Metadata Browser window again, you can see that the ACT has been removed from the table.
The following code deletes the table, the ACT, and the person by name, with the search form of URI. The calls in the code are submitted without a transaction context, so the changes are made immediately. Because the PUBLIC user group was denied access to the ACT earlier, only the unrestricted user can perform this task. Administrative access is required to add and delete users.
options metaserver="myserver"
metaport=8561
metauser="sasadm@saspw"
metapass="adminpwd"
metarepository="Foundation";

data _null_;
   rc=metadata_delobj("omsobj:PhysicalTable?@Name='Demo Table 2 for METASEC'"); 

   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   rc=metadata_delobj("omsobj:AccessControlTemplate?@Name='Grant SASUSERS
ACT'");  
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;

   rc=metadata_delobj("omsobj:Person?@Name='Demo User for METASEC'");  
   if (rc < 0 ) then do;
      sysmsg = sysmsg();
      put sysmsg;
      end;
run;