-
Notifications
You must be signed in to change notification settings - Fork 103
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
add support for collecitng multiple user keys on via secure enclave #1644
add support for collecitng multiple user keys on via secure enclave #1644
Conversation
ses.pathToLauncherBinary = p | ||
} | ||
|
||
return ses, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wonder if we should do some kind of key verification here? we can at least query secure enclave to make sure it recognizes the users key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ehh .. not sure it's worth the extra execs
we don't save a key unless secure enclave creates it
once we store the key server side, if the key is lost some how launcher would need a new install if were strict on validating SE keys
if err != nil { | ||
return nil, fmt.Errorf("marshalling hardware keys: %w", err) | ||
} | ||
results[0]["hardware_key"] = string(jsonBytes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this produces a json array of objects with uid & keys, need to see how K2 handles this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is changes the meaning of the column from prior and makes it different per platform. That's going to be hard to manage inside k2. Instead, I would recommend we move to using hardware_keys
(and hardware_keys_source
) and be consistent consistent across platforms.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressed in #1647
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥 let's try it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good. Mostly nits and questions. I'm a bit ambivalent about the signature changes, but okay.
I think we do need to change how these are exposed to k2. The change in column meaning is hard to support.
// It's available as a separate command because launcher runs as root by default and since it's | ||
// not in a user security context, it can't use the secure enclave directly. However, this command | ||
// can be run in the user context using launchctl. | ||
func runSecureEnclave(args []string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot decide, but we could try to examine the parent process to see if launcher is in there. Though the parent is just going to be sudo, so this may not be feasible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Early on we considered trying to do this, but decided not to since it was easy to spoof ppid. If we're feeling different now and we do go this route, we could even exec codesign and verify that the calling binary is signed as we expect.
// hardware signing is not implemented for darwin | ||
if runtime.GOOS != "darwin" && e.hardwareSigner != nil && e.hardwareSigner.Public() != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why change this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the current state, the signer will not be nil, but will error when sign function is called. So it didn't make sense to me to just let it error.
return nil, fmt.Errorf("creating key: %w", err) | ||
} | ||
|
||
span.AddEvent("new_key_created") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need this? It's somewhat implied by the function name. I guess we're still learning the tools
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like seeing the events when I look at a span, but I can live without them.
@@ -92,6 +92,9 @@ type ExtensionOpts struct { | |||
// RunDifferentialQueriesImmediately allows the client to execute a new query the first time it sees it, | |||
// bypassing the scheduler. | |||
RunDifferentialQueriesImmediately bool | |||
// skipHardwareKeysSetup is a flag to indicate if we should skip setting up hardware keys. | |||
// This is useful for testing environments where we don't have required hardware. | |||
skipHardwareKeysSetup bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that this is explicit, but it does require changing a lot of test filed. Do you think it makes more sense than switching off the environment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ehh, I waffled on this one. It felt worse to have logic in the production code to try and figure out if we were under test.
if err != nil { | ||
return nil, fmt.Errorf("marshalling hardware keys: %w", err) | ||
} | ||
results[0]["hardware_key"] = string(jsonBytes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is changes the meaning of the column from prior and makes it different per platform. That's going to be hard to manage inside k2. Instead, I would recommend we move to using hardware_keys
(and hardware_keys_source
) and be consistent consistent across platforms.
return nil, fmt.Errorf("getting public ecc data from store: %w", err) | ||
} | ||
|
||
if data != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if it's nil? That branch isn't populated. Maybe early return?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't we would gain anything with an early return. With the intention of having key available as soon as possible, were making a call to currentConsoleUserKey
that will get/create keys near bottom of func. We would have to add another line calling this if we early returned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hrm. That's reasonable. But I think points to some lurking need to refactor. Maybe the quick path is to leave a comment, and call it good enough
"err", err, | ||
) | ||
|
||
if err := store.Delete([]byte(PublicEccDataKey)); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's probably correct to delete the key if it's corrupt, but it feels a little odd to do it here in the secureenclavesigner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea it feels a little odd. I though it might be better than switching on errors in the calling function, deciding what to do, then calling new again. Also, since, without some big changes to the way SetUpKeys
works, we have to let secureEnclaveSIgner
handle the saving of new keys. So it kinda made sense to just let it handle the whole storage layer.
opt(ses) | ||
} | ||
|
||
if ses.pathToLauncherBinary == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels a little odd to record this. Why not look at os.Executable
each time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is for testing. If we look at os.Executable in a test, it will have a go test binary and will error out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will leave a comment about this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment left in #1647
"asuser", | ||
u.Uid, | ||
"sudo", | ||
"--preserve-env", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hrm. No idea what the risk is here. It's probably fine, but it's a bit of a yellow flag
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we need this to retain the os variable LAUNCHER_SKIP_UPDATES
, though we could move the cmd to the top of main and bypass the update logic completely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a couple of ways to approach this.
If that's the only one we care about, maybe we could --preserve-env= LAUNCHER_SKIP_UPDATES
.
I think we could also invoke sudo with LAUNCHER_SKIP_UPDATES=true
in the command line. from the man page:
Environment variables to be set for the command may also be passed as options to sudo in the form VAR=value, for example LD_LIBRARY_PATH=/usr/local/pkg/lib.
follow up PR addressing post merge comments here #1647 |
for now this just creates keys, follow on work will implement actual signing