We were inconsistent throughout the codebase and would sometimes
use the slices package and other times use our own equivalents
in api/.
This removes our versions in favor of the golang.org/x package that
does the same, which has the added benefit of reducing the surface
area of the public API module.
Note: despite existing uses of the slices package, for some reason
it didn't show up in go.mod or go.sum. Fixed that too.
Update `duo-labs/webauthn` up to `20220122034320`, which is the latest version
we can get without dipping into dependency hell (`etcd` and `opentelemetry` woes
ensue after [2365c59d9f][1]).
`tstranex` could be dropped for a while now (we moved on to WebAuthn-like
interfaces for mocks). `cfssl` was only imported due to what I assume was an
IDE mishap.
I've elected to keep `fxamacker/cbor`, instead of trying to move to
[webauthncbor][2]. fxamacker is solid, past v0, seems more appropriate for
client-side libs and still backs webauthncbor.
There are no updates for `flynn/hid` and `flynn/u2f`.
Release notes for fxamacker/cbor:
https://github.com/fxamacker/cbor/releases/tag/v2.4.0.
[1]: https://github.com/duo-labs/webauthn/commit/2365c59d9fb666cb5f5b6bbae86910632198a8d4
[2]: https://pkg.go.dev/github.com/duo-labs/webauthn@v0.0.0-20220815211337-00c9fb5711f5/protocol/webauthncbor
* Drop tstranex/u2f dependency
* Drop direct dependency to cloudflare/cfssl
* Update fxamacker/cbor/v2 to v2.4.0
* Update duo-labs/webauthn to 2022-01-22
* Fix: Make sure all credentials are set in the user
* Simplify: Drop now unnecessary AuthenticationSelection copy
Update metalinter, fix a few lint warnings and replace deprecated linters.
`deadcode`, `structcheck` and `varcheck` are abandoned and now replaced by [`unused`][1].
Since 1.19, `go fmt` reformats godocs according to https://go.dev/doc/comment. I've done a bulk-reformatting of the codebase to keep the linter happy. Backporting is mostly harmless (the exception being `lib/services/role_test.go`, that for some reason breaks the _old_ linter using the new format).
[1]: https://golangci-lint.run/usage/linters/
* Bump golangci-lint version
* Replace abandoned linters
* Fix bodyclose on lib/auth/github.com
* Fix bodyclose on lib/kube/proxy/streamproto/proto_test.go
* Fix bodyclose on lib/srv/alpnproxy/proxy_test.go
* Fix bodyclose on lib/web/conn_upgrade_test.go
* Silence staticcheck on lib/kube/proxy/forwarder_test.go
* Silence staticcheck on lib/utils/certs_test.go
* Address BuildNameToCertificate deprecation warnings
* Run `go fmt ./...`
* Run `go fmt ./...` on api/
* Ignore formatting in role_test.go
* Remove redundant initializers in lib/srv/uacc/
* Update e/
* Update api/types/fuzz_test.go
* do not fail if the file is missing
* missing go-118-fuzz-build fix
Co-authored-by: Zac Bergquist <zac.bergquist@goteleport.com>
* Allow register passwordless on invite/reset
* Specify the type of device usage when registering new device
* Minor refactoring to reduce number of parameters to funcs
* Check if device register requested pwdless, response is pwdless capable
Passwordless login is enabled by the global `--pwdless` flag. Registration gets
a new prompt and an `--allow-passwordless` flag.
UX messages were tweaked to follow the descriptions on RFD 53: Passwordless
FIDO2[1].
Passwordless login requires two touches for all devices (both PIN and biometric).
I'd like to get it down to a single touch, at least for the most common
situations, but that'll be a follow up to this work.
Passwordless support requires `tsh` to be compiled with the `libfido2` tag, try
`go build -tags=libfido2 ./tool/tsh`.
#9160
[1] https://github.com/gravitational/teleport/blob/master/rfd/0053-passwordless-fido2.md#ux
* Allow reuse of devices for passwordless
* Implement passwordless registration in tsh
* Add better tracing to FIDO2 filters
* Implement passwordless logins in tsh
* Make --pwdless a global flag
* Fix lint errors
* Fix U2F tests
* Use initClient's URL as origin
* Distinguish whether --allow-passwordless is set or unset
Alias the "u2f" second factor mode to "webauthn", effectively sunsetting U2F in
favor of WebAuthn.
The change effectively disables "U2F mode" server-side, making Teleport use
WebAuthn instead. This is in line with our compatibility promise, as Teleport
8.x clients are already WebAuthn-capable (and thus have no problems talking to
the cluster).
I have cleaned up a good chunk of U2F references in lib/web and lib/client, plus
a few other places. Changes on lib/auth are just the necessary to get the tests
back to good standing. There is more work to be done, but this seems enough for
a single PR.
#10375
* Remove "Disabled" field from types.Webauthn
* Update generated protos
* Treat second_factor "u2f" as "webauthn"
* Remove references to Webauthn.Disabled
* Remove U2F from lib/web/
* Remove U2F from lib/client/
* Remove U2F from lib/auth/ (partially)
* Fix issues after rebase on master
* Fix typo
I've opted to keep MFA and passwordless authorization interfaces separate, as
they have slight interface differences, storage needs, and allow for different
use-cases.
LoginFlow, the existing API, is now focused on MFA. A new type,
PasswordlessFlow, provides support for passwordless authorization. Both
implementations are backed by a private loginFlow type, refactored from the guts
of the old LoginFlow, which is a superset of MFA and Passwordless.
All registration use-cases are provided by the existing RegistrationFlow. In
this case the change is simpler, as a single passwordless parameter suffices.
Registration is always performed by a previously-authorized user, so it's
storage interactions remain uniform.
Finally, login methods won't create a WebAuthn ID anymore, instead they rely on
registration to do it. The simplification relies on the fact that user handles
are not mandatory. (They do matter for resident key registration, which does
provide them.)
#9160
* Add verification support to mocku2f
* Support passwordless login on lib/auth/webauthn
* Support passwordless registration on lib/auth/webauthn
* Refactor web ID creation
The default user verification setting, "preferred", leaves it open for
client-side implementations whether to to perform verification checks.
In theory it sounds reasonable, but in practice it takes a variety of
forms: Chrome will perform PIN checks if a PIN is configured, a
redundant check in face of our existing password checks. Windows goes a
step further and directs user to set a PIN, a further deviation from the
usual security key workflow.
The traditional workflow is achieved by setting user verification to
discouraged, implemented here.
Reference:
- https://chromium.googlesource.com/chromium/src/+/refs/heads/main/content/browser/webauth/uv_preferred.md
* Set user verification to "discouraged" for WebAuthn
* Add user verification to CredentialAssertion proto
* Add authenticator selection to CredentialCreation proto
Proto conversions are more likely to have nils due to message nesting.
The non-proto structs we use here tend to not have pointer-to-struct attributes,
so in most cases only a top-level check suffices.
* Do careful nil handling on Webauthn proto conversions
* Use require.NotPanics
This is a collection of a few small changes related to user presentation of
WebAuthn/MFA in tsh. The intent is to make tsh language match ongoing Web UI
changes.
* Make use of preferred MFA in `tsh mfa add`
* Tweak prompt error message
Old:
ERROR: "U2F\n" is not a valid option, please specify one of [TOTP, WEBAUTHN]
New:
ERROR: "U2F" is not a valid option, please specify one of [TOTP, WEBAUTHN]
* Directly mention WebAuthn when prompting for challenges
* Fix typo on godoc
* Print devices sorted by name on `tsh mfa ls`
* Address origin validation TODOs
For registration and a few other use cases the original error is relayed
back to the client, so there is already a good indicator that it failed
due to origin woes.
For login we purposefully obsfucate errors. To address that I've added a
few debug-level server-side log statements; it seems best to not make
further changes in this case.
* Amend preferred device type logic
* Adjust PromptMFAChallenge message
Attestation allows Teleport admins a manner of control over the devices used for
MFA.
Attestation support for Webauthn works similarly to U2F attestation, but
provides both allow and deny lists for device CAs. The device's attestation
certificate must clear both lists before registration is complete.
Previously-registered devices are not affected (similarly to U2F).
* Better error messages on webauthn/httpserver
* Make mocku2f attestation cert public
* Implement attestation for Webauthn
Replaces the local device type in AddMFADeviceRequestInit for a global enum.
Useful for future RPCs.
* Add the DeviceType proto to Auth Service
* Generate protos
* Use new DeviceType in implementations
Simplify MFA testing by using (mostly a single code path to register and
authenticate MFA devices.
I've hunt down and changed a good chunk of tests, all the while prioritizing
Webauthn over U2F where the latter is not hard requirement, as this alleviates
the required changes when U2F is deprecated.
* Simplify creation of test MFA devices
* Apply RegisterTestDevice to login tests
* Apply RegisterTestDevice to account recovery tests
* Replace insertDummyDevice with RegisterTestDevice
* Use configureForMFA in TestCreateResetPasswordToken
* Apply RegisterTestDevice in Web tests
* Add a TODO for proto.DeviceType
* Fix lint errors
* Fix account recovery test breakage
The toy interface serves a few purposes:
Easy testing of Webauthn login and of interop between CLI and Web
Reference for the actual Web UI implementation
* Add a toy Webauthn web interface
* Use the device type to decide whether to use the App ID
* Small tweaks in server and Js
* Fix webauthncli TestLogin breakage
* Replace Printf with Println
Address a couple of outstanding TODOs:
* Keep SessionData in memory during registration
A nice to have that allows multiple concurrent registrations, plus it
matches how U2F works today.
* Remove test assertion for RegistrationIdentity
* Refactor authenticateUser to take advantage of validateMFAAuthResponse
Not as big as a gain as I was hoping for (due to password checking on
OTP), but at least we consolidate U2F/Webauthn challenges to a single
place.
* GenerateUserSingleUseCerts checks for Webauthn challenges
Plug Webauthn registration into the *MFADevice RPC family: AddMFADevice,
DeleteMFADevice and GetMFADevices.
As a consequence, Webauthn authentication and registration become supported by
various other gRPC endpoints that defer authn and registration to the RPCs
above.
Further RPC support and refactors are punted to upcoming PRs.
* Add streaming tests for Webauthn
* Add further login/registration failure tests
* Add Webauthn support for streaming RPCs
* Guard against unexpected second factor type in deletion
Add server-side Webauthn registration logic to lib/auth/webauthn.
This allows both U2F and Webauthn-enabled devices to be registered.
* Implement Webauthn registration
* Add clone warning to Webauthn login
* Handle Webauthn devices on login
Since #8176[1] landed, tsh login favors Webauthn challenges over U2F, a behavior
recommended to other clients as well (such as the Web UI). This creates a
problem: until the Webauthn implementation if proven in the wild, if there are
issues with it, then clients could consistently fail login.
This change introduces a fallback for disabling Webauthn regardless of the
cluster's second_factor:on or second_factor:optional setting. By stopping
challenge generation we automatically push clients over to U2F or TOTP as a
fallback, allowing breaking issues to be fixed without impact. (Note that using
second_factor:u2f as a fallback isn't always possible, since it disables OTP as
well.)
The added setting is meant as a safety switch - once Webauthn is proved in the
wild it is to be removed.
This affects both teleport.yaml and cloud resource configs.
teleport.yaml:
```yaml
auth_service:
authentication:
type: local
second_factor: on # or "optional"
u2f: {} # omitted
webauthn:
disabled: true
```
Resource configuration:
```yaml
kind: cluster_auth_preference
version: v2
spec:
type: local
second_factor: on
webauthn:
disabled: true
```
[1] https://github.com/gravitational/teleport/pull/8176
* Add global disable flag for Webauthn
* Generate protos
* Apply Webauthn global disable flag
Implement the device polling loop for Webauthn devices and apply it to
tsh login.
A separate package, lib/auth/webauthncli, is introduced to hold client-focused
Webauthn logic. The separation highlights the distinction between server- and
client-side code and isolates client-side dependencies from the existing
lib/auth/webauthn.
Includes improved test coverage for TeleportClient.Login (local logins only) and
refactoring of existing code to support Webauthn challenges (PromptMFAChallenge
logic has less branching and U2F device loop extracted and refactored into
lib/auth/webauthncli).
In terms of device compatibility, this is identical to the existing U2F
solution- we are using the same underlying libraries and adapting the CTAP1
responses to Webauthn. This is easy to do and easy to reason about. I'm planning
for a native Webauthn solution, such as libfido2, but that is larger change that
doesn't seem to get us all the way to where we want for now (looking at you,
Touch ID).
* Add transformations and validations to lib/auth/webauthn
* Implement client-side Webauthn login
* Use RunOnU2FDevices in the lib/auth/u2f package
This one is optional: it cuts a bit of the codebase today, but one could
argue that it is safer to keep U2F untouched (up to the point where it
gets removed).
* Use CollectedClientData definition in lib/auth/mocku2f
* Fix data race on auth.Server clock usage
* Add direct test for TeleportClient.Login
* Reply to Webauthn challenges on `tsh login`
Allow login using Webauthn instead of U2F.
Installs with second_factor:on will automatically support Webauthn, generating
challenges for any U2F devices and allowing Webauthn to be used throughout the
entire login process.
Web REST API modified as follows:
Added /webapi/mfa/login/begin (1st login step)
Added /webapi/mfa/login/finish (2nd login step, SSH)
Added /webapi/mfa/login/finishsession (2nd login step, web session)
U2F endpoints deprecated, but support full breadth of MFA login options
(/webapi/u2f/signrequest, /webapi/u2f/certs and /webapi/u2f/sessions,
respectively)
Auth REST API modified as follows:
Added /:version/mfa/users/:user/login/begin (1st login step)
ssh/authenticate and web/authenticate now support Webauthn (2nd login step)
U2F endpoints deprecated, but support full breadth of MFA options as well
(/:version/u2f/users/:user/sign)
RFD: https://github.com/gravitational/teleport/pull/7808.
* Plug Webauthn into MFAAuth protos
* Generate protos
* Make CredentialAssertionResponse json-friendly
* Add Webauthn proto conversions
* Wire Webauthn to auth apiserver
* Wire Webauthn login to web apiserver
* Wire Webauthn to web login
* Add missing license headers
* Delete login_identity_test.go
* Use previously acquired devices on mfaAuthChallenge
* Take U2F App ID literally if it's not a proper URL
* Add direct tests for auth.Server
* Use trace.BadParameter consistently
* Include user name in "failed to authenticate" logs
* Add more login-related tests to auth.Server
Adjust lib/auth/webauthn to correctly match Identity methods (interfaces
deviated a little during reviews) and make use of WebauthnLocalAuth to create
and record Webauthn user IDs.
* Adjust lib/auth/webauthn to Identity and configs
* Apply default Webauthn challenge timeout
* Create and make use of Webauthn ID
Add the necessary logic to perform WebAuthn logins/authentication, including
both necessary steps (named "Begin" and "Finish" after the Duo Labs
API/reference implementation).
Note that the login logic is not yet wired to Teleport, that is to come in a
future PR.
Part of the WebAuthn Support[1] work.
[1] https://github.com/gravitational/teleport/pull/7808
* Vendor duo-labs/webauthn and fxamacker/cbor/v2
* Implement the first step of login
* Implement the second step of login
* Add WebAuthn support for mock U2F devices
* Add tests for the complete login flow
* Be explicit about the default attestation value
* Refactor "appid" into a constant
* Add missing license headers