/*! \Copyright: Sertainty Corporation, 2020. All Rights Reserved. \File: sample_workflow_delegate.uxl \Brief: Demonstrates UXP authentication via Delegate Service. using UXL scripting. This sample exercises various Delegate Service operations using UXP SDK. 1. Users, IDs, and Delegates are added to the Delegate Service database. 2. Users subscribe to the User Delegate ID. 3. UXP is created with the Delegate ID. 4. Upon access to a UXP by a User Subscriber of the Delegate ID, subscription metadata, like max access and access count, is observed. \Details: A UXP Identity database is a UXP Object that permits SQL access. The database is used to manage named user and Delegate definitions. A Delegate ID can be used to allow access to a UXP Object without having the named user's Identity embedded within the UXP Object. Access is still controlled by the data owner, but access is managed via the Delegate Sevice Database. This is Delegate ID containing named user and Delegate definitions needs to be exported as a *.iic file and stored in a location where the Delegate Service can access it. For an expanded explanation for Delegate Service, go to the Data Services Guide. \Author: Greg Smith 02/04/2020 \Edited: Melani Smith Weed 07/27/2020 */ replace procedure delegate_sample() { string libname; list inlist, outlist, outlist2; ValuePair pair; int i, j; on return { if (db) ds::closeDatabase(db); } bytearray b1, idbuf, id, id2; int status, done, db, session; struct delegate_s { string description; date expiration; int permit_offline; int offline_duration; int access_max; string checksum; bytearray uxpid; } delegate; struct subscription_s { date expiration; int permit_offline; int offline_duration; int access_max; int access_count; } subscription; struct user_s { string formalname; string description; string email; int privileges; string app_data1; string app_data2; } user; struct userid_s { int flags; string description; bytearray uxpid; bytearray source; } userid; printf("\nSample UXL script for UXP delegate Management\n\n"); string user1 = "SampleUser@myemail.com"; string user2 = "SampleUser2@myemail.com"; string delegate1 = "DelegateExample"; /************************************************************/ /* Create a new ID from the sampleid.xml ID definition. */ /* The sample ID is used to create the Delegate Service database. */ /************************************************************/ printf("Creating sample ID\n"); idbuf = file::readAll("sampleid.xml"); id = id::newIdFromDocument(idbuf); file::writeAll("sampleid.iic", id, "replace"); /************************************************************/ /* Load UXP Delegate code and create a db with SYSADMI */ /************************************************************/ printf("Creating Delegate database\n"); if (x::debug()) { switch (osPlatform()) { case "MACOSX": libname = "libSertaintyDataServicesd"; break; case "ORACLE": case "UBUNTU": libname = "libSertaintyDataServicesd"; break; case "WINDOWS": libname = "SertaintyDataServicesd"; break; } } else { switch (osPlatform()) { case "MACOSX": libname = "libSertaintyDataServices"; break; case "ORACLE": case "UBUNTU": libname = "libSertaintyDataServices"; break; case "WINDOWS": libname = "SertaintyDataServices"; break; } } x::loadPackage("*", libname); ds::initDatabase("dataservices.db",id, user1); db = ds::openDatabase("dataservices.db"); /************************************************************/ /* Open new database. Authentication will happen at */ /* command line. */ /************************************************************/ printf("Opening session and authenticating\n"); printf("\nCredentials necessary to open session:\n"); printf(" Username = %1\n", user1); printf(" Challenge 1 = Response 1\n"); printf(" Challenge 2 = Response 2\n"); printf(" ... \n"); printf(" Challenge 10 = Response 10\n\n"); session = ds::openSession(db, user1); status = ds::authenticate(db,session); if (status != 16) return; ds::setServer(db, session, "file:///local"); /************************************************************/ /* Store the source of the Delegate ID. */ /************************************************************/ idbuf = file::readAll("sampleid.xml"); ds::getUserId(db, session, user1, "SessionID", &userid.flags, &userid.description, &userid.uxpid, &userid.source); userid.description = "My session ID"; ds::updateUserId(db, session, user1, "SessionID", &userid.flags, &userid.description, &userid.uxpid, &idbuf); /************************************************************/ /* Print out user info. */ /************************************************************/ ds::getUser(db,session, user1, &user.formalname, &user.description, &user.email, &user.privileges, &user.app_data1, &user.app_data2); printf("\nUser: %1\n", user1); printf("-----------------------------\n"); printf("Formal Name: %1\n", user.formalname); printf("Description: %1\n", user.description); printf("Email: %1\n", user.email); printf("Privileges: %1\n", user.privileges); ds::getUserId(db, session, user1, "SessionID", &userid.flags, &userid.description, &userid.uxpid, &userid.source); printf("\nUser: %1 ID: SessionID\n", user1); printf("--------------------------------------------\n"); printf("Description: %1\n", userid.description); printf("Flags: %1\n", userid.flags); printf("Uxpid: *****\n"); printf("Source: *****\n"); /************************************************************/ /* Create 2nd user from sample ID. */ /************************************************************/ idbuf = file::readAll("sampleid2.xml"); id2 = id::newIdFromDocument(idbuf); ds::newUser(db, session, user2, "Joe Sample", "This is a test user", user2, 0, "Sample App Data","More App Data"); ds::newUserId(db, session, user2, "MyID", 6, "My ID", id2, ""); ds::getUsers(db, session, &outlist); printf("\nUsers\n"); printf("-----\n"); for (i = 0; i < countList(outlist); i++) { printf("%1\n", getList(outlist, i)); } ds::getUser(db,session, user2, &user.formalname, &user.description, &user.email, &user.privileges, &user.app_data1, &user.app_data2); printf("\nUser: %1\n", user2); printf("-----------------------------\n"); printf("Formal Name: %1\n", user.formalname); printf("Description: %1\n", user.description); printf("Email: %1\n", user.email); printf("Privileges: %1\n", user.privileges); printf("AppData1: %1\n", user.app_data1); printf("AppData2: %1\n", user.app_data2); /************************************************************/ /* Create a Delegate ID and select info. */ /************************************************************/ ds::newDelegate(db,session, user1, delegate1, "Company access", "", 0, 0, 0); ds::getDelegate(db,session, user1, delegate1, &delegate.description, &delegate.expiration, &delegate.permit_offline, &delegate.offline_duration, &delegate.access_max, &delegate.checksum, &delegate.uxpid); file::writeAll("delegate.iic", delegate.uxpid, "replace"); printf("\nDelegate: %1\n", delegate1); printf("-------------------------\n"); printf("Description: %1\n", delegate.description); printf("Expiration: %1\n", delegate.description); printf("Permit Offline: %1\n", delegate.description); printf("Offline Duration: %1\n", delegate.offline_duration); printf("Access Max: %1\n", delegate.access_max); printf("Checksum: %1\n", delegate.checksum); printf("Uxpid: ****\n"); /************************************************************/ /* Add the delegate user to the sample ID. UXP Objects */ /* created with the ID will contain the new delegate user. */ /************************************************************/ idbuf = file::readAll("sampleid.xml"); b1 = id::getUsers(delegate.uxpid); idbuf = id::addUsers(idbuf, b1); id = id::newIdFromDocument(idbuf); file::writeAll("sampleid.iic", id, "replace"); /************************************************************/ /* Manage subscriptions. */ /************************************************************/ ds::subscribe(db, session, user1, delegate1, user2, "", 1, 1, 10, 0); ds::getSubscribers(db, session, user1, delegate1, &outlist); printf("\nSubscribers\n"); printf("-----------\n"); for (i = 0; i < countList(outlist); i++) { ds::getSubscription(db, session, user1, delegate1, getList(outlist,i), &subscription.expiration, &subscription.permit_offline, &subscription.offline_duration, &subscription.access_max, &subscription.access_count); printf("Delegate: %1\n", delegate1); printf("Subscriber: %1\n", getList(outlist,i)); printf("Expiration: %1\n", subscription.expiration); printf("Permit Offline: %1\n", subscription.permit_offline); printf("Offline Duration: %1\n", subscription.offline_duration); printf("Access Max: %1\n", subscription.access_max); printf("Access Count: %1\n", subscription.access_count); } ds::getSubscriptions(db, session, user2, &outlist); printf("\nSubscriptions\n"); printf("-------------\n"); for (i = 0; i < countList(outlist); i++) { pair = getList(outlist,i); printf("%1: %2\n", pair.name, pair.value); } printf("\n"); /* Create a new UXP document with the delegate ID. */ printf("\nCreating new UXP containing delegate: sample_delegate.uxp\n"); printf("Protecting document data.pdf\n"); int data; /* The Delegate ID is usedto protect data in this sample. Though easy to do, this isn't recommended because there is only limited or default policy control. It is recommended to create a new ID that includes a named user as well as the Delegate User from the Delegate ID. * From there, set the policies for the new ID that includes both the named user and the Delegate User and publish ID definition to an *.iic file. */ data = sf::newUxp("sample_delegate.uxp", "sampleid.iic", "IdFile|Replace"); sf::addFile(data, "data.pdf", "data.pdf"); sf::closeUxp(data); printf("Closing new UXP\n"); printf("Opening new UXP\n\n"); printf("\nCredentials necessary to open UXP:\n"); printf(" Username = SampleUser2@myemail.com\n"); printf(" Challenge 1 = MyResponse 1\n"); printf(" Challenge 2 = MyResponse 2\n"); printf(" ... \n"); printf(" Challenge 10 = MyResponse 10\n\n"); data = sf::openUxp("sample.uxp", "ShareAll"); if (data == 0) { printf("\nNot authorized: %1\n", errorstring); return 0; } /* Read the virtual file and write it back out to disk. */ printf("\nYou're authorized via Delegate Services\n"); printf("\nExtracting data.pdf to copy2.pdf\n"); sf::exportFile(data, "data.pdf", "copy.pdf", "Replace"); ds::getSubscribers(db, session, user1, delegate1, &outlist); printf("\nSubscribers After Remote Authentication\n"); printf("---------------------------------------\n"); for (i = 0; i < countList(outlist); i++) { ds::getSubscription(db, session, user1, delegate1, getList(outlist,i), &subscription.expiration, &subscription.permit_offline, &subscription.offline_duration, &subscription.access_max, &subscription.access_count); printf("Delegate: %1\n", delegate1); printf("Subscriber: %1\n", getList(outlist,i)); printf("Expiration: %1\n", subscription.expiration); printf("Permit Offline: %1\n", subscription.permit_offline); printf("Offline Duration: %1\n", subscription.offline_duration); printf("Access Max: %1\n", subscription.access_max); printf("Access Count: %1\n", subscription.access_count); } printf("\nSample finished running\n"); } delegate_sample();