Closed shiftkey closed 10 years ago
I submitted the pull request, so I will be the first to jump into the fray.
First, let's make sure it is clear what we are talking about. This issue is about Strong-Name Signing, not signing the code with an SSL certificate purchased from a signing authority.
Strong-Name signing just provides managed assemblies with a globally unique identity, whereas the second is used to verify the publisher of the application, in this case GitHub. The signing key for strong naming is just a key that a developer creates on the command line and checks into the repository. Ideally they would be secured, but that does not work for open source projects.
Public libraries should always be strong named otherwise they cannot be used by applications that are strong named or in Click-Once deployments. In my case, I am working on a Visual Studio extension which should be strong named. I can get around it, but that will limit what I can do in the extension.
Look around at most of the most popular non-Microsoft open source libraries, they are all signed and are not putting artificial limitations on their users. Here is a short list, Newtonsoft.Json, NUnit, NLog, Ninject, DotNetOpenAuth, log4net, AutoMapper, Castle (Windsor, MonoRail, etc). In all cases, their keys are in their repositories.
If you want to troll around your bin directory and see what is signed, sn -T Ninject.dll
So, to sum up, Strong-Name signing costs you nothing and allows your library to be used everywhere and play nice with others.
Okay, who's next? Gloves off, Internet fight time...
LOL.
This is an issue on another public project I try to help with.
Let me throw this idea out there that I've been toying around with. (Disclaimer: I've seen the idea on a few projects so it's not an original idea.)
What if we were to set up the build server to generate two different sets of assemblies, one Strong-Name signed and one not signed? As a byproduct it would also generate two sets of NuGet packages. The unsigned NuGet package would continue to have the same name. The signed NuGet package would be named something along the lines of "Octokit-Signed".
The one downside to introducing signed assemblies, only, is that it could lead to assembly version redirect issues for end-users. log4net ran into this issue and got a little backlash from it.
I'd like to think it makes people on both sides of the fence happy. Thoughts?
Two sets of NuGet packages is very bad for libraries that other libraries depend on. What package should they reference? This might not be as big a deal for Octokit.net.
I believe that eventually, strong naming as we know it will be burnt down by the CLR team and replaced with something better.
Using Octokit in Visual Studio seems like a core scenario to me. I would be :thumbsup: to taking the JSON.NET approach.
In this plan, NuGet becomes the unit of deployment, not the assembly as has traditionally been the case with .NET.
By freezing the assembly version, we don't have to worry about binding redirect problems in the future. Octokit is pre-release right now so I don't care about introducing breaking changes like this at the moment.
Also, while you should never rely on strong name keys to verify an assembly, I do worry that people still do. So we should consider having a set of private keys in the project for builds and another set for the official releases that we keep private.
The alternative is just to have one set of SN keys and have them in the project and hope people by now understand SN verification is a bad idea.
@Haacked, I do agree that two NuGet packages are a bad idea. That's why the other project I'm involved in hasn't proceeded in any direction yet.
Freezing the assembly versions would work to resolve the binding redirect (I forgot the name for that) problems. I can't think of any downside to this off the top of my mind, but can you think of any?
@Haacked, I also agree that two sets of NuGet packages is a very bad idea, especially if you do freeze the assembly version number which takes away the only downside that I know of. We've been having the same discussions over on the NUnit team recently, but at least we have the advantage that unit tests are recompiled often.
As for keeping the key private, if you want to, you could have the build check for the existence of a key and generate one if it doesn't exist. Then you just need to drop the key in on the build server.
That said, from my experience, most open source projects just check it into the repository. I think the downsides of that are much lower than the consequence of ever losing the official key which would be a breaking change if you had to regenerate it. Plus there is just the headache of keeping track of the official key and making sure it is always used for the production builds.
+1 on freezing the AssemblyVersion number. The AssemblyFileVersion can be used to store the real version number instead.
If I'm not mistaken, you could increment the assembly version on major releases (i.e. 1.0.0, 2.0.0, 3.0.0) as those would be breaking and require recompilation anyway when following SemVer?
I was thinking more about freezing the assembly version number and wonder if it is necessary for this project. There are usually only problems for libraries that tend to get pulled in from other libraries. For example, when a project uses two NuGet packages that reference different versions of log4net.
I don't think that will be a problem for this project as it will probably be a top level package.
If this ends up getting the thumbs up, I would be happy to take my original pull request and incorporate whatever is decided here. Just let me know.
If the version number was to be frozen. What would the benefit be to freeze it indefinitely as opposed to updating it for major releases (i.e. breaking changes)? Don't we want it to break at a predictable time if the assemblies are not actually compatible?
Also this :+1:
I don't think that will be a problem for this project as it will probably be a top level package.
Was going to say that I would also rather see the key be public and checked into the repository. But considering the above statement, using a private key becomes much less of an issue and I really have no preference one way or another re: public vs. private :key:
In summary I would say Sign it! If we have to freeze the version number (not convinced that we do) at least update for major releases. No preference on public/private key for official releases.
I hate it when @paulcbetts writes what I wanted to
https://github.com/reactiveui/ReactiveUI/issues/43#issuecomment-37471892
Every time a new contributor comes along, they now have to have an extremely demotivating fight with Visual Studio to get the project to build, or to replace the official binaries with ones they've built for testing.
Anyone have a sample/blog post around about doing this without touching the csproj files so we can avoid this pain?
But I'd lean towards Authenticode signing for this sort of thing, because It's The Real Deal.
@shiftkey what paul writes about is a non-issue if we just include the official snk in the solution. Problem solved.
Remember, we're not doing this for security reasons. We're doing it so people can use Octokit.net within a Visual Studio extension. I bet you can see the appeal of that to me. :wink:
@Haacked I mean, I currently use ReactiveUI in a Visual Studio Extension, I don't know where this "You must SN every binary" is coming from
I mean, I currently use ReactiveUI in a Visual Studio Extension, I don't know where this "You must SN every binary" is coming from
People keep telling me this :poop:. If we don't need to sign it, then let's not. What the hell? Can I get some good intel here? :smirk:
Can I get some good intel here? :smirk:
This seems like an interesting breakdown of the VSIX situation: http://stackoverflow.com/a/16452046/1363815
Reasons for strong naming:
Also, if you didn't strong name sign, you do risk a name collision with another extension.
template wizards do require strong name signing, but only because they must be installed into the GAC
If your package exposes a public API which other extensions consume, you might be referencing a common DLL as the other people consuming your public API.
If you created a DLL called "Package.dll" and another extension also did, and neither of you strong name signed your binaries, it's possible the CLR will get a bit confused here. So if you weren't strong name signing, make sure your assembly name is "unique enough" to avoid this risk.
Reasons against:
If you are already VSIX-deployable and don't need anything in the GAC, then no, Visual Studio makes no requirement that you are strong name signed.
Emphasis mine
Also, if you didn't strong name sign, you do risk a name collision with another extension.
lol ok
template wizards do require strong name signing, but only because they must be installed into the GAC
If you install Octokit into the GAC you've got bigger problems
If your package exposes a public API which other extensions consume, you might be referencing a common DLL as the other people consuming your public API.
This has happened before with libgit2sharp, it's the one legitimate reason you might want to SN.
I am the one working on the Visual Studio extension. Not signing the extension is not causing any major problems for me and as long as I keep my assembly names unique, I shouldn't have a problem.
It does prevent anyone from creating a Visual Studio template extension with wizards which is a possible usage, but to be honest I can't think of an Octokit.net use case for a wizard. Maybe automatically create and populate a Github repository for new solutions? Actually, that would be kind of cool :+1:
@paulcbetts, I've done template wizards before. It isn't Octokit that needs to be in the GAC, just the wizard, but it means that the rest of the extension (not in the GAC) needs to be signed and therefore all the assemblies you use with it.
If anyone is interested in checking out or helping me beta test the Visual Studio extension, add a comment to https://github.com/rprouse/GitHubExtension/issues/47 and I will get in touch.
We have a huge application that we are trying to use ReactiveUI in. Our application is strongly named and it is up to our architects to allow removal of strong-naming which they refuse to. Now we are having a catch-22 with this ReactiveUI. Paul (I respect this guy) has not come up with a good reason not to have ReactiveUI strongly-named.
I have never had trouble getting public libraries from NuGet because they generally are all strongly-named. We cannot maintain a branch just for strong-naming, it would be an extra effort for not a good reason.
note the VSIX+share appdomain issue also exists for msbuild tasks. in some cases you can have multiple slns sharing the same msbuild appdomain. SN does avoid this.
But this should be a deployment concern for people writing a task or VSIX.
Options
I tried creating an unsigned package. People unhappy. I tried creating two packages. People unhappy. Eventually I just went with signing the assembly, freezing the assembly version at just major/minor versions, and nobody has complained since. I think the reality is this is the most accessible, least bad choice.
If someone's going to bear the suffering of Strong Naming, it's going to be the people who want it, not the Open Source community and everyone else sane who doesn't want it. -:100: to strong naming.
Maybe my project is different, but I've never received in 6 years anyone asking to remove strong naming. Only to put it in. I error'd on the side of inclusion and maybe (?) pain for some, versus exclusion.
I also dual licensed my project, which I didn't care about, but also led to inclusion for folks that can only accept MIT or Apache. But what can I say, I'm a pleaser.
I agree with @jbogard. I was strong naming first, nobody complained. Then someone convinced me that strong naming was bad (at least, it should be banned). However I get more and more requests to strong name it again. The downsides of strong naming are:
1) ???
And the pros are:
1) People can decide whether they want to strong name themselves (both ways are working with strong named assemblies) 2) You can use assembly redirects in your config files (and then it is up to the user whether he wants to redirect breaking changes versions (as in 3.x => 4.x)
I know strong naming is nonsense for some, but as long as the users are happy, why not? It's not that it costs you money, takes a lot of time or is very complex.
@GeertvanHorrik to add to those pros: 3) Strong-named assemblies can only reference other strong-named assemblies. For me, this meant I locked out a ton of folks from using my library 4) Some companies have arcane, insane policies around strong-naming ALL THE THINGS. It's not the developer's policy, so why punish them.
Ultimately, my assembly versioning policy removed most (or nearly all) the pain of strong naming. I reversed my position as it was really pride that was the only thing keeping me from strong-naming. But, this really only applies to my library and how it was being used, referenced and applied. Dunno about OctoKit but thought I'd share my experiences.
@jbogard
3 == 1 4) Agree, but is probably the reason why we "need" 1 ;-)
I'm reminded of a Richard M. Stallman Quote:
"This is where I am great. I am great at being very, very stubborn and ignoring all sorts of reasons why you should change your goal, reasons that many other people will be susceptible to. Many people want to be on the winning side. I didn't give a damn about that. I wanted to be on the side that was right, and even if I didn't win, at least I was going to give it a good try."
Depends on the "right" side. Everyone likes to be a visionary, the one that knew what had to be done. I just look at your latest message:
"If someone's going to bear the suffering of Strong Naming, it's going to be the people who want it, not the Open Source community and everyone else sane who doesn't want it"
1) What "suffering"? 2) I am part of the Open Source community, and what is wrong with strong naming?
So can you please elaborate with actual arguments? I really want to add it to the list of cons in my previous posts, but I cannot put wise quotes there...
@GeertvanHorrik Here's my previous write-up of this issue:
https://github.com/reactiveui/ReactiveUI/issues/43#issuecomment-37471892
Short version: SN fucks with the "Getting started contributing" story and the "Build my version from source" story
From what I understand, you consider "strong naming" an enormous entry level burden to take when entering a project. I do this in my SolutionAssemblyInfo (shared over all projects):
#pragma warning disable 1699 // 1699 = Use command line option '/keyfile' or appropriate project settings instead of 'AssemblyKeyFile'
#if SIGN_ASSEMBLIES
// Sign assembly (this is relative to the obj output directory)
#if X86 || X64
[assembly: AssemblyKeyFile(@"..\..\..\..\Catel.snk")]
#else
[assembly: AssemblyKeyFile(@"..\..\..\Catel.snk")]
#endif
#endif
Every junior developer can build this, or am I missing the big clue here?
And about new versions, you can redirect them (in case you are working on a diff. version than you are currently using on existing projects).
@GeertvanHorrik out of curiousity - why the two different keys?
I still don't understand how SN fucks up the "Get started contributing". Developers pull down the source, compile in VS, and they have a signed version of the assembly. Or run the build, whatever. Where's the contributor pain exactly? I'm not trying to be an ass, I'm genuinely curious.
The only time I've truly had problems with SN is when I try to recompile MS stuff and they don't distribute the key. I get around this by putting the key in the repo and removing build/revision numbers from the assembly version. Seems pretty straightforward to me, what am I missing?
@shiftkey The keys must be relative to the obj folder (so even when you change the output (the default bin folder), the obj files are used for strong naming). For AnyCPU, this is easy (obj), but for x86 and x64, the obj contains an additional directory which you must "step up". So the keys are exactly the same, just different paths to conquer.
Ok, so we've got a bunch of feedback about how to address the onboarding experience, and how to freeze the assembly version to ensure maximum compatibility. That's all fine.
However what still isn't resolved for me is about the when strong-naming is necessary, and the impact of not strong-naming (as we're doing currently). Yes, I know many teams do strong-naming still, but I'm not satisfied with doing it for the sake of doing it.
I've seen some mentions of scenarios above, so let me call out the specific scenarios I've seen mentioned so far:
What else have I missed? What war stories do other people have that we need to be aware of?
@shiftkey also the VS extensibility story can be answered with "ILMerge and then SN the result"
Note of caution about freezing the assembly version: If someone GACs an old version of your library with the same version then every application will automatically prioritize the GACed assembly over the assembly in the /bin folder.
The scheme I have settled on with json.net is to increment the assembly version only for major releases (i.e., infrequently) to balance the possibility of old versions being GACed vs the need for binding redirects.
No matter what you do no one will be completely happy but that is the best solution I have found for keeping the most people happy.
A strong named assembly can only reference other strong named assemblies. Weak named can reference both. @shiftkey so that means anyone that strong names their assembly for any reason whatsoever cannot use this library.
@jbogard
so that means anyone that strong names their assembly for any reason whatsoever cannot use this library.
:cool:
Given I haven't had to SN something of my own free will in many, many moons, I'd love to hear why people are doing this...
@jbogard
anyone that strong names their assembly for any reason whatsoever cannot use this library.
That is not technically correct. They have the option of either strong naming this lib themselves or ILMerge and then SNing the result
This is functionally correct, however. When I suggested this to folks using AutoMapper when I removed strong-naming, I got...less than enthusiastic responses. That's just not a viable option. There's no right-click-reference-click-strong-name in Visual Studio, making this choice a non-starter.
I also distribute as a PCL and a platform extension library. It's even harder to modify an assembly's references to point to now a strong-named assembly.
The main argument is "my boss makes me do it" or I need to GAC/Allow multiple in a single appdomain, we could mitigate this by creating a tool/exe/msbuild task which allowed you to easily strong name everything in the build output folder (which is not signed), optionally ILMerging everything in before it signs?
For me it seems that you try to sag under folks who love monkey-patch and binary update all the things, when you yell arguments like 'the "Getting started contributing" story', and 'the "Build my version from source" story' and 'binding redirects pain'.
So the problem here is to decide what you need - do you want more users of your library or not. If you do so, then sign the fcking assembly and go ahead. If you don't care about your users - continue to think up the reasons like "my god does not allow me to sign my assemblies".
@hazzik
So the problem here is to decide what you need - do you want more users of your library or not.
I started this discussion as a way to hear more about how/where people are using strong naming, in particular situations where they needed strong naming to use Octokit.net. As someone who doesn't need strong naming, the input from others has been great to clarify things for me - as well as the various gotchas we've found from others who do SN on their projects.
If you do so, then sign the fcking assembly and go ahead. If you don't care about your users - continue to think up the reasons like "my god does not allow me to sign my assemblies".
We also had a long JabbR chat last week with some of the chaps at Microsoft about the strong naming situation. You should check it out (should be the afternoon of Friday 25th in your timezone).
If we were violently opposed to strong naming, we probably wouldn't be having this discussion.
oh wow! @hazzik
So it looks like there are some suggestions for people to do things like this:
or ILMerge and then SNing the result
Um, is it just me or that sounds like crazy-talk? Like, just because we can do it .. doesn't mean we should be doing it. What ever happened to Keeping thingS Simple?
My question about all of this, is this:
If the users are mostly Visual Studio Extension builders .. then some of the arguments (above) about SN + VIX might take preference.
If the users are mostly dark matter developers (oops. these folks don't use non MS libraries) or your avg joe public making web sites or phone apps or maybe a desktop app ... then really, really do they cared about SN?
Or putting it another way, does having the library not signed make it easier for these type of users to easily consume OctoKit in their solutions?
A tiny part of me wonders if the vocal minority are those people who QQ for SN. The flip side - is it really hard for -them- (if they are a minority) to clone + SN + build it, themselves?
If you have to SN it, then I've been a fan of the 'best of the worst' solutions to this: lock down the aseembly and use NuGet versions.
Now for some useless opinion..
Personally, people who are using the GAC still (eg My boss makes me do it [sigh..] , etc) ...
(But my opinion doesn't help solve this important question, though :blush: )
My brain is too small ... I'll just go back and hide in Jabbr.
Signing is bad despite what argument @hazzik can come up with. Don't sign. Too much pain signing.
C'mon, @phillip-haydon, do you want to discuss how you suffer from signing assemblies? Did you go to your local church or a psychotherapist to discuss that?
Well I'm lucky, I don't go to church or follow any religious cults such as Christianity, so I don't have any need to see a psychotherapist.
I don't really want to discuss how I suffer from signing, but we can discuss the benefits of signing:
Benefits of Signing:
@phillip-haydon there is an "or" between church and psychotherapist.
But the huge benefits of signing that then users who need to sign their shit for whatever reasons can use your signed shit.
@shiftkey, it is just my general opinion on that religious "problem", it does not related to Oktokit.net, nor to you directly.
I fully agree with @jbogard as he said that by removing signing or not signing a project you will just drop a lot of your currrent or potential users. And as he said - no one ever asked to remove strong naming from an assembly.
So the problem is just made up by people who are to scared to press one button in VS to sing an assembly, or by people who "suffer" from binding redirects "pain" (never had this before), or by people who love to do monkey patching by dropping assemblies into a bin folder.
Benefits of Signing:
Какие ваши доказательства?
So #404 landed, and I wanted to have a proper discussion about whether we should do this in an official capacity for Octokit releases.
So let the fur fly (remember, bonus points for good reasoning and being gentlemanly) and I'll check back in a few days to see who is left standing...