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

webauthn tests p1 #230

Merged
merged 2 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions cmd/keymasterd/2fa_webauthn.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

// RegisterRequest?
func (state *RuntimeState) webauthnBeginRegistration(w http.ResponseWriter, r *http.Request) {
logger.Debugf(3, "top of webauthnBeginRegistration")
state.logger.Debugf(3, "top of webauthnBeginRegistration")
if state.sendFailureToClientIfLocked(w, r) {
return
}
Expand All @@ -47,16 +47,18 @@
if len(pieces) >= 4 {
assumedUser = pieces[3]
} else {
logger.Debugf(1, "webauthnBeginRegistration: bad number of pieces")
state.logger.Debugf(1, "webauthnBeginRegistration: bad number of pieces")

Check warning on line 50 in cmd/keymasterd/2fa_webauthn.go

View check run for this annotation

Codecov / codecov/patch

cmd/keymasterd/2fa_webauthn.go#L50

Added line #L50 was not covered by tests
http.Error(w, "error", http.StatusBadRequest)
return
}
state.logger.Debugf(3, "top of webauthnBeginRegistration: after piece processing ")
// TODO(camilo_viecco1): reorder checks so that simple checks are done before checking user creds
authData, err := state.checkAuth(w, r, state.getRequiredWebUIAuthLevel())
if err != nil {
logger.Debugf(1, "%v", err)
state.logger.Debugf(1, "webauthnBeginRegistration: checkAuth Failed %v", err)

Check warning on line 58 in cmd/keymasterd/2fa_webauthn.go

View check run for this annotation

Codecov / codecov/patch

cmd/keymasterd/2fa_webauthn.go#L58

Added line #L58 was not covered by tests
return
}
state.logger.Debugf(3, "top of webauthnBeginRegistration: after authentication ")
w.(*instrumentedwriter.LoggingWriter).SetUsername(authData.Username)

// Check that they can change other users
Expand All @@ -68,20 +70,21 @@

profile, _, fromCache, err := state.LoadUserProfile(assumedUser)
if err != nil {
logger.Printf("webauthnBeginRegistration: loading profile error: %v", err)
state.logger.Printf("webauthnBeginRegistration: loading profile error: %v", err)

Check warning on line 73 in cmd/keymasterd/2fa_webauthn.go

View check run for this annotation

Codecov / codecov/patch

cmd/keymasterd/2fa_webauthn.go#L73

Added line #L73 was not covered by tests
http.Error(w, "error", http.StatusInternalServerError)
return

}
if fromCache {
logger.Printf("DB is being cached and requesting registration aborting it")
state.logger.Printf("DB is being cached and requesting registration aborting it")

Check warning on line 79 in cmd/keymasterd/2fa_webauthn.go

View check run for this annotation

Codecov / codecov/patch

cmd/keymasterd/2fa_webauthn.go#L79

Added line #L79 was not covered by tests
http.Error(w, "db backend is offline for writes", http.StatusServiceUnavailable)
return
}
state.logger.Debugf(3, "top of webauthnBeginRegistration: after profile loadingn ")

profile.FixupCredential(assumedUser, assumedUser)
logger.Debugf(2, "webauthnBeginRegistration profile=%+v", profile)
logger.Debugf(2, "webauthnBeginRegistration: About to begin BeginRegistration")
state.logger.Debugf(2, "webauthnBeginRegistration profile=%+v", profile)
state.logger.Debugf(2, "webauthnBeginRegistration: About to begin BeginRegistration")
options, sessionData, err := state.webAuthn.BeginRegistration(profile)
if err != nil {
state.logger.Printf("webauthnBeginRegistration: begin login failed %s", err)
Expand Down
97 changes: 97 additions & 0 deletions cmd/keymasterd/2fa_webauthn_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package main

import (
"bytes"
"io"
"net/http"
"os"
"testing"

"github.com/Cloud-Foundations/keymaster/lib/webapi/v0/proto"

"github.com/duo-labs/webauthn/webauthn"
)

func TestWebAuthnRegistrationBegin(t *testing.T) {

state, passwdFile, err := setupValidRuntimeStateSigner(t)
if err != nil {
t.Fatal(err)
}
defer os.Remove(passwdFile.Name()) // clean up

state.Config.Base.AllowedAuthBackendsForWebUI = append(state.Config.Base.AllowedAuthBackendsForWebUI, proto.AuthTypeU2F)

state.signerPublicKeyToKeymasterKeys()

// cviecco -> probablt dont need tempdir
dir, err := os.MkdirTemp("", "example")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir) // clean up
state.Config.Base.DataDirectory = dir
err = initDB(state)
if err != nil {
t.Fatal(err)
}
state.HostIdentity = "testHost"
// end of copy
logger = state.logger

u2fAppID = "https://" + state.HostIdentity // this should include the port...but not needed for this test as we assume 443
state.webAuthn, err = webauthn.New(&webauthn.Config{
RPDisplayName: "Keymaster Server", // Display Name for your site
RPID: state.HostIdentity, // Generally the domain name for your site
RPOrigin: u2fAppID, // The origin URL for WebAuthn requests
// RPIcon: "https://duo.com/logo.png", // Optional icon URL for your site
})
if err != nil {
t.Fatal(err)
}

// end of setup

req, err := http.NewRequest("GET", webAutnRegististerRequestPath+"username", nil)
if err != nil {
t.Fatal(err)
//return nil, err
}
cookieVal, err := state.setNewAuthCookie(nil, "username", AuthTypeU2F)
if err != nil {
t.Fatal(err)
}
authCookie := http.Cookie{Name: authCookieName, Value: cookieVal}
req.AddCookie(&authCookie)

regData, err := checkRequestHandlerCode(req, state.webauthnBeginRegistration, http.StatusOK)
if err != nil {
t.Fatal(err)
}
/*
resultAccessToken := newTOTPPageTemplateData{}
*/
body := regData.Result().Body
var b bytes.Buffer
_, err = io.Copy(&b, body)
if err != nil {
t.Fatal(err)
}
t.Logf("regdata=%s\n", b.String())

/*
err = json.NewDecoder(body).Decode(&resultAccessToken)
if err != nil {
t.Fatal(err)
}
t.Logf("totpDataToken='%+v'", resultAccessToken)
*/

/*
Example post for finalization:
{
"{\"id\":\"_N2M7t9Qe2rwS4asNZ15I4Thd-nkXow6_lyDT6CURM3gD1sAq0FyMnf8NDOARMWMjjNgPfeHpPWP0Q8nkx-v7pNRuR0IwRHkvZeZxaV3Ql3HFigByVOhuB3OCq2em8Ve\",\"rawId\":\"_N2M7t9Qe2rwS4asNZ15I4Thd-nkXow6_lyDT6CURM3gD1sAq0FyMnf8NDOARMWMjjNgPfeHpPWP0Q8nkx-v7pNRuR0IwRHkvZeZxaV3Ql3HFigByVOhuB3OCq2em8Ve\",\"type\":\"public-key\",\"response\":{\"attestationObject\":\"o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjkSZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NBAAADlwAAAAAAAAAAAAAAAAAAAAAAYPzdjO7fUHtq8EuGrDWdeSOE4Xfp5F6MOv5cg0-glETN4A9bAKtBcjJ3_DQzgETFjI4zYD33h6T1j9EPJ5Mfr-6TUbkdCMER5L2XmcWld0JdxxYoAclTobgdzgqtnpvFXqUBAgMmIAEhWCBwm_S46LuncSKubWLGS7236xBQyY-Ptg0dTKpOmddRMCJYIG02ZJischNpyUqMXRdiJfBW2kDmG3TROzKzHHBHmLlp\",\"clientDataJSON\":\"eyJjaGFsbGVuZ2UiOiJlTW1Ca0gxQ05KZzFsbGRQb3ZXQUN6R0pMZUpYRHZndmViUXIycDRxdWNVIiwib3JpZ2luIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6MzM0NDMiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0\"}}": ""
}
*/

}
4 changes: 3 additions & 1 deletion cmd/keymasterd/userProfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

// This function is needed to create a unified view of all webauthn credentials
func (u *userProfile) WebAuthnCredentials() []webauthn.Credential {
logger.Debugf(3, "top of profile.WebAuthnCredentials ")

Check warning on line 36 in cmd/keymasterd/userProfile.go

View check run for this annotation

Codecov / codecov/patch

cmd/keymasterd/userProfile.go#L36

Added line #L36 was not covered by tests
var rvalue []webauthn.Credential
for _, authData := range u.WebauthnData {
if !authData.Enabled {
Expand Down Expand Up @@ -81,6 +82,7 @@

// This function will eventualy also do migration of credential data if needed
func (u *userProfile) FixupCredential(username string, displayname string) {
logger.Debugf(3, "top of profile.FixupCredential ")
if u.DisplayName == "" {
u.DisplayName = displayname
}
Expand All @@ -98,7 +100,7 @@
}
}

/// next are not actually from there... but make it simpler
// next are not actually from there... but make it simpler
func (u *userProfile) AddWebAuthnCredential(cred webauthn.Credential) error {
index := time.Now().Unix()
authData := webauthAuthData{
Expand Down
Loading