Hi guys. I am finding troubles to understand how should I organize my users and UserGlobals for my app.
I want to have a user like DataCurator, let's say 'MyAppAdmin' that is allowed to create classes, update code, connect to GemTools, and other stuff. Then, I want a normal user (without any privilege) say 'MyAppWebUser' and the seaside gems of my app will be run with such a user. So....how can I define these 2 users? I guess I can create a user and assign the DataCuratorGroup or policy. Is there anything specially recommended for this? (how to create a typical "admin" user)
Anyway... still..each of these users will have their own UserGlobals. If I load the code with 'MyAppAdmin' then it will be in the UserGlobals of that user and not available to 'MyAppWebUser'. What do I need to do? Put everything under Published list instead of UserGlobals? So basically, I am asking how can I have an admin user and a none-admin both sharing the same UserGlobals (or similar).
Thanks in advance, Mariano http://marianopeck.wordpress.com _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
If you are going to share code between users, then I would suggest that you start by installing the GLASS/seaside code into a SymbolList that is not UserGlobals and perhaps even use a Gemstone user that is not DataCurator. The attached script creates a 'glass' user with the same permissions as DataCurator and loads the GLASS code (starting with a $GEMSTONE/bin/extent0.dbf) into a GLASS SymbolDictionary. Once you've done this, you can arrange to install the glass users's #GLASS SymbolDictionary into another users SymbolList and thus share the code ... The `web` user will have to have write permission on all of the slots of the Seaside code, so it might make sense to load the seaside code into the `web` users space directory ... I have to get ready for work right now, so the additional instructions will have to wait:) In the meantime, though I would like to better understand the rationale for separate GemStone users ... things will be much simpler if you done have separate users, so I would think that you'd need a good reason for the extra hassle:) A diagram of the shared and isolated data would help me understand how the code/users/data should be structured ... Dale From: "Mariano Martinez Peck" <[hidden email]> _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass installGLASS.tpz (1K) Download Attachment |
In reply to this post by Mariano Martinez Peck
On Mon, Jan 6, 2014 at 2:08 PM, Mariano Martinez Peck <[hidden email]> wrote:
Mariano http://marianopeck.wordpress.com _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
Administrator
|
Hi Mariano, If you haven't already read chapter 6 of the Sys Admin guide, you should definitely start there. In particular, pay attention to the "Published" and "Publisher" information. That may be a good example/template for what you are trying to do. One idea that might work, is to define a Symbol Dictionary for each version of your application. For example, MyAppV11Globals versus MyAppV12Globals versus MyAppV21Globals, etc. For each application user, insert the appropriate version Symbol Dictionary into his (or her) Symbol List. You probably want some scripts to help facilitate this, since you may have more than one user. Unfortunate, I don't see anything that facilitates managing the Symbol List from a group perspective. Does that help? Thanks, Richard |
Administrator
|
And in case the implication wasn't clear, you can also define CustomerXGlobals versus CustomerYGlobals to allow segregation of quasi-globally accessible collections with the same, common names. For example, if your app has Customers and Invoices, etc., each of these customer-specific Symbol Dictionaries can define various collections with these names. You will need to use dynamic binding to access them, otherwise you get whatever was visible when the code was compiled. e.g., use #resolveSymbol: to find the collection roots (or collections root, depending whether you have a single root dictionary or discrete collections in the Symbol Dictionary). |
In reply to this post by Mariano Martinez Peck
From: "Mariano Martinez Peck" <[hidden email]>If you are allowing users at some level to write arbitrary Smalltalk, then the security afforded by GemStone users is the ticket:) If you are going to share code that you didn't write, you _can_ change the references to class variables, etc. to message sends where you arrange to do some user-specific shenanigans, like referencing UserGlobals (which is automatically switched on a per user basis) ... If you don't want to go around and modify everything in Seaside, there is a facility in 3.x where you can arrange for class variable references to be compiled using a message send and a custom association class. Normally, class var associations are compiled using a known kernel class and the value slot is directly accessed without a message send ... By setting a couple of flags and using a custom Association class, the compiler will use your association class and the compiled reference will use a message send. This means that in your custom Association the value message can be used to do a lookup in UserGlobals and get per gemstone user class variable associations ... I did this with Pier a couple of years ago and while it didn't address every shared data issue, it did address the vast majority of issues .... I've still got the code lying around if you want to play with it.... Dale _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
In reply to this post by Dale Henrichs-3
On Mon, Jan 6, 2014 at 1:34 PM, Dale K. Henrichs <[hidden email]> wrote:
OK...
Dale, I have just tried that and indeed it was quite helpful. At least, I was able to create a user with DataCurator like privileges, load my code there, and run my app. So I could have "two instances of my app running with 2 different gemstone users". So it was quite a good step.
A few notes: 1) could this script be committed somewhere to the public? Maybe to the same place were you were grouping scripts like the purge logs from Norbert? 2) I had to execute: "export upgradeDir=$GEMSTONE/upgrade" before running the script..otherwise, #upgradeDir doesn't exist.
3) After finishing the load, I noticed that I have 2 entries called 'GLASS' in my SymbolList. In addition, the SystemDictionary created for #'GLASS' was actually a SymbolDictionary whose key was #'GLASS' and the value was a reference to itself (the SymbolDictionary). So class in there..... In fact, classes were loaded into the third dictionary, which is....UserGlobals. I guess something is wrong here since I expect all glass classes to be in #'GLASS' SymbolDictionary, right?
Well, the reason so far is security. Mostly because users are able to define they own rules. I answered this later on in another entry of this thread. Thanks for the help
Mariano http://marianopeck.wordpress.com _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
In reply to this post by Dale Henrichs-3
On Mon, Jan 6, 2014 at 1:34 PM, Dale K. Henrichs <[hidden email]> wrote:
Hi Dale. This sentence "so it might make sense to load the seaside code into the `web` users space directory" confuses me.
So..say I have just created the user 'glass' with the provided script. I have loaded all GLASS and all my code in a SystemDictionary called 'GLASS'. Cool, so far so good. So now I need to add this SystemDictionary into the 'web' user. That seems fine as well. I guess a simple #at:put:. I do understand I need to give write access to 'GLASS' to the web user. But I don't get why it would make sense to load seaside code into 'web' uses space. You mean to load all 'GLASS' and all my code directly into the web user instead than in 'glass' symbolList? Of course, to do this I need to do it with the admin user ('glass' in this example) because otherwise my web user doesn't have permission to load code. if that is what you mean, then:
1) how can I load code into UserGlobals of user 'web' while I am connected to topaz with 'glass' user ? 2) If I load glass and my code into the web user UserGlobal. Would the DataCurator have access to it? I guess yes because that user is the one that load it at the first time ;)
Thanks in advance!!
Mariano http://marianopeck.wordpress.com _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
In reply to this post by Mariano Martinez Peck
From: "Mariano Martinez Peck" <[hidden email]>I've submmitted an Issue[1] as a reminder to clean up script and publish... [1] https://github.com/glassdb/glass/issues/16 I'll have to take a closer look at the results of the script ... SymbolDictionaries will have a self-referencing association with the name of the symbollist ... by design ... Not sure about the the two entries in the Symbol list with GLAS, tho... I did cobble together this script form some other scripts that I use (without testing) so I will have to look a little bit closer at the source scripts and this one ... Appreciate the feedback .. Yes I saw that ... and it makes sense to use the GemStone users to secure your data from the prying eyes of other users... Dale _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
In reply to this post by Mariano Martinez Peck
From: "Mariano Martinez Peck" <[hidden email]>I mentioned this because the Seaside code has a fair amount of state in things like class variables that would make trying to share those globals a bit difficult ... these shared globals exist in GLASS as well, but there just aren't quite as many - the bulk of the shared variables in the base GLASS classes are used mainly by the development tools: GemTools or tODE, so don't impact deployed apps as much ... Much of the Seaside state just can't be shared ... The write access is needed for Class Variables etc. If code is expecting to stash some state in class variables, then you either share this state between two users or you have to arrange for each user to have their own slots in the Shared Code ... So if you don't use the trick of "per user class var associations" you either load the code on a per user basis or edit the code so that class variables, etc. are no longer used ... My recommendation is that you use the "per user class var associations, otherwise known as dynamic literal vars" and share the code. However if it turns out that you do need to load code on a per 'web' user basis, you would use the trick of having the 'glass' user load the code into per `web` user SymbolDictionaries ... each web user would get their own symbol dictionary .... While doing the load, you'd have to monkey with the UserSecurityData so that only the target `web` user has read/write access (in the end SystemUser _might_ have to do the load) ... If you were writing code from scratch and knew that you were going to partition the access permissions for data, you would avoid the direct reference to class variables in your application code and it would be simple to share code across multiple users .. The problem here is that Seaside is not written to be "multi-user" and leverages the heck out of "single-user" data structures like class vars, etc ... The "dynamic lieraral vars" trick was invented to allow a GLASS user to leverage the shared code of open source packages while keeping the data completely private ... Some user will have to have superior permissions ... and this user will be the one responssible for system maintaince etc. ... Dale _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
In reply to this post by Mariano Martinez Peck
From: "Mariano Martinez Peck" <[hidden email]>I talked this over with Allen and there is no clean way separate the GsObjectSecurityPolicy for the code and the class vars, etc. So the easiest path will probably be the dynamic literal variable path ... you can still install the whole stack on a per user basis (as DataCurator), but use the dynamic literal vars to isolate the code and data ... This also brings up the question of how are you going to give users the ability to customize their access to data. If you are planning to compile code then they will need code modification privileges ... I'll try to run an experimental run with the dynamic literals installing GLASS and Seaside and then give you a script when I get that working ...
_______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
On Tue, Jan 7, 2014 at 4:15 PM, Dale K. Henrichs <[hidden email]> wrote:
Sorry Dale, but I am afraid I am lost here. If I were able to install the whole stack on a per user basis (as DataCurator), why would I need the dynamic literal vars to isolate the code and the data??? If I have same (but not #==) class (which has a classVar) in 2 different SymbolDictionary from 2 different users, wouldn't each class var point to the slot of of that class? So why would be a problem having same class in other SymbolDictionary of another user? or in other words, why would I need the dynamic literal vars stuff? Wouldn't it be like 2 isolated SmalltalkDictionaries running?
Well.... the data associated to a site will be placed in UserGlobals. But it should be only readable/writable by that 'web' user and (if it exists) the 'glass'/admin one. I still need to investigate how to do this. As a first step, I can start by having same user 'glass' for both things, for the web and for the admin. This is not ideal, but at least as a first step.
I thought about the same, but I have just tried and I don;t need CodeModification privilege. What I do is to send #evaluate to a String and that seems to work without such a privilege.
Thanks Dale. I am still trying to understand where is the problem of having the stack on a per user basis ;)
Mariano http://marianopeck.wordpress.com _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
On Tue, Jan 7, 2014 at 11:48 AM, Mariano Martinez Peck <[hidden email]> wrote:
I'm sorry as well ... I'm afraid that I don't have a clear picture of what you want to do ... I am under the impression that you don't want your web user to be a clone of DataCurator, If so, then who do you think will be doing the install and peridic updates of the code?
If you expect DataCurator to install the code then you _must_ use dynamic literal variables to make it _possible_ for you user to store data into the the class variables ... OR ... you must find all class var reference in the installed code base and change the reference to UserGlobals ... the thing about dynamic literal variables is that it does this mapping "automatically" so by definition it is easier to use dynamic literal variables than it is to edit code ...
If you don't expect DataCurator to the install and instead you give your user all of the same privileges as DataCurator with a different name, then everything is cool...
The permissions of the association for the class variables is established at code install time by the user doing the install ... DataCurator can install the same code into two different SymbolDictionaries, but since DataCurator did the install, the privileges for the code and Associations are governed by the privileges in effect at the time of the install ... by default everything will be owned by DataCurator ...
Moving a SymbolDictionary into another users SymbolList does not change the privileges on the class var associations. So the user will not be able to write to the associations ... they will be able to execute the code ... so if you write code that does not use class variables or class instance variables then you are in good shape ...
As I've said before Seaside is not written this way. With dynamic literal variables it is possible arrange to make the class variable storage use the current users UserGlobals (or any other object that the user has write privileges for) and it is not necessary to modify the code ...
If it works it works (I didn't try it myself:) ... but this does explain why you are going through all of this trouble in the first place:)
If you are going to have completely separate stacks for each user, then it might make sense to go all of the way and have a separate stone for each user ...
When you do a gemstone upgrade you are going to need to be able to reinstall all of the source code of the application and if you have a separate stack per user you are going to have to be able to reinstall and updateand validate each user independently during the upgrade process ... with separate stones you will be able to tackle each user/stone independently ...
At this point with separate stacks per user, what is the advantage of using a single stone? Dale _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
On Tue, Jan 7, 2014 at 9:03 PM, Dale Henrichs <[hidden email]> wrote:
I think we are quite in sync in fact, just a little misunderstanding from my part.
Well...ideally ideally ideally, I wanted to have Seaside/Glass installed many time, once per site. For each site I wanted to have 2 users, one running the seaside gems with no privilege and one user with the code modification privilege to make the load of the code, updates, etc. So Site1 will have 'webUser1' and 'adminUser2'. Site2 would have 'webUser2' and 'adminUser2'. Each 'webUserX' would be a normal user and each 'adminUserX' would have the CodeModification privilege (or maybe the same as DataCurator).
But this implied 2 main problems: 1) How do I load the code with a 'adminUserX' and share it ONLY with the associated 'webUserX'. 2) The code loaded from the previous step should only be read/written by those exact 2 users.
This was cool because I could run Seaside gems with some security out of the box. But.... as a first step, I can manage to have only one user per site, say 'adminUserX' and I use it for everything: load code, update code, run seaside gems.
Yes I do. Not necessary DataCurator but a user with CodeModification privilege.
OK. And this happens even if I don't user DataCurator but rather my own 'adminUserX' right? I mean, I would have the same problem if I want to use 'adminUserX' and 'webUserX', wouldn't I?
Yes, this was the misunderstanding. I was thinking about this.....having one 'adminUserX' per site (no 'webUserX') for all things will work without problem.
OK, I got it. But there is no way to change such privileges? I mean, if I move the SymbolDictinary into another user SymbolList, cannot I change the permissions so that the user can indeed write?
OK, I guess this is what I would need if I want to make it work with my 'adminUserX' and 'webUserX' right? Is there a place I can read about these dynamic literal variables so that I can know what should I do to make it work?
Indeed because if I would need CodeModification to evaluate a string I could have used the same user for all.
Indeed. That was the second step. I thought about this: first step, multiple sites in the sense of separate GemStone users. Second step, not only first step, but also multiple stones. But for second step I need to dig more about how to create stones. So far I was happy with the seaside one I get out of the box with the installGemstone.sh ;)
That's a good point.
Excellent question that I have been asking myself for a while. The thing is that what I call a site may have only a few users (it could be from 1 to a few or much more). It is like deploying the app for one particular client. Maybe the client has 3 users, maybe 1, maybe 10, or maybe more. So I thought that having one stone per site could be overkill. Is this the case? Having multiple users in same stone allows me to group clients with a small numbers of users. Does it make sense or your recommend to directly go with a stone per site?
The problem with multiple sites within same stone is that I share the same SPC. Having one stone per site solves this problem. But again, for small clients this might not be a problem.
I am not sure yet if I would need to share data between clients. But in this case, having multiple users within the same stone makes sharing data easier, since I can use Published or something like that. If they are at different stones, I need to serialize and manage the sharing myself. Anyway, I would need this for the "second step" if case of needing sharing data between sites...
Mariano http://marianopeck.wordpress.com _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
In reply to this post by Mariano Martinez Peck
Mariano,
I’ve been following this conversation with interest and have a couple questions. First, I understand that you plan to run multiple sites. Do you expect to share code among the various sites? The two extremes are fairly simple: (a) all sites use the same code; and (b) there is no overlap in code use between the sites. In either of the extremes (or combinations of the extremes) it is easy to have the sites in the same database. If you want to be able to run one site with one version of some code and another site with another version of the same code then things start getting complicated. In that case multiple users or multiple databases is probably indicated. Second, do you expect to allow your end-users to edit or create source code on the server or execute Smalltalk expressions that they write? The reason I ask is because you describe an interest in having an “admin” user and a “web” user. The UserProfile in GemStone/S dates from the Client/Server era when it was typical to have many users connect to the database using Smalltalk clients (VA/VW) where each user has an ID and password. Once they were connected they could do any operation for which their user had privileges. In the web-based thin-client era your users do not (typically) get a login user ID and password to the database (though they might get something equivalent to your application). All they can do is pass HTTP requests to a FastCGI adaptor (for example), and applications typically enforce their own security as part of the application code (instead of taking advantage of database features that enforce security when the various login users do not trust each other). If the only code that will run on the server is code that you write, then there is less need for the added complexity of separate users with different privileges. If the driving force for having multiple users for the multiple sites is to separate application data, then I would also be inclined to consider an alternative that does not require multiple users. When code uses class (instance) variables to store application data, then the design tends to limit each class to supporting only one instance of the application. My preference is to have an Application class, where the instance(s) of the class hold the root objects of the application (typically a few collections). Then by selecting the desired Application instance early in the web request/response cycle, the rest of the code just interacts with the Application. There are various ways that can happen, but it is typically easier than multiple users. I recognize that I’m guessing what problems you are trying to solve rather than answering your questions about how to use multiple users and enforce various types of security and privileges. So view this as more of my curiosity about what needs people have than as advice on how you should do things. Thanks, James On Jan 6, 2014, at 8:04 AM, Mariano Martinez Peck <[hidden email]> wrote:
_______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
On Wed, Jan 8, 2014 at 11:17 AM, James Foster <[hidden email]> wrote:
Hi James,
My scenario is closer to a). In fact, for the moment the code that each site runs is exactly the same. The difference is in the database they use, and some setup that unfortunately is defined at class variables level... In the future, I might want to load certain package only to certain sites. Or maybe update one site to a kind of premium version with more packages or something like that. That's why I don't want to try to focus too much in the scenario in which I share the code for all sites. I prefer to have the code loaded for each site even if for the moment it is the same. Because this allows me to change/expand to further needs in the future, as I comment above. And moreover, I solve the problem of class variables.
OK good. Yes, that's the approach I was concluding: multi-user as a first step, and multi-stones as a second step. But Dale asked if that made sense...maybe I should jump direcly into a stone per site basis (second step).
Yes to the latter...basically, the user can kind of define its own rules which is interpreted as Smalltalk code which is then evaluated. At the end, it is string which when evaluated it is a block closure, and then we do the #value. For that I am using String>>evaluate and #value. But this seems to work even without DataModification privilege!
Totally agree. Yes, the "gemstone user" in my case is for the whole site. Real application users are managed by my own. I consider a GemStone user like it would be a relational db user. All this complexity I was thinking about ("admin" vs "web" user) was because right now I am not doing any validation in what the users can write as Smalltalk code. So I thought that directly making the seaside gem run under a user with no privilege would give me an security out of the box. But I have realized now (with all your help), that having these 2 types of users brings complexity. So maybe it is easier to use same user for everything (one with CodeModification privilege) and then write my own validations so that the user cannot type any arbitrary smalltalk expression. Or make a DSL or any kind of language that is then compiled to Smalltalk or something....like a rule engine.
Good question. Yes, this was another of the reasons.
Yes, I thought about this as well. This would solve the isolation of data, but I would still have the problem of class variables. I do use class variables that should apply only to "one instance of the app running". So to use this approach I would need to solve all these class variables. Which in fact, it makes sense. I would like to reify an "Application" object and move there all state specific for one app running. But I would like to let that for later.... (I need a working version asap ;) )
Also, I know that from my app, the user will only have access to the correct application. But technically, from GemStone permission point of view, the user the gems are running *could* have access to the data of other site. So yes, we come back again to the fact that I should validate the expressions type by users etc. In my case, the data is very critical since it is financial stuff. So I feel kind of a bit more safe if each site would be completely isolated from each other in terms of Gemstone itself (be it a different user or a different stone).
Does it make sense?
Thanks James, your response is very appreciated. Sometimes this kind of answer is even better than answering what I asked ;)
Mariano http://marianopeck.wordpress.com _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
Hi Mariano,
It does sound like you are on a reasonable path (and asking the right questions and getting the right answers). I recognize that refactoring code to eliminate the use of class variables is not trivial. Also, the desire to avoid commingling financial data is a strong argument for separate users or databases. My remaining concern is with letting users enter arbitrary Smalltalk code. It seems that using something like Petit Parser (http://seaside.gemtalksystems.com/ss/PortablePetitParser.html) might be preferable. Petit Parser will be part of the base class library in GemStone 3.2. James On Jan 8, 2014, at 7:14 AM, Mariano Martinez Peck <[hidden email]> wrote:
_______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
Hi Mariano,
Running multiple stones is quite a bit easier than setting up a multi-user stone. And, as Dale pointed out, it makes coordinating upgrades easier. So you might consider doing that first, then maybe considering a multi-user stone later if you see any advantage. I agree with James about allowing arbitrary Smalltalk code to come over the wire and be executed on the server. This *will* be exploitable. If you think it's not, tell me the scheme you're thinking of using and I'll break it for you. :-) Defining your own rule language and parsing that would be more work (but not all *that* much work) but would be much safer. Regards, -Martin _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
Thanks all for the support and help. So.....to conclude, this is what I will do:
- Investigate how to create stones and start with a stone per site basis instead of multi-user. - Create my own DataCurator like user for my app, say 'adminUserX'. This step is not mandatory, but I kind of like it.
- Make sure UserGlobals of 'adminUserX' is only read/written by that user (I need to investigate how to do that). - I will do both, load code and run seaside gems with the user 'adminUserX'.
- I will add validation or something to the rules defined by the user. Likely, I will write my own rule language and yes, I could use PetitParser maybe. Thanks guys, On Wed, Jan 8, 2014 at 3:32 PM, Martin McClure <[hidden email]> wrote: Hi Mariano, Mariano http://marianopeck.wordpress.com _______________________________________________ Glass mailing list [hidden email] http://lists.gemtalksystems.com/mailman/listinfo/glass |
Free forum by Nabble | Edit this page |