Thursday, October 04, 2007
Posted on Thursday, October 04, 2007 11:02:35 PM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: ArcGIS Devt | ArcMap | Geodatabase

We put a lot of business logic into Class Extensions tied in on the OnCreate, OnChange, and OnDelete Object Class Extension events. If an edit violates business logic, it is rolled back and the user is informed about what was wrong. This has been working quite smoothly until today when we started creating our Object Inspectors (see previous post).

What we found was that attribute edits done through our Object Inspector (and consequently ArcDAL) were not respecting the business logic. I dropped some breakpoints into the OnChange event in one of the class extensions, and found that it was not hit when we saved changes in the Object Inspector. Yet, when I opened the table editor I would see the changes, so I knew something was happening. Here's the series of events graphically...

1) Original values in Object Inspector...

original-values

2) District Name updated and saved

update-values

3) Table editor shows the updated name, but OnChange event never fired!

table-editor

4) When I try to edit the District Name via the table editor...

table-editor-change

the OnChange event does fire, and the edit is rolled back because I do not have edit rights to that feature.

table-editor-roll-back

We traced it back to using update cursors. Turns out that updating features via FeatureClass.Update in an edit session does not store changes to the base table until the edit session is saved. Thus, the ObjectClassExtension events do not fire until you "save" the edits and end the session. We need these events to fire as the edits occur so the user is informed when business rules are broken.

The solution was to just change back to using IFeature.Store - which correctly raises the events. This was just 4 simple edits, but we have 25 feature classes in our geodatabase model. Thanks to code-generation, we just made the edits in the templates, and re-generated all the classes.

Sunday, April 29, 2007
Posted on Sunday, April 29, 2007 8:48:26 PM (Mountain Daylight Time, UTC-06:00)  Comments [1] | 
Categories: ArcGIS Devt | ArcGIS Server | ArcMap | Geodatabase

I recently recieved an email from a reader asking about role based security & ArcGIS Server. Specifically they were interested in restricting access to columns, based on the user's credentials.

I'd been doing some thinking on similar issues related to row based edit permissions, and I thought I'd share my ideas on possible solutions to these problems.

Fine Grained Access Permissions

Essentially, you can't use the DBMS security capabilities to restrict user access to columns or rows because ArcSDE does not support security at this fine grained level (FeatureClass, ObjectClass or FeatureDataset only). There may be some hacks, but as far as I know nothing like this is supported directly.

Next, and possibly more important, regardless of how you actually create the connections (i.e. store the connection properties in the MXD file, or use pass-through authentication and grant the SOC process permission to connect into the database) all interactions with features are done as the SOC Service user. The identity of the front end user  is not passed back to the SOC. Thus, regardless of who is running the application, the SOC identity is always the same. The diagram below shows how far you can pass back the end user's identity (assuming you setup impersonation in your web app).


 

The SOC always runs as the SOC Service user - so any use of the end user's identity to control any sort of access is not going to work.

Possible Solutions - Restricting Access to Columns

There are a variety of ways to tackle this, but none are particularly flexible - you will need to define the roles up front, and then setup the application to respect those roles explicity. Adding additional roles will require code changes. Four options come to mind

1) Let the SOC return all the data and apply the permissions in the client application. This is not a bad solution if you control the web app. It basically means re-writing a lot of the out of the box tools so that they will respect this additional business logic.

2) Setup the spatial data so that it has the minimal set of field that all users can see (including ObjectId). When doing an inquiry, the web app would get the base set of fields from the featureclass, and then use the ObjectId  to run a second query against a multi-version view to retreive the other "secured"  attributes. There would be a multi-version view for each role in the application, and the columns would be restricted as needed. The application logic would need to handle the mapping of the users role to the correct view.

3) Use Spatial Views. Similar to #2, but the SOC would load layers based on the user's role, and the layers would actually be Spatial Views with only the columns that are visible for the particular role of the user. I suspect this would be slower than the previous two options, as the SOC would need to load layers all the time, but if the application is using a non-pooled SOC anyhow, it may not bemuch more of a performance hit - just start with a minimal map (just the layers which do not have any restrictions on them). The upside is that you can likely use most of the out of the box tools since the column restrictions are being applied by the view, at the ArcSDE level. Another upside of this model is that the restricted data is never available - either in the SOC, or in the web application tier.

4) Similar to #3, you could separate out the restricted fields into separate tables, and apply joins on the fly. Same benefits as #3, but you'd still want to work with non-pooled SOCs. Not sure how well this would play with the out of the box tools, but it may be ok.

I'm sure there are other options, but I suspect they are all variations on this same theme. If the application was super simple (like 1 ID tool), you could just limit the fields returned by setting the IQueryFilter.SubFields property.


Row Based Edit Permissions

For our applications, there are typically business rules which restrict the area in which a user can edit features, and related attribute tables. In the past we have implemented this logic in feature class extensions. In the extension, we simply get the current principal (the user's Windows Login identity) lookup their access permissions from our repository and allow/block the edit. We have logic in the extension which allows for editing of shared boundaries (which I believe is one of the issues with implementing this sort of logic at the DBMS level)

This works just fine for Desktop and ArcEngine applications, but is more problematic for web applications. As I noted at the start of this post, all connections into ArcSDE from ArcGIS Server run as the SOC user. Thus we have a problem - if we apply a class extensions to the geodatabase, it's logic always fires - regardless of the client appliction. But, if all the edits from everyone using the web app effectivly run in the same context, (agssoc or whatever you call it on your system), then this logic is both moot, and a waste of processor time. But we still want to use this logic for the desktop apps, so we had a bit of a problem.

Our solution is to create feature class extensions which are themselves extensible. Basically we use  the Provider Model to add in various security providers at run-time. When the class extension spins up, it uses the ConfigurationManager to check the configuration file (ArcMap.exe.config for desktop, web.config for web apps) for "SecurityProviders". In the desktop apps, there will be a provider configured, the class will be instantiated, and the logic applied to all the edits. In the web app, we do not configure a security provider, thus there is no logic applied. 

This still begs the question of "how does the row based edit permission get applied in the web app?". At this time, there is no (easy) way to pass the user identity back into the SOC, let alone get the SOC to impersonate a user such that the class extension would be running in the context of the front end user. So, for now, the answer is - the web application must handle this logic itself. While this is not idea, at least the class extensions can be used in the desktop apps - which is where the vast majority of the edits will occur anyhow.

Wednesday, February 28, 2007
Posted on Wednesday, February 28, 2007 2:55:20 PM (Mountain Standard Time, UTC-07:00)  Comments [2] | 
Categories: ArcMap | Geodatabase | Security
[UPDATE 3/1/07 8:00am : After a few emails with ESRI, they agreed that discussing their public API, as it relates to the security of passwords is reasonable, and they have confirmed that the password that is returned by IWorkspace.ConnectionProperties is encrypted. For obvious reasons they will not disclose any of the technical details. Thanks to ESRI for confirming this, and for permitting me to share the answer.]

[UPDATE 2/28/07 7:50pm : I received a request from ESRI to take this posting, and my related forum post down because they discuss security and encryption related to their software. At this time, I'm taking the posting down, and will work with them to determine a reasonable update. Stay Tuned]


[ORIGINAL POSTING]
I posted a question [I deleted it's contents at ESRI's request] over at the ESRI forums about this, but thought I'd also throw it out here as well. Essentilly, I'm looking to build a secure application, and I want to know if it's possible to extract the connection password from the data returned by IWorkspace.ConnectionProperties. I posted some VBA code from an EDN sample that pulls the connection properties from the first layer in the map and displays the properties in a popup. All I added was a few lines which would actually write out the password byte array.
 


What I'd like to know (preferably from someone @ ESRI) just what that byte array is. I suspect it's the password encrypted, but it could also be a hash. If it is the password encrypted, where is the key? How safe is it? If it is a hash, is it reversible?

[Clarification: In my  original posting, I had asked a series of rhetorical questions (above) - I did not expect to get these answers from ESRI, nor do I really want them - I really just wanted to know that the password is "relatively" safe - i.e. encrypted.]

Friday, February 23, 2007
Posted on Friday, February 23, 2007 5:06:17 PM (Mountain Standard Time, UTC-07:00)  Comments [2] | 
Categories: ArcMap | Geodatabase
I had heard that raster performance in a File Geodatabase was good, and thought I'd check into it. For source data I used 4 tiles of 6 inch orthophotography. The files are TIFFs, and come in at 715MB each.

Initially I tried loading all 4 into ArcMap, and it just took too long to display, so I killed ArcMap, and re-started by just loading one.

To load and draw the file (no pyramids) took ~60 seconds (based on my watch)



Next, I used ArcCatalog to created pyramids for another of the tiles (took a few minutes and created an 80Mb RRD file). This loaded in about 5 seconds.




Finally, I loaded all 4 TIFFs into a file geodatabase (again took a few minutes). The resulting File Geodatabase is 2.87 GB in size, so it's a little bigger than the source TIFFs, which were 2.7GB. When loading into ArcMap, the layer took about 1 second to draw (again using my watch - it maybe a half second - hard to tell, other than it was FAST).




The other thing to note is that in both the TIFFs, the resulting image looks pretty choppy at this scale (compare the images above). The File Geodatabase image looks great.

As far as zooming and panning, the File Geodatabase just rocked. It's screaming fast. This next shot is at full resolution - I zoomed in 3 times drawing a rectangle each time, and the screen re-draw just about as fast as I could draw the boxes. Amazing.




The TIFF with pyramids seemed to be about the same speed with panning and zooming, but the TIFF without was consistenly a much slower 2-5 seconds for a pan or a zoom.

So - if you've got imagery that's slow, try out the file geodatabase and see if you get the same boost in speed.

Note: All these tests were done on a local disk - connecting across a network will impact performance.
Friday, November 10, 2006
Posted on Friday, November 10, 2006 11:28:27 AM (Mountain Standard Time, UTC-07:00)  Comments [1] | 
Categories: ArcCatalog | ArcSDE | Geodatabase
For the last few weeks I've been working on three elements of an enterprise system - high-level functional requirements, the system architecture and the geodatabase design. I'm working from a mass of information collected from weeks of on-site meetings and a mountain of documentation supplied by the client. And, for the most part, things are going pretty well. Except for the actual geodatabase design experience.

The Present
The standard practice for creating a geodatabase model is to use Visio or Rational Rose to cookup the model in UML. Ok, I can see where this started - UML is handy for designing class model diagrams, and the various elements in the geodatabase are classes. But there is a lot more in the geodatabase than can not easily be managed in UML - projections, topologies, rasters. And the whole use of tagged values is truly painful. Overall, the entire process is horribly inefficient.

One issue is that there are several hundred possible "types" for a field...


While this makes sense for a Uml model, it's a pain for geodatabase design, as there are only 12 valid attribute types (plus the Domains in the model). Yet I still have to jump through this list for every single attribute on every single class.

Once you've finally created your model, and gotten it to validate, you then need to load it into a geodatabase. This is pretty smooth, but you need to manually define the projection for every featureclass (or dataset) in the model. And then you need to setup the topologies. Manually. If you need to do this iteratively - like most design processes - then you need to repeat this process several dozen times.

Don't get me wrong here - this is a million times better than trying to manually bake a geodatabase via the ArcCatalog interface, so thanks to ESRI for giving us this option. But, if we're wishing for 9.3 goodies, this would be a nice thing to fix.

The Future
What I'd like to see (either from ESRI, or anyone else who's got some time, and wants to make some money) is a tool which can handle all aspects of the geodatabase. I want to define my topologies and projections in the design, not later. If I've got rasters, let me have them in the model. Networks? Yep. The question is: How?

Lets start at the end - How can we get a geodatabase design into a geodatabase? The current method is to use the CASE Tools in ArcCatalog to load the Visio or Rational produced Xmi file. The other option is to use an Xml Workspace document. They store all aspects of the geodatabase, so it's an idea option. Typically these are used to transfer schemas (or data) between geodatabase instances - usually ArcSDE instances, but there is no reason that they could not be co-opted as a model storage format. Ok, that part is solved.

What we really need is a nice front end. The key here is to keep the interface simple. Designing a geodatabase is not rocket science, and should be really easy. Have some simple design surface, but I don't see a big need to show all the fields. Just the class name, it's type and the relationships it particpates in.

Have another design surface to show the topologies. The editor UI for the classes should be very easy to use - instead of crytpic tagged values for the geometry type - how about a pull-down? For relationships, just connect two classes with a line, and present a simple dialog for picking PK/FK, notification. Simple, focused, and all about the geodatabase. And if you offer it for $300, I think you'll sell a ton of them. Heck - maybe ESRI buys it from you and ships it with ArcCatalog, and all our lives are just a little bit better.

For now though, it's back to Visio for me. joy.