Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: cmd/internal/codesign: Extend mach-O codesigning with entitlements #59522

Open
oxisto opened this issue Apr 10, 2023 · 8 comments · May be fixed by #59611
Open

proposal: cmd/internal/codesign: Extend mach-O codesigning with entitlements #59522

oxisto opened this issue Apr 10, 2023 · 8 comments · May be fixed by #59611
Labels
Milestone

Comments

@oxisto
Copy link
Contributor

oxisto commented Apr 10, 2023

Hi everyone,

Not sure if this is would actually need to be a proposal, since it only changes an internal API but I would like to extend the functionality of the cmd/internal/codesign package. Currently, it only performs basic codesigning of (macOS) mach-O binaries. However, on macOS, the code signing process also includes additional meta-data, for example so called entitlements. I would like to extent the currently code signing code to make it possible to create Go binaries with entititlements (and possibly other code signing features).

One could argue, that for such use-cases codesign should or can be used. While this is true, there are two points that speak in favour:

  1. The Go pipeline is already there; so why not extend it to include more advanced features? The code signing process seemed pretty stable over the last years, so not much maintenance should be expected
  2. While you can use codesign in the final steps of preparing an executable, it is cumbersome to use in go test. A good example for such a workaround is the current way tests are working in delve for the (slightly broken) native Go frontend. An external Go script is compiling the test binary and signs it with codesign, making in-place debugging very hard.

I already made myself familiar with the code in cmd/internal/codesign and would like to implement these changes in a PR.

I have not yet discussed how to actually read the entitlements (maybe from an ENV?), I would like to focus on extending the code sign functionality first.

@gopherbot gopherbot added this to the Proposal milestone Apr 10, 2023
@prattmic
Copy link
Member

cc @golang/compiler @cherrymui

@prattmic
Copy link
Member

cmd/internal/codesign is an internal package used by the Go command and Go linker. Is it your intention to extend the Go command to allow adding additional entitlements to binaries built through the go command? Or are you using this package in a separate project outside of the go toolchain?

@oxisto
Copy link
Contributor Author

oxisto commented Apr 10, 2023

cmd/internal/codesign is an internal package used by the Go command and Go linker. Is it your intention to extend the Go command to allow adding additional entitlements to binaries built through the go command? Or are you using this package in a separate project outside of the go toolchain?

My intention would be to extend the Go command / linker.

@prattmic
Copy link
Member

Thanks for the clarification. I think that this should stay in the proposal process, as it will need to add flags to the Go toolchain.

@cherrymui
Copy link
Member

Could you propose the command line interface that the user would use? As discussed above, cmd/internal/codesign is an internal ABI and is less important, as long as the implementation is not too complex.

A good example for such a workaround is the current way tests are working in delve for the (slightly broken) native Go frontend.

Could you give more detail about the difficulties in this? That would probably be helpful to design a workflow to solve the user's problem.

Thanks.

@oxisto
Copy link
Contributor Author

oxisto commented Apr 10, 2023

Could you propose the command line interface that the user would use?

I could imagine several ways to do it. Each one has some pros and cons:

Option 1: Linker flag

Adding a linker flag like -entitlements would solve most of the issues I guess. Then we could do something like go test -ldflags="-entitlements file.plist" which would look for the plist file and embed its content as entitlements.

I am not quite sure, if this would work with go install? But this is maybe less of a priority.

Option 2: Environment variable

This would give us either the option to specify a file or even the XML directly as a GOMACHOENTITLEMENTS variable.

Option 3: Somehow embed entitlements in code

This would be a real nice option, maybe embedding them into a comment somehow, but I fear that this would change too much and would need to tackle other areas of Go that I don't want to touch.

As discussed above, cmd/internal/codesign is an internal ABI and is less important, as long as the implementation is not too complex.

That's good to hear. The initial prototype exploration I did does not seem to complex. Basically, we need to add one more Blob for the entitlement, add additional hashes to the end of the CodeDirectory and adjust sizes/offsets correctly. The tricky part is to actually get the entitlements from the user to the codesign package. At first glance, adding a field like entitlements (or similar) to the Link structure of cmd/link/internal/ld seemed the best way, as all the machoXXX functions can access this.

A good example for such a workaround is the current way tests are working in delve for the (slightly broken) native Go frontend.

Could you give more detail about the difficulties in this? That would probably be helpful to design a workflow to solve the user's problem.

The way it works is basically that delve uses a make.go file that executes a go run test command with the -exec option, which in turn executes a little script that does execute's macOS native codesign + launches the executable. One of the major drawbacks is that this only works in the command-line and not when debugging (e.g. with delve itself and/or vscode). It is also a major workaround.

Similarly, go install also does not work out of the box because as far as I know there is not way to execute the additional codesign command after "installation"/building.

Thanks.

@oxisto
Copy link
Contributor Author

oxisto commented Apr 12, 2023

I have a working prototype of this (at least the core signing, without the interface to the user), I might submit this in the following days and then wait for the proposal decision. We still need to work out which of the options discussed above would work best then.

oxisto added a commit to oxisto/go that referenced this issue Apr 13, 2023
This CL adds support for embedding entitlements in mach-o executables
during the codesigning process. Entitlements are used on macOS to grant
additional rights to the executable. This can be useful for example when
performing system-near tasks, such as writing a debugger in Go. Previously,
the codesign binary was needed as an additional step to embedd entitlements
into Go binaries.

With this CL, a new ldflag `-entitlements` is introduced. If provided, it
specifies the location of a entitlements file in XML (property list format).
This file is then used in the code signing process.

Furthermore, the codesign package was slightly cleaned up and designed a bit
more modular, so that additional blobs used for signing, such as requirements,
could be added in the future.

Fixes golang#59522
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/484495 mentions this issue: cmd/internal/codesign: Support embedding entitlements on mach-o

oxisto added a commit to oxisto/go that referenced this issue Apr 13, 2023
This CL adds support for embedding entitlements in mach-o executables
during the codesigning process. Entitlements are used on macOS to grant
additional rights to the executable. This can be useful for example when
performing system-near tasks, such as writing a debugger in Go. Previously,
the codesign binary was needed as an additional step to embedd entitlements
into Go binaries.

With this CL, a new ldflag `-entitlements` is introduced. If provided, it
specifies the location of a entitlements file in XML (property list format).
This file is then used in the code signing process.

Furthermore, the codesign package was slightly cleaned up and designed a bit
more modular, so that additional blobs used for signing, such as requirements,
could be added in the future.

Fixes golang#59522
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Incoming
Development

Successfully merging a pull request may close this issue.

4 participants