Apps Script Library Security - security

I am wondering about the security of apps script libraries. If a user imports a library, is there any way for them to retrieve the code within the library?
I ask because I am writing a library that connects many sheets to a single sheet which acts like a database. Users of the many sheets should not be able to find the database sheet.
I have tested console logging the functions, and they just return [Function] and not the actual function definition. However I still don't know if this is a safe implementation or not. Would love to hear your thoughts.

For other users to use your library, you have to give them access by sharing the script.
Authorized users can view the function code by printing the function or going to the script link
Using print:
Using script link:
https://script.google.com/d/(Script ID Here)/edit
In your post above, you want to hide any data that will lead users to database sheet.
I suggest to create a temporary function in your library script that will set a property containing the Sheet ID. This can be done by using Properties Service. Using this service will allow you to store strings as key-value pairs scoped to one script.
Example:
function setProperty(){
PropertiesService.getScriptProperties().setProperty("Sheet_ID", "123456");
}
Usage:
function myFunction() {
var databaseID = PropertiesService.getScriptProperties().getProperty("Sheet_ID");
SpreadsheetApp.getActiveSpreadsheet().getSheetId(databaseID)
}
Note: Before deploying your library script, run the setProperty() function and delete it in your script editor. This will prevent users from viewing the source code for setProperty() function. Also, make sure that the role of the users you will authorize to access your library is Viewer only to prevent them from editing your script and printing the Property value.
Reference:
Properties Service

Related

Node typescript library environment specific configuration

I am new to node and typescript. I am working on developing a node library that reaches out to another rest API to get and post data. This library is consumed by a/any UI application to send and receive data from the API service. Now my question is, how do I maintain environment specific configuration within the library? Like for ex:
Consumer calls GET /user
user end point on the consumer side calls a method in the library to get data
But if the consumer is calling the user end point in test environment I want the library to hit the following API Url
for test http://api.test.userinformation.company.com/user
for beta http://api.beta.userinformation.company.com/user
As far as I understand the library is just a reference and is running within the consumer application. Library can for sure get the environment from the consumer, but I do not want the consumer having to specify the full URL that needs to be hit, since that would be the responsibility of the library to figure out.
Note: URL is not the only problem, I can solve that with environment switch within the library, I have some client secrets based on environments which I can neither store in the code nor checkin to source control.
Additional Information
(as per jfriend00's request in comments)
My library has a LibExecutionEngine class and one method in it, which is the entry point of the library:
export class LibExecutionEngine implements ExecutionEngine {
constructor(private environment: Environments, private trailLoader:
TrailLoader) {}
async GetUserInfo(
userId: string,
userGroupVersion: string
): Promise<UserInfo> {
return this.userLoader.loadUserInfo(userId, userGroupVersion)
}
}
export interface ExecutionEngine {
GetUserInfo(userId: string, userGroupVersion: string): Promise<UserInfo>
}
The consumer starts to use the library by creating an instance of the LibraryExecution then calling the getuserinfo for example. As you see the constructor for the class accepts an environment. Once I have the environment in the library, I need to somehow load the values for keys API Url, APIClientId and APIClientSecret from within the constructor. I know of two ways to do this:
Option 1
I could do something like this._configLoader.SetConfigVariables(environment) where configLoader.ts is a class that loads the specific configuration values from files({environment}.json), but this would mean I maintain the above mentioned URL variables and the respective clientid, clientsecret to be able to hit the URL in a json file, which I should not be checking in to source control.
Option 2
I could use dotenv npm package, and create one .env file where I define the three keys, and then the values are stored in the deployment configuration which works perfectly for an independently deployable application, but this is a library and doesn't run by itself in any environment.
Option 3
Accept a configuration object from the consumer, which means that the consumer of the library provides the URL, clientId, and clientSecret based on the environment for the library to access, but why should the responsibility of maintaining the necessary variables for library be put on the consumer?
Please suggest on how best to implement this.
So, I think I got some clarity. Lets call my Library L, and consuming app C1 and the API that the library makes a call out to get user info as A. All are internal applications in our org and have a OAuth setup to be able to communicate, our infosec team provides those clientids and secrets to individual applications, so I think my clarity here is: C1 would request their own clientid and clientsecret to hit A's URL, C1 would then pass in the three config values to the library, which the library uses to communicate with A. Same applies for some C2 in the future.
Which would mean that L somehow needs to accept a full configuration object with all required config values from its consumers C1, C2 etc.
Yes, that sounds like the proper approach. The library is just some code doing what it's told. It's the client in this case that had to fetch the clientid and clientsecret from the infosec team and maintain them and keep them safe and the client also has the URL that goes with them. So, the client passes all this into your library, ideally just once per instance and you then keep it in your instance data for the duration of that instance

GET / POST using Clarion

I have Clarion 9 app that I want to be able to communicate with HTTP servers. I come from PHP background. I have 0 idea on what to do.
What I wish to be able to do:
Parse JSON data and convert QUEUE data to JSON [Done]
Have a global variable like 'baseURL' that points to e.g. http://localhost.com [Done]
Call functions such apiConnection.get('/users') would return me the contents of the page. [I'm stuck here]
apiConnection.post('/users', myQueueData) would POST myQueueData contents.
I tried using winhttp.dll by reading it from LibMaker but it didn't read it. Instead, I'm now using wininet.dll which LibMaker successfully created a .lib file for it.
I'm currently using the PROTOTYPE procedures from this code on GitHub https://gist.github.com/ddur/34033ed1392cdce1253c
What I did was include them like:
SimpleApi.clw
PROGRAM
INCLUDE('winInet.equ')
ApiLog QUEUE, PRE(log)
LogTitle STRING(10)
LogMessage STRING(50)
END
MAP
INCLUDE('winInetMap.clw')
END
INCLUDE('equates.clw'),ONCE
INCLUDE('DreamyConnection.inc'),ONCE
ApiConnection DreamyConnection
CODE
IF DreamyConnection.initiateConnection('http://localhost')
ELSE
log:LogTitle = 'Info'
log:LogMessage = 'Failed'
ADD(apiLog)
END
But the buffer that winInet's that uses always returns 0.
I have created a GitHub repository https://github.com/spacemudd/clarion-api with all the code to look at.
I'm really lost in this because I can't find proper documentation of Clarion.
I do not want a paid solution.
It kind of depends which version of Clarion you have.
Starting around v9 they added ClaRunExt which provides this kind of functionality via .NET Interop.
From the help:
Use HTTP or HTTPS to download web pages, or any other type of file. You can also post form data to web servers. Very easy way to send HTTP web requests (and receive responses) to Web Servers, REST Web Services, or standard Web Services, with the most commonly used HTTP verbs; POST, GET, PUT, and DELETE.
Otherwise, search the LibSrc\ directory for "http" and you will get an idea of what is already there. abapi.inc for example, appears to provide a wrapper around wininet.lib.

Feathers JS nested Routing or creating alternate services

The project I'm working on uses the feathers JS framework server side. Many of the services have hooks (or middleware) that make other calls and attach data before sending back to the client. If I have a new feature that needs to query a database but for a only few specific things I'm thinking I don't want to use the already built out "find" method for this database query as that "find" method has many other unneeded hooks and calls to other databases to get data I do not need for this new query on my feature.
My two solutions so far:
I could use the standard "find" query and just write if statements in all hooks that check for a specific string parameter that can be passed in on client side so these hooks are deactivated on this specific call but that seems tedious especially if I find this need for several other different services that have already been built out.
I initialize a second service below my main service so if my main service is:
app.use('/comments', new JHService(options));
right underneath I write:
app.use('/comments/allParticipants', new JHService(options));
And then attach a whole new set of hooks for that service. Basically it's a whole new service with the only relation to the origin in that the first part of it's name is 'comments' Since I'm new to feathers I'm not sure if that is a performant or optimal solution.
Is there a better solution then those options? or is option 1 or option 2 the most correct way to solve my current issue?
You can always wrap the population hooks into a conditional hook:
const hooks = require('feathers-hooks-common');
app.service('myservice').after({
create: hooks.iff(hook => hook.params.populate !== false, populateEntries)
});
Now population will only run if params.populate is not false.

Multiple Auth drivers in kohana3.2

I'm working on a project where I'm trying to implement authentication against external user base for customers, this seems to be working correctly.
Recently there has been added another requirement that some people (not present in the aforementioned base) need to be able to edit parts of pages' content. First thing that comes to mind is to have separate ORM/File Auth driver enabled for those few editors to be able to authenticate them separately.
Is it possible to use two Auth drivers at the same time in Kohana 3.2?
Yes, you can use different drivers at once. Just create another instance instead of standard singleton:
// default Auth
$config = Kohana::$config->load('auth');
$auth = new Auth($config);
$user = $auth->get_user();
// special Auth for administration
$config2 = Kohana::$config->load('admin_auth');
$auth2 = new Auth($config2);
$admin = $auth2->get_user();
Restrictions:
You must use differ configs (driver and session_key values must differ). Note that some settings are defined in classes and cant be changed by config (for example, "remember" cookie named authautologin).
You cant share default ORM models (Model_User, Model_Token, Model_Role), because their names are hardcoded. But ORM driver & File driver can be used.
Kohana's Auth module does not natively support using two Drivers.
However, you can implement a new Driver yourself very easily. You can follow the instructions for creating a new Driver by copying the existing driver and modifying it, here: http://kohanaframework.org/3.3/guide/auth/driver/develop
The simple thing to do would be to put the following logic in your _login method:
Check the external user database for a valid login
If there is a valid user in the external user database, return true.
If there is no valid user in the external user database, check the local user database instead.
If the user exists in the local database, return true.

Launch Documents To Go app from third party Blackberry App

I was wondering if it's possible to open doc, xls, pdf, etc files using the "Documents To Go" app from a third party blackberry app.
If you want to open a specific document, since Docs ToGo registers to handle these extensions, you can use the Registry invocation and it will be handled for you. Take a look at the Registry and Invocation classes, the following code will open the document in the given path, Docs ToGo will take over through the Registry:
Invocation invocation = new Invocation(path);
Ragistry reg = = Registry.getRegistry("<your app namespace.class>");
reg.invoke(invocation);
If there is no registered handler for the file content type a ContentHandlerException will be thrown with error code ContentHandlerException.NO_REGISTERED_HANDLER.
Note: there's a small bug in Docs ToGo - closing the document or clicking the back button might not lead the user back to your application.
EDIT: The getRegistry function takes a class fully qualified name e.g. com.softartisans.SilverDust, where SilverDust is the class mane. You can find more info about the use of the Registry in this online book starting page 291 - Client use of Registry. I originally linked to the javax Registry, but it is more useful to look at the BlackBerry Registry docs.
You can use the ApplicationManager class to launch other applications, for example by looking up its descriptor and using runApplication(). You can also pass arguments in the descriptor and if the application looks at arguments passed into it, it may actually open the specified file.

Resources