Conversation
| 1. Copy all files from the previous step, including the application manifest file itself, to a temporary directory. | ||
| 1. Sign files in the following order: files alongside the application manifest, the application manifest itself, then the deployment manifest. | ||
| 1. Copy the files back. | ||
| 1. If the signed deployment manifest file is a `.vsto` file, copy it to the versioned application manifest file directory and overwrite if necessary. |
There was a problem hiding this comment.
I'm debating this. I feel like Sign CLI should not do this; Sign CLI should focus on signing, not emulating behaviors of a build-time task. Users who desire this behavior --- not just for .vsto files, but any ClickOnce app --- can do the copy after signing.
In trying to provide an equivalent experience to the VSTO build-time task, I think this will set up Sign CLI to do more non-signing-related chores. This is not a sustainable direction for Sign CLI.
There was a problem hiding this comment.
Since it's not called out, I wanted to mention that if you are taking an existing published application and signing it's manifest/binaries, the deployment manifest will have to be re-generated after signing the application manifest to update its assembly identity in the deployment manifest.
You can see it happening for ClickOnce apps here:
https://github.com/dotnet/msbuild/blob/014f3faab9cc9a5c3387d04190fbca51abac34e7/src/Tasks/Microsoft.Common.CurrentVersion.targets#L6336
| 1. Interate through both [`AssemblyReferences`](https://learn.microsoft.com/dotnet/api/microsoft.build.tasks.deployment.manifestutilities.manifest.assemblyreferences?view=msbuild-17-netcore) and [`FileReferences`](https://learn.microsoft.com/dotnet/api/microsoft.build.tasks.deployment.manifestutilities.manifest.filereferences?view=msbuild-17-netcore), manually resolve `TargetPath` property to the base path of the application manifest file. | ||
| * Note: it seems like calling `Manifest.ResolveFiles()` would resolve the full file path for every file dependency in the application manifest. However, this fails because `ResolveFiles()` assumes dependency files do not have `.deploy` file extension, but they do. We could temporarily remove the `.deploy` extension and then call `ResolveFiles()` but a user's glob patterns might filter out files based on the `.deploy` extension. The safest option is to resolve file paths ourselves. | ||
| 1. Copy all files from the previous step, including the application manifest file itself, to a temporary directory. | ||
| 1. Sign files in the following order: files alongside the application manifest, the application manifest itself, the deployment manifest, then `setup.exe`. |
There was a problem hiding this comment.
You can sign files programmatically using https://github.com/dotnet/msbuild/blob/a9d68ab58eab3c25b6378a90be8060dd1429a6ef/src/Tasks/ManifestUtil/SecurityUtil.cs#L552
e9d0f84 to
608a5d3
Compare
608a5d3 to
cee18cb
Compare
|
|
||
| ### Rollout strategy | ||
|
|
||
| The new ClickOnce signing algorithm is **opt-in**. Users must pass the `--use-new-clickonce-signing` flag to enable the proposed behavior. Without this flag, Sign CLI continues to use the current algorithm described in Appendix A. |
There was a problem hiding this comment.
Would it instead make sense to have a "version" of clickonce signing. The default today would be version 1 and this new one would be version 2.
The command-line argument would something like --signing-version 1 and --signing-version 2.
Then we could consider logging a warning when people are using signing version 1 saying that version 2 is better. Eventually we could make version 2 the default, and then users could still specify version 1 as an escape hatch in the future.
There was a problem hiding this comment.
@jeffkl, would it be generic (i.e., --signing-version) or ClickOnce-specific (e.g., --clickonce-signing-version)? It seems like it should be the latter to enable signing parts to move independently of one another.
There was a problem hiding this comment.
Yes it should be specific to clickonce. I originally thought clickonce signing was its own gesture but its not
|
|
||
| 1. Load the deployment manifest, locate the referenced application manifest, and refuse to continue if it is missing. | ||
| 1. Stage only the files referenced by the manifests, sign the payloads first, then the application manifest, then the deployment manifest, and finally the bootstrapper. | ||
| 1. After each signing stage, refresh manifest metadata so hashes, sizes, and entry-point information are consistent with the newly signed bits. |
There was a problem hiding this comment.
Curious is there are plans to make the whole operation atomic where if any one task fails, none of the files are signed or if signing proceeds until one failure occurs, leaving some files signed and other unsigned.
|
|
||
| ### Rollout strategy | ||
|
|
||
| The new ClickOnce signing algorithm is **opt-in**. Users must pass the `--use-new-clickonce-signing` flag to enable the proposed behavior. Without this flag, Sign CLI continues to use the current algorithm described in Appendix A. |
There was a problem hiding this comment.
Given that we are still in the pre-release phase for SignCLI, I think breaking changes might be okay until the major release. I am proposing new behavior by default have a different option or an environment variable to fall back to the current behavior.
See #842.
This PR adds a specification for changes to the ClickOnce signing algorithm. The goal is to make ClickOnce signing simpler, more correct, more efficient, and easier to maintain over time.
Rendered view: https://github.com/dotnet/sign/blob/cee18cb08d824564dd087974d00d11dde0fa2972/docs/specs/ClickOnce-Signing-Algorithm.md
(The rendered view is best viewed in light mode, because the animated GIF, which you can see clearly here, does not display well in dark mode.)