Add controller-led worker auth flow (#2413)
This adds an action to the API that allows pulling out an activation token that can be given to a worker in its config (directly or via env or file). The worker can pass this along with its normal request in place of its normal nonce and the server will automatically accept it. Co-authored-by: Irena Rindos <irenarindos@users.noreply.github.com>
This commit is contained in:
1 parent
a1be125f5b
commit
01fb949d0b
55 files changed
+2728
-625
No files matched your search
@@ -86,7 +86,16 @@ func (w *Worker) controllerDialerFunc(extraAlpnProtos ...string) func(context.Co
|
||||
case w.conf.WorkerAuthKms != nil && !w.conf.DevUsePkiForUpstream:
|
||||
conn, err = w.v1KmsAuthDialFn(ctx, addr, extraAlpnProtos...)
|
||||
default:
|
||||
conn, err = protocol.Dial(ctx, w.WorkerAuthStorage, addr, nodeenrollment.WithWrapper(w.conf.WorkerAuthStorageKms), nodeenrollment.WithExtraAlpnProtos(extraAlpnProtos))
|
||||
conn, err = protocol.Dial(
|
||||
ctx,
|
||||
w.WorkerAuthStorage,
|
||||
addr,
|
||||
nodeenrollment.WithWrapper(w.conf.WorkerAuthStorageKms),
|
||||
nodeenrollment.WithExtraAlpnProtos(extraAlpnProtos),
|
||||
// If the activation token hasn't been populated, this won't do
|
||||
// anything, and it won't do anything if it's already been used
|
||||
nodeenrollment.WithActivationToken(w.conf.RawConfig.Worker.ControllerGeneratedActivationToken),
|
||||
)
|
||||
// No error and a valid connection means the WorkerAuthRegistrationRequest was populated
|
||||
// We can remove the stored workerAuthRequest file
|
||||
if err == nil && conn != nil {
|
||||
@@ -97,13 +106,23 @@ func (w *Worker) controllerDialerFunc(extraAlpnProtos ...string) func(context.Co
|
||||
}
|
||||
}
|
||||
}
|
||||
switch err {
|
||||
case nil:
|
||||
case nodeenrollment.ErrNotAuthorized:
|
||||
// We don't event in this case, because the function retries often
|
||||
// and will spam the logs. The status function will event indicating
|
||||
// that it can't send status because it's not authorized, so that
|
||||
// will be a fine hint to the user as to the issue.
|
||||
switch {
|
||||
case err == nil:
|
||||
// Nothing
|
||||
|
||||
case errors.Is(err, nodeenrollment.ErrNotAuthorized):
|
||||
switch w.conf.RawConfig.Worker.ControllerGeneratedActivationToken {
|
||||
case "":
|
||||
// We don't event in this case, because the function retries
|
||||
// often and will spam the logs while waiting on the user to
|
||||
// transfer the worker-generated request over
|
||||
|
||||
default:
|
||||
// In this case, event, so that the operator can understand that
|
||||
// it was rejected
|
||||
event.WriteError(ctx, op, fmt.Errorf("controller rejected activation token as invalid"))
|
||||
}
|
||||
|
||||
default:
|
||||
event.WriteError(ctx, op, err)
|
||||
}
|
||||
|
||||
@@ -251,6 +251,10 @@ func (w *Worker) Start() error {
|
||||
// the controller, we don't want to invalidate that request on restart
|
||||
// by generating a new set of credentials. However it's safe to output a
|
||||
// new fetch request so we do in fact do that.
|
||||
//
|
||||
// Note that if a controller-generated activation token has been
|
||||
// supplied, we do not output a fetch request; we attempt to use that
|
||||
// directly later.
|
||||
var err error
|
||||
w.WorkerAuthStorage, err = nodeefile.New(w.baseContext,
|
||||
nodeefile.WithBaseDirectory(w.conf.RawConfig.Worker.AuthStoragePath))
|
||||
@@ -311,6 +315,15 @@ func (w *Worker) Start() error {
|
||||
return fmt.Errorf("error loading worker auth creds: %w", err)
|
||||
}
|
||||
|
||||
// Don't output a fetch request if an activation token has been
|
||||
// provided. Technically we _could_ still output a fetch request, and it
|
||||
// would be valid to do so, but if a token was provided it may well be
|
||||
// confusing to a user if it seems like it was ignored because a fetch
|
||||
// request was still output.
|
||||
if actToken := w.conf.RawConfig.Worker.ControllerGeneratedActivationToken; actToken != "" {
|
||||
createFetchRequest = false
|
||||
}
|
||||
|
||||
// NOTE: this block _must_ be before the `if createFetchRequest` block
|
||||
// or the fetch request may have no credentials to work with
|
||||
if createNodeAuthCreds {
|
||||
|
||||
Reference in new issue
Block a user