The passphrase is "Install already": A new look at VSTO Security.
I've tried to start this post about ten times now, and honestly, the problem is that it's a little hard to know where to start. So I'm just going to dive in.
With VSTO 2.0 to "trust" your customization, you would have to create Caspol entries for everything, including (I believe) the location of the document if it was a customized document. Additionally, there was this Click Once deployment thing that used the Internet explorer cache.
VSTO 3.0 on the other hand has a completely totally different outlook on things. (Groans for the play on words are expected)
So let's first talk about what VSTO 3.0 doesn't use.
First off: we no longer use Caspol. You could create trust entry for everything in your solution, but it's not going to help your solution run. Secondly, the Click Once deployment we use is not the same Click Once that was In VSTO 2.0. We've redesigned the whole Click Once experience in VSTO 3.0 to be much more consistent with the Windows Forms Application Click Once. We no longer force you the developer to create custom windows installers just to install your customization on another machine.
That said, here's what VSTO 3.0 is:
So the new Security in VSTO 3.0 is (almost completely) the same if you are installing using Click Once, simply F5'ing a solution or if you create a Custom installer using a technology like Windows Installer. The differences between these 3 scenarios are details that I'll leave for another day because each of them is a large enough topic to be a post in of itself.
The core of the security model comes down to some basic ideas.
Every part of a program (customization in this case) are not individual units but rather just part of the greater whole. If you can maintain a "signature" that identifies and seals all of the parts of the program so that any tampering is easily detected, this single trust action is enough to ensure that all the parts themselves are trusted.
You can trust (or not trust) either the developer of a program, or you can trust just the program itself if you don't want to trust all programs of the developer.
With those 2 simple concepts we get the basic VSTO security model. In our model we actually take advantage of the security model Click Once gives us, and some of our own parts. We use this combined model even when we are not using Click Once to install the solution. It may seem a little strange at first because usually when people talk about Click Once they are talking about things like "automatic updating", special manifests and the Click Once Cache.
There's also a very rich security model in there. We take advantage of this model and add a few more things, this lead us to:
The actual VSTO 3.0 Security model (I feel like I've already ran the 10 miles but only started the race).
Our model consists of 3 or 4 basic types of objects.
The first type is the "document", it's only valid for document level customization (and really could be a document file, a workbook, or a template). Both Word and Excel require that any customization attached to a "document" can only run if the "document" is trusted. We can make this decision based on 2 things: Location and the Office Trusted Locations List. If the document is local (but not in a specific set of temporary locations) it is trusted. If the document is on a network, the location it is stored at must be in the Office Trusted Locations List.
The second type of object is the deployment manifest. In VSTO 2.0, manifests we optional, this is no longer the case. Your customization will have a deployment manifest, when you build you can find it as a .vsto file. The deployment manifest describes the type of deployment of the solution. Part of this information is some basic details about the certificate used to sign the solution, specifically the publisher and the signature authority can be determined based on this information. Trust decisions are ultimately based on the information contained within the deployment manifest. This file is signed with the developers signature (using the signing certificate), and as such will automatically fail a security check if the file has been changed. The deployment manifest points to the application manifest.
The third type of object, the application manifest (the .dll.manifest file) describes the what the application is. It includes all binaries and resources that will be installed into the Click Once Cache, should the solution be installed. Part of the information about each of the files in the solution is the hash of that file. The application manifest is also signed, which means, once it is signed, any of the solution files being altered will cause it to no longer be valid (Additionally, changing it's contents changes the signature and it will not install without being re-signed).
The final type of object is the application files. These range from dlls to resource files, basically anything that is part of your customization that you expect to install into the Click-Once Cache.
Except for the document type of object, trust for the other parts comes down to one of 2 options:
Trusting the publisher (developer) or Trusting the customization.
A publisher is "Trusted" only if the developer's signing certificate is in the users trusted publishers certificate store and the Certificate Authority that issued the certificate to the developer is a Trusted Root Authority or "chains" to one.
A publisher may be "Known" (verifiable identified) if their certificate comes from a Trusted Root Authority. I expect in most enterprise shops, the enterprise will enforce trusting of a specific publisher. I expect most small home/business developers will only have "known" certificates from a Certificate Authority like VeriSign. A "Known" certificate grants a certain amount of trust-ability to a customization ex: If it's a known certificate a trust prompt will be allowed by default when the solution is installed from the Internet, but it does not actually make the solution trusted (I'll talk more about this when I talk about the inclusion list).
A publisher can also be "Un-Trusted", in which case a customization signed by their certificate will never install.
If the publisher isn't "Trusted", it may be possible to trust the solution (given it is not "Un-Trusted"). If the solution is published in the Internet zone (ex: not on a local intra-net or not on a local drive) it (by default) must be signed by a "Known" publisher. If the solution is on a local intra-net or HDD location then an "unknown" certificate will suffice, but it also brings with it much smaller degree of "trust-ability". In either case, the next step is to trust the solution. We can make a local trust decision for a solution that involves the location it is in and the public key of the certificate used to sign the manifests. There are 2 entry points for these decisions to be made: and API that can be accessed (the inclusion list API) via the Microsoft.VisualStudio.Tools.Office.Security namespace or by clicking the "Trust Prompt" that will come up during installation. Clicking the "Trust Prompt" will actually create an inclusion list entry. When that entry is created, the solution goes form "Not-Trusted" (Trust or Un-Trust has not been determined) to Trusted. The prompt includes a "don't install" option which effectively says "I don't trust this solution".
Hopefully that explanation isn't too confusing, as you can see though, it is a little complicated (and this is the simplified version).
The good news is, what the developer has to do to make their solution work isn't all that bad.
Ideally, obtaining a certificate from a globaly acknowledge Certificate Authority (or from an internal Certificate authority if the solution is for an internal solution only) is the first step.
Sign the manifests (dlls are not required to be signed, but signing them should not cause problems) using the Signing properties page in Visual Studio.
Publish (or distribute) the solution to it's appropriate location.
Let the users or user's IT administration handle determining trust (either via the trust prompt, or via trusting the developer certificate).
In the next installment, I plan to go into depth the inclusion list and all of the curious factors that can come into play.
Thank You for reading.
Kris
Comments
Anonymous
January 17, 2008
I have a question regarding the situation where an assembly that must be shipped with an add-in or document extension is not directly referenced as a dependency. This would occur, for instance, if one wishes to decide dynamically what assembly to load to perform some function (as with using an Abstract Factory) based on runtime conditional logic. It does not seem possible to assure that assemblies not directly referenced end up in the manifest to be downloaded via the publication feature in Visual Studio 2008. Do you have any thoughts on how to address this scenario?Anonymous
January 17, 2008
One way to approach this scenario is to bundle all of your indirectly referenced Assemblies into a MSI and author the MSI into a prerequisite package. This works well if you don't think the assemblies you are binding to are going to be updated (or you can live with a different update story for them). However there is another way. You can add the Assembly directly to the VSTO project as a "Content" file. As long as you select "Copy Always" the file should get copied into the Build Folder and should be published. In this scenario your indirectly referenced assemblies always end up in the ClickOnce cache next to your VSTO Assemblies. At that point your assemblies also fall under the ClickOnce updating model (rollback/updates/etc work as normal in ClickOnce, version parity is maintained).Anonymous
January 21, 2008
I've been thinking about this a little bit. If you do decide to employ late binding and push your assemblies into the cache, you will need to determine at runtime where that is. Here's what I would use (based on investigation by a co-worker) System.AppDomain.CurrentDomain.BaseDirectoryAnonymous
February 27, 2008
Hi, Ive just managed to get ClickOnce working with Office 2007 and an application level Excel add-in. Now I need to create an installer for Office 2003 applications. I have an existing install using VSTO 2 SE and CASPOL - generally works OK. Moving to VS 2008 can I now exclude the CASPOL stuff and rather use VSTO 3.0. If I do so, I understand I need to sign the manifest for trust. Can I creat a standard setup and deployment project and include VSTO 3.0 as a pre-requisite or must I use the publish function as with ClickOnce (my confusion results in that I dont know how the standard setup project creates and signs manifests. Thanks.Anonymous
February 28, 2008
I'm not quite sure what you mean by "standard installer" but this might help, if not let me know. Office 2003 in VS 2008 still works under the old deployment/Security model of MSI + CASPOL. You still need to follow the same steps for deploying customizations built against the 2003 version of Office. (When you installed VS 2008 you should have 2 VSTO Runtimes, the VSTO 2 SE runtime and the VSTO 3.0 Runtime) If you tried to create a manifest against this runtime, the manifests were not signed. VSTO 2 used a flavor of ClickOnce that was built for VSTO. It wasn't until VS 2008 (and Office 2007) that we were able to integrate into the "standard" model of ClickOnce with signed manifests. However... If you are just considering customizing Office 2007, then yes you can ignore CASPOL and you can easily build the bootstrapper. By default when you publish using the publish page, a (standard) bootstrapper (setup.exe) that includes the prerequisites(by default: windows installer 3.1, the 3.5 .NET Framework and the VSTO 3.0 runtime ) is created. If you go to the Project Publish Properties page and click the Prerequisites button you can select any prerequistes you want including and custom prerequisites that you make (just like in a MSI Setup project). In VSTO 3.0 there is no dependancy on the setup project like there was in VSTO 2.0 and 2.0 SE. We expect that in most cases the developer should not need to create it (though you can still create a standard MSI installer, more on this later). VSTO 3.0 Manifests are created and signed automatically when you build the solution and are required even for "F5". The bootstrapper doesn't really have any direct relationship to the manifest. The way the bootstrapper starts the VSTO Click Once install is to call VSTOInstaller with the path to the manifest. If you wanted to create an MSI installer (with a setup project) you would still have a (standard) bootstrapper and would have to do one of the following: Publish/copy the (publish contents) manifest and application folder contents to a (known) accessable location (you could publish to an internet or network location in which case the MSI would not need the manifest and etc.) and then use VSTOInstaller to start the customization install. OR you could include the build folder contents into the MSI manually, register the (addin) (or recustomize the document to point to the local location of the .vsto file) withe the |vstolocal tag. This bypasses the ClickOnce install but not the security (in fact security is evaluated every time you run instead just when an update is installed). Clear as mud. Anyway, if that's not enough information, let me know what it is you're trying to do an I'll try and give you some clearer advice.