Richard
Richard

Reputation: 27508

Programmatically create a new Person having an Internal Login

I am trying to programmatically create Users with Internal Accounts as part of a testing system. The following code can not create an InternalLogin because there is not password hash set at object creation time.

Can a person + internal account be created using metadata_* functions ?

data _null_;
  length uri_Person uri_PW uri_IL $256;
  call missing (of uri:);

  rc = metadata_getnobj ("Person?@Name='testbot02'", 1, uri_Person); msg=sysmsg();
  put 'NOTE: Get Person, ' rc= uri_Person= / msg;
  if rc = -4 then do;
  rc = metadata_newobj ('Person', uri_Person, 'testbot02'); msg=sysmsg();
  put 'NOTE: New Person, ' rc= uri_Person= / msg;
  end;

  rc = metadata_setattr (uri_Person, 'DisplayName', 'Test Bot #2'); msg=sysmsg();
  put 'NOTE: SetAttr, ' rc= / msg;

  rc = metadata_newobj ('InternalLogin', uri_IL, 'autobot - IL', 'Foundation', uri_Person, 'InternalLoginInfo'); msg=sysmsg(); 
  put 'NOTE: New InternalLogin, ' rc= / msg;
run;

Logs

NOTE: Get Person, rc=-4 uri_Person=

NOTE: New Person, rc=0 uri_Person=OMSOBJ:Person\A5OJU4RB.AP0000SX

NOTE: SetAttr, rc=0

NOTE: New InternalLogin, rc=-2
ERROR: AddMetadata of InternalLogin is missing required property PasswordHash.
NOTE: DATA statement used (Total process time):
      real time           0.02 seconds
      cpu time            0.01 seconds

The management console and metabrowse were used to find what objects might need to be created.

enter image description here enter image description here

Metabrowse

enter image description here enter image description here

Upvotes: 1

Views: 511

Answers (1)

Richard
Richard

Reputation: 27508

I ended up using Java to create new users.

A ISecurity_1_1 instance from MakeISecurityConnection() on the metadata connection was used to SetInternalPassword

Java ended up being a lot more clear coding wise.

package sandbox.sas.metadata;

import com.sas.iom.SASIOMDefs.GenericError;
import com.sas.metadata.remote.*;
import com.sas.meta.SASOMI.*;
import java.rmi.RemoteException;
import java.util.List;

/**
 *
 * @author Richard
 */
public class Main {

    public static final String TESTGROUPNAME = "Automated Test Users";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {        
        String metaserver="################";
        String metaport="8561";
        String omrUser="sasadm@saspw";
        String omrPass="##########";

        try 
        {
            MdFactoryImpl metadata = new MdFactoryImpl(false);
            metadata.makeOMRConnection(metaserver,metaport,omrUser,omrPass);

            MdOMIUtil util = metadata.getOMIUtil();
            ISecurity_1_1 security = metadata.getConnection().MakeISecurityConnection();

            MdObjectStore workunit = metadata.createObjectStore();

            String foundationID = util.getFoundationReposID();
            String foundationShortID = foundationID.substring(foundationID.indexOf(".") + 1);

            // Create group for test bot accounts

            List identityGroups = util.getMetadataObjects(foundationID, MetadataObjects.IDENTITYGROUP,  MdOMIUtil.OMI_XMLSELECT,
                    String.format("<XMLSelect search=\"IdentityGroup[@Name='%s']\"/>", TESTGROUPNAME));

            IdentityGroup identityGroup;

            if (identityGroups.isEmpty()) {
                identityGroup = (IdentityGroup) metadata.createComplexMetadataObject (workunit, TESTGROUPNAME, MetadataObjects.IDENTITYGROUP, foundationShortID);
                identityGroup.setDisplayName(TESTGROUPNAME);
                identityGroup.setDesc("Group for Automated Test Users performing concurrent Stored Process execution");
                identityGroup.updateMetadataAll();
            }

            identityGroups = util.getMetadataObjectsSubset(workunit, foundationID, MetadataObjects.IDENTITYGROUP,  MdOMIUtil.OMI_XMLSELECT,
                    String.format("<XMLSelect search=\"IdentityGroup[@Name='%s']\"/>", TESTGROUPNAME));

            identityGroup = (IdentityGroup) identityGroups.get(0);

            // Create (or Update) test bot accounts

            for (int index = 1; index <= 25; index++)
            {
                String token = String.format("%02d", index);

                String personName = String.format("testbot%s", token);
                String password   = String.format("testbot%s%s", token, token);  * simple dynamically generated password for user (for testing scripts only);

                String criteria = String.format("Person[@Name='%s']", personName);
                String xmlSelect = String.format("<XMLSelect search=\"%s\"/>", criteria);

                List persons = util.getMetadataObjectsSubset(workunit, foundationID, MetadataObjects.PERSON, MdOMIUtil.OMI_XMLSELECT | MdOMIUtil.OMI_GET_METADATA | MdOMIUtil.OMI_ALL_SIMPLE, xmlSelect);

                Person person;
                if (persons.size() == 1)
                {
                    person = (Person) persons.get(0);
                    System.out.println(String.format("Have %s %s", person.getName(), person.getDisplayName()));
                }
                else
                {
                    person = (Person) metadata.createComplexMetadataObject (workunit, personName, MetadataObjects.PERSON, foundationShortID);
                    person.setDisplayName(String.format("Test Bot #%s", token));
                    person.setDesc("Internal account for testing purposes");
                    System.out.println(String.format("Make %s, %s (%s)", person.getName(), person.getDisplayName(), person.getDesc()));
                    person.updateMetadataAll();                    
                }

                security.SetInternalPassword(personName, password);

                AssociationList personGroups = person.getIdentityGroups();                
                personGroups.add(identityGroup);
                person.setIdentityGroups(personGroups);
                person.updateMetadataAll();
            }

            workunit.dispose();
            metadata.closeOMRConnection();
            metadata.dispose();
        } 
        catch (GenericError | MdException | RemoteException e) 
        {
            System.out.println(e.getLocalizedMessage());
            System.exit(1);
        }
    }    
}

Upvotes: 1

Related Questions