From 465a03efcd308d07b2d7a1d0a0494873c7acafc4 Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Fri, 11 Oct 2024 20:15:40 -0700 Subject: [PATCH 01/10] initial dump, server handlers and basic structs --- cmd/keymasterd/app.go | 19 +++++++- cmd/keymasterd/auth_sshcert.go | 78 +++++++++++++++++++++++++++++++ cmd/keymasterd/config.go | 4 ++ go.mod | 73 +++++++++++++++-------------- go.sum | 85 ++++++++++++++++++++++++++++++++++ 5 files changed, 222 insertions(+), 37 deletions(-) create mode 100644 cmd/keymasterd/auth_sshcert.go diff --git a/cmd/keymasterd/app.go b/cmd/keymasterd/app.go index 8a57e045..b3209e56 100644 --- a/cmd/keymasterd/app.go +++ b/cmd/keymasterd/app.go @@ -55,6 +55,7 @@ import ( "github.com/Cloud-Foundations/tricorder/go/tricorder" "github.com/Cloud-Foundations/tricorder/go/tricorder/units" "github.com/cloudflare/cfssl/revoke" + "github.com/cviecco/webauth-sshcert/lib/server/sshcertauth" "github.com/duo-labs/webauthn/webauthn" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -74,6 +75,7 @@ const ( AuthTypeKeymasterX509 AuthTypeWebauthForCLI AuthTypeFIDO2 + AuthTypeKeymasterSSHCert ) const ( @@ -218,6 +220,7 @@ type RuntimeState struct { webAuthn *webauthn.WebAuthn totpLocalRateLimit map[string]totpRateLimitInfo totpLocalTateLimitMutex sync.Mutex + sshCertAuthenticator *sshcertauth.Authenticator logger log.DebugLogger } @@ -714,14 +717,21 @@ func (state *RuntimeState) sendFailureToClientIfLocked(w http.ResponseWriter, r func (state *RuntimeState) setNewAuthCookie(w http.ResponseWriter, username string, authlevel int) (string, error) { + expiration := time.Now().Add(time.Duration(maxAgeSecondsAuthCookie) * + time.Second) + return state.setNewAuthCookieWithExpiration(w, username, authlevel, expiration) +} + +func (state *RuntimeState) setNewAuthCookieWithExpiration(w http.ResponseWriter, + username string, authlevel int, expiration time.Time) (string, error) { cookieVal, err := state.genNewSerializedAuthJWT(username, authlevel, maxAgeSecondsAuthCookie) if err != nil { logger.Println(err) return "", err } - expiration := time.Now().Add(time.Duration(maxAgeSecondsAuthCookie) * - time.Second) + //expiration := time.Now().Add(time.Duration(maxAgeSecondsAuthCookie) * + // time.Second) authCookie := http.Cookie{ Name: authCookieName, Value: cookieVal, @@ -1950,6 +1960,11 @@ func main() { panic("got bad signer ready data") } + err = runtimeState.initialzeSelfSSHCertAuthenticator() + if err != nil { + logger.Fatalf("cannot inialize ssh identities for certauth %s", err) + } + if len(runtimeState.Config.Ldap.LDAPTargetURLs) > 0 && !runtimeState.Config.Ldap.DisablePasswordCache { err = runtimeState.passwordChecker.UpdateStorage(runtimeState) if err != nil { diff --git a/cmd/keymasterd/auth_sshcert.go b/cmd/keymasterd/auth_sshcert.go new file mode 100644 index 00000000..85660c34 --- /dev/null +++ b/cmd/keymasterd/auth_sshcert.go @@ -0,0 +1,78 @@ +package main + +import ( + "encoding/json" + "net/http" + + "github.com/Cloud-Foundations/keymaster/lib/webapi/v0/proto" + "golang.org/x/crypto/ssh" +) + +// Thus function can only be called after all known keymaster public keys +// have been loaded, that is after the server is ready +func (state *RuntimeState) initialzeSelfSSHCertAuthenticator() error { + + // build ssh pubkey list + var sshTrustedKeys []string + for _, pubkey := range state.KeymasterPublicKeys { + sshPubkey, err := ssh.NewPublicKey(pubkey) + if err != nil { + return err + } + authorizedKey := ssh.MarshalAuthorizedKey(sshPubkey) + sshTrustedKeys = append(sshTrustedKeys, string(authorizedKey)) + } + return state.sshCertAuthenticator.UnsafeUpdateCaKeys(sshTrustedKeys) +} + +// CreateChallengeHandler is an example of how to write a handler for +// the path to create the challenge +func (s *RuntimeState) CreateSSHCertAuthChallengeHandler(w http.ResponseWriter, r *http.Request) { + err := s.sshCertAuthenticator.CreateChallengeHandler(w, r) + if err != nil { + // we are assuming bad request + s.logger.Debugf(1, + "CreateSSHCertAuthChallengeHandler: there was an err computing challenge: %s", err) + s.writeFailureResponse(w, r, http.StatusBadRequest, "Invalid Operation") + return + } +} + +func (s *RuntimeState) LoginWithChallengeHandler(w http.ResponseWriter, r *http.Request) { + username, maxAge, userErrString, err := s.sshCertAuthenticator.LoginWithChallenge(r) + if err != nil { + s.logger.Printf("error=%s", err) + errorCode := http.StatusBadRequest + if userErrString == "" { + errorCode = http.StatusInternalServerError + } + //http.Error(w, userErrString, errorCode) + s.writeFailureResponse(w, r, errorCode, userErrString) + return + } + // TODO: make the maxAge the smaller of maxAge and now + 60s + // Make new auth cookie + _, err = s.setNewAuthCookieWithExpiration(w, username, AuthTypeKeymasterSSHCert, maxAge) + if err != nil { + s.writeFailureResponse(w, r, http.StatusInternalServerError, + "error internal") + s.logger.Println(err) + return + } + + returnAcceptType := getPreferredAcceptType(r) + // TODO: The cert backend should depend also on per user preferences. + loginResponse := proto.LoginResponse{Message: "success"} + switch returnAcceptType { + case "text/html": + loginDestination := getLoginDestination(r) + eventNotifier.PublishWebLoginEvent(username) + s.logger.Debugf(0, "redirecting to: %s\n", loginDestination) + http.Redirect(w, r, loginDestination, 302) + default: + // RODO needs eventnotifier? + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(loginResponse) + } + +} diff --git a/cmd/keymasterd/config.go b/cmd/keymasterd/config.go index 6252ca3b..928bb2e9 100644 --- a/cmd/keymasterd/config.go +++ b/cmd/keymasterd/config.go @@ -39,6 +39,7 @@ import ( "github.com/Cloud-Foundations/keymaster/lib/pwauth/ldap" "github.com/Cloud-Foundations/keymaster/lib/server/aws_identity_cert" "github.com/Cloud-Foundations/keymaster/lib/vip" + "github.com/cviecco/webauth-sshcert/lib/server/sshcertauth" "github.com/duo-labs/webauthn/webauthn" "github.com/howeyc/gopass" "golang.org/x/crypto/openpgp" @@ -416,6 +417,9 @@ func loadVerifyConfigFile(configFilename string, runtimeState.vipPushCookie = make(map[string]pushPollTransaction) runtimeState.totpLocalRateLimit = make(map[string]totpRateLimitInfo) + runtimeState.sshCertAuthenticator = sshcertauth.NewAuthenticator( + []string{runtimeState.HostIdentity}, []string{}) + //verify config if len(runtimeState.Config.Base.HostIdentity) > 0 { runtimeState.HostIdentity = runtimeState.Config.Base.HostIdentity diff --git a/go.mod b/go.mod index 2bb895f6..b27a62df 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/Cloud-Foundations/keymaster -go 1.21.0 +go 1.22.0 -toolchain go1.22.3 +toolchain go1.22.6 replace github.com/bearsh/hid v1.3.0 => github.com/bearsh/hid v1.5.0 @@ -11,45 +11,46 @@ require ( github.com/Cloud-Foundations/golib v0.5.0 github.com/Cloud-Foundations/npipe v0.0.0-20191222161149-761e85df1f92 github.com/Cloud-Foundations/tricorder v0.0.0-20191102180116-cf6bbf6d0168 - github.com/aws/aws-sdk-go v1.54.0 - github.com/aws/aws-sdk-go-v2 v1.27.2 - github.com/aws/aws-sdk-go-v2/config v1.27.18 - github.com/aws/aws-sdk-go-v2/service/organizations v1.27.9 - github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 + github.com/aws/aws-sdk-go v1.55.5 + github.com/aws/aws-sdk-go-v2 v1.32.2 + github.com/aws/aws-sdk-go-v2/config v1.27.43 + github.com/aws/aws-sdk-go-v2/service/organizations v1.34.2 + github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 github.com/bearsh/hid v1.5.0 github.com/cloudflare/cfssl v1.6.5 github.com/cviecco/argon2 v0.0.0-20171122181119-1dc43e2eaa99 + github.com/cviecco/webauth-sshcert v0.0.0-20241011234852-c2476e5f6f0f github.com/duo-labs/webauthn v0.0.0-20221205164246-ebaf9b74c6ec github.com/flynn/u2f v0.0.0-20180613185708-15554eb68e5d github.com/foomo/htpasswd v0.0.0-20200116085101-e3a90e78da9c github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef github.com/lib/pq v1.10.9 github.com/marshallbrekka/go-u2fhost v0.0.0-20210111072507-3ccdec8c8105 - github.com/mattn/go-sqlite3 v1.14.22 + github.com/mattn/go-sqlite3 v1.14.24 github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20170819232839-0fbfe93532da github.com/pquerna/otp v1.4.0 - github.com/prometheus/client_golang v1.19.1 + github.com/prometheus/client_golang v1.20.4 github.com/tstranex/u2f v1.0.0 github.com/vjeantet/ldapserver v1.0.1 - golang.org/x/crypto v0.24.0 - golang.org/x/net v0.26.0 - golang.org/x/oauth2 v0.21.0 - golang.org/x/term v0.21.0 + golang.org/x/crypto v0.28.0 + golang.org/x/net v0.30.0 + golang.org/x/oauth2 v0.23.0 + golang.org/x/term v0.25.0 gopkg.in/ldap.v2 v2.5.1 gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v2 v2.4.0 - mvdan.cc/sh/v3 v3.8.0 + mvdan.cc/sh/v3 v3.9.0 ) require ( - dario.cat/mergo v1.0.0 // indirect + dario.cat/mergo v1.0.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/ProtonMail/go-crypto v1.0.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.30.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect - github.com/cloudflare/circl v1.3.9 // indirect - github.com/cyphar/filepath-securejoin v0.2.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect + github.com/cloudflare/circl v1.5.0 // indirect + github.com/cyphar/filepath-securejoin v0.3.4 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect @@ -58,29 +59,31 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/klauspost/compress v1.17.11 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/skeema/knownhosts v1.2.2 // indirect + github.com/skeema/knownhosts v1.3.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) require ( github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.18 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect - github.com/aws/smithy-go v1.20.2 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.41 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect + github.com/aws/smithy-go v1.22.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/boombuler/barcode v1.0.1 // indirect + github.com/boombuler/barcode v1.0.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/dchest/blake2b v1.0.0 // indirect github.com/flynn/hid v0.0.0-20190502022136-f1b9b6cc019a // indirect - github.com/fxamacker/cbor/v2 v2.6.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/google/certificate-transparency-go v1.2.1 // indirect github.com/google/uuid v1.6.0 // indirect @@ -88,12 +91,12 @@ require ( github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.54.0 // indirect + github.com/prometheus/common v0.60.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/x448/float16 v0.8.4 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/time v0.5.0 - google.golang.org/protobuf v1.34.2 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/time v0.7.0 + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect ) diff --git a/go.sum b/go.sum index 0810e96a..ab0a639f 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Cloud-Foundations/Dominator v0.3.4 h1:afpj8nuKj8pXkceizSwzfsUnV9TmEoPBkpLB2XjzXRw= github.com/Cloud-Foundations/Dominator v0.3.4/go.mod h1:AWCsCpke0lOpHROUDe7sJG6IDqtBfCcOWK1KVHYwJHE= @@ -28,36 +30,68 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aws/aws-sdk-go v1.54.0 h1:tGCQ6YS2TepzKtbl+ddXnLIoV8XvWdxMKtuMxdrsa4U= github.com/aws/aws-sdk-go v1.54.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= +github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aws/aws-sdk-go-v2 v1.27.2 h1:pLsTXqX93rimAOZG2FIYraDQstZaaGVVN4tNw65v0h8= github.com/aws/aws-sdk-go-v2 v1.27.2/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= +github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI= +github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= github.com/aws/aws-sdk-go-v2/config v1.27.18 h1:wFvAnwOKKe7QAyIxziwSKjmer9JBMH1vzIL6W+fYuKk= github.com/aws/aws-sdk-go-v2/config v1.27.18/go.mod h1:0xz6cgdX55+kmppvPm2IaKzIXOheGJhAufacPJaXZ7c= +github.com/aws/aws-sdk-go-v2/config v1.27.43 h1:p33fDDihFC390dhhuv8nOmX419wjOSDQRb+USt20RrU= +github.com/aws/aws-sdk-go-v2/config v1.27.43/go.mod h1:pYhbtvg1siOOg8h5an77rXle9tVG8T+BWLWAo7cOukc= github.com/aws/aws-sdk-go-v2/credentials v1.17.18 h1:D/ALDWqK4JdY3OFgA2thcPO1c9aYTT5STS/CvnkqY1c= github.com/aws/aws-sdk-go-v2/credentials v1.17.18/go.mod h1:JuitCWq+F5QGUrmMPsk945rop6bB57jdscu+Glozdnc= +github.com/aws/aws-sdk-go-v2/credentials v1.17.41 h1:7gXo+Axmp+R4Z+AK8YFQO0ZV3L0gizGINCOWxSLY9W8= +github.com/aws/aws-sdk-go-v2/credentials v1.17.41/go.mod h1:u4Eb8d3394YLubphT4jLEwN1rLNq2wFOlT6OuxFwPzU= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 h1:dDgptDO9dxeFkXy+tEgVkzSClHZje/6JkPW5aZyEvrQ= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5/go.mod h1:gjvE2KBUgUQhcv89jqxrIxH9GaKs1JbZzWejj/DaHGA= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 h1:TMH3f/SCAWdNtXXVPPu5D6wrr4G5hI1rAxbcocKfC7Q= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17/go.mod h1:1ZRXLdTpzdJb9fwTMXiLipENRxkGMTn1sfKexGllQCw= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 h1:cy8ahBJuhtM8GTTSyOkfy6WVPV1IE+SS5/wfXUYuulw= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9/go.mod h1:CZBXGLaJnEZI6EVNcPd7a6B5IC5cA/GkRWtu9fp3S6Y= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 h1:UAsR3xA31QGf79WzpG/ixT9FZvQlh5HY1NRqSHBNOCk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21/go.mod h1:JNr43NFf5L9YaG3eKTm7HQzls9J+A9YYcGI5Quh1r2Y= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 h1:A4SYk07ef04+vxZToz9LWvAXl9LW0NClpPpMsi31cz0= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9/go.mod h1:5jJcHuwDagxN+ErjQ3PU3ocf6Ylc/p9x+BLO/+X4iXw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 h1:6jZVETqmYCadGFvrYEQfC5fAQmlo80CeL5psbno6r0s= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21/go.mod h1:1SR0GbLlnN3QUmYaflZNiH1ql+1qrSiB2vwcJ+4UM60= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 h1:o4T+fKxA3gTMcluBNZZXE9DNaMkJuUL1O3mffCUjoJo= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11/go.mod h1:84oZdJ+VjuJKs9v1UTC9NaodRZRseOXCTgku+vQJWR8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0= github.com/aws/aws-sdk-go-v2/service/organizations v1.27.9 h1:KNXacqpLvkK4oAMqSNhG2ETQzrVK4mKETAeNeo+dWyk= github.com/aws/aws-sdk-go-v2/service/organizations v1.27.9/go.mod h1:hcr6lPG6K2l0WiKyu2ag/JrHbiIOUMg3tdNPtpTe+PM= +github.com/aws/aws-sdk-go-v2/service/organizations v1.34.2 h1:ndH1E8olS/rDB+tiUMKj09g0o11PoOLAC+xRFB13bJw= +github.com/aws/aws-sdk-go-v2/service/organizations v1.34.2/go.mod h1:YZvv/wXIgIviYq9P/fQDhoMlzlI89M0D45GnYvIorLk= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.30.0 h1:nqR1mkoDntCpOwdlEfa2pZLiwvQeF4Mi56WzOTyuF/s= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.30.0/go.mod h1:M9TqBwpQ7AC6zu1Yji7vijRliqir7hxjuRcnxIk7jCc= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 h1:Rrqru2wYkKQCS2IM5/JrgKUQIoNTqA6y/iuxkjzxC6M= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2/go.mod h1:QuCURO98Sqee2AXmqDNxKXYFm2OEDAVAPApMqO0Vqnc= github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 h1:gEYM2GSpr4YNWc6hCd5nod4+d4kd9vWIAWrmGuLdlMw= github.com/aws/aws-sdk-go-v2/service/sso v1.20.11/go.mod h1:gVvwPdPNYehHSP9Rs7q27U1EU+3Or2ZpXvzAYJNh63w= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 h1:bSYXVyUzoTHoKalBmwaZxs97HU9DWWI3ehHSAMa7xOk= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.2/go.mod h1:skMqY7JElusiOUjMJMOv1jJsP7YUg7DrhgqZZWuzu1U= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 h1:iXjh3uaH3vsVcnyZX7MqCoCfcyxIrVE9iOQruRaWPrQ= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5/go.mod h1:5ZXesEuy/QcO0WUnt+4sDkxhdXRHTu2yG0uCSH8B6os= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 h1:AhmO1fHINP9vFYUE0LHzCWg/LfUWUF+zFPEcY9QXb7o= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2/go.mod h1:o8aQygT2+MVP0NaV6kbdE1YnnIM8RRVQzoeUH45GOdI= github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF5e2mfxHCg7ZVMYmk= github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 h1:CiS7i0+FUe+/YY1GvIBLLrR/XNGZ4CtM1Ll0XavNuVo= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.2/go.mod h1:HtaiBI8CjYoNVde8arShXb94UbQQi9L4EMr6D+xGBwo= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= +github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bearsh/hid v1.5.0 h1:8ChLlc9Nqmlrla4U0QMHLhb/h1hnVcs2Unjoz7iY+vk= github.com/bearsh/hid v1.5.0/go.mod h1:cs47JobsdK/AHOpD4wgX80i0el+2r/PjZkxrpaJxR84= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -67,7 +101,10 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4= +github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -77,6 +114,8 @@ github.com/cloudflare/cfssl v1.6.5/go.mod h1:Bk1si7sq8h2+yVEDrFJiz3d7Aw+pfjjJSZV github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE= github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= +github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys= +github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -85,8 +124,14 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cviecco/argon2 v0.0.0-20171122181119-1dc43e2eaa99 h1:8co/GRKovq1R4wCidV2GrIf9FQ+2s0bV4IXulkzbkeI= github.com/cviecco/argon2 v0.0.0-20171122181119-1dc43e2eaa99/go.mod h1:bhY/hbDzWD0J/Sr4zDxR9WaRilSZ06n+qMzGWUjU6yQ= +github.com/cviecco/webauth-sshcert v0.0.0-20241002165410-bee0202d04f5 h1:Hb8wwfZcVLcu6FyQcuSReIQ2ApyT3Zli/zufi2vS3BQ= +github.com/cviecco/webauth-sshcert v0.0.0-20241002165410-bee0202d04f5/go.mod h1:tGQETMLmW4RLPTrbxq21h1iNeJLQ3xM0m5DtQhrWUCQ= +github.com/cviecco/webauth-sshcert v0.0.0-20241011234852-c2476e5f6f0f h1:tIOpxFgFSk3KXAVTUSvBt+kLrGSJI0JJS8ZBF3uXAEU= +github.com/cviecco/webauth-sshcert v0.0.0-20241011234852-c2476e5f6f0f/go.mod h1:tGQETMLmW4RLPTrbxq21h1iNeJLQ3xM0m5DtQhrWUCQ= github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= +github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -113,6 +158,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= @@ -167,6 +214,8 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -186,11 +235,15 @@ github.com/marshallbrekka/go-u2fhost v0.0.0-20210111072507-3ccdec8c8105 h1:Si3VA github.com/marshallbrekka/go-u2fhost v0.0.0-20210111072507-3ccdec8c8105/go.mod h1:VyqGj5jbZtzHO11cS7rkDh/owr/rNCEM98IhQwWvmXg= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= +github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20170819232839-0fbfe93532da h1:qiPWuGGr+1GQE6s9NPSK8iggR/6x/V+0snIoOPYsBgc= github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20170819232839-0fbfe93532da/go.mod h1:DvuJJ/w1Y59rG8UTDxsMk5U+UJXJwuvUgbiJSm9yhX8= @@ -211,6 +264,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= @@ -219,6 +274,8 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8= github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= +github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= +github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= @@ -236,6 +293,8 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= +github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -277,6 +336,10 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -296,9 +359,15 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -326,6 +395,10 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -333,6 +406,10 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -342,9 +419,13 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -359,6 +440,8 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= @@ -387,3 +470,5 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= mvdan.cc/sh/v3 v3.8.0 h1:ZxuJipLZwr/HLbASonmXtcvvC9HXY9d2lXZHnKGjFc8= mvdan.cc/sh/v3 v3.8.0/go.mod h1:w04623xkgBVo7/IUK89E0g8hBykgEpN0vgOj3RJr6MY= +mvdan.cc/sh/v3 v3.9.0 h1:it14fyjCdQUk4jf/aYxLO3FG8jFarR9GzMCtnlvvD7c= +mvdan.cc/sh/v3 v3.9.0/go.mod h1:cdBk8bgoiBI7lSZqK5JhUuq7OB64VQ7fgm85xelw3Nk= From 37f01d3ceda4a2e9b93e534bec8de0c80ce195fd Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Sun, 13 Oct 2024 11:13:52 -0700 Subject: [PATCH 02/10] server side but no tests --- cmd/keymasterd/app.go | 11 +++++++++++ cmd/keymasterd/auth_sshcert.go | 7 +++---- cmd/keymasterd/certgen.go | 5 +++++ lib/webapi/v0/proto/api.go | 1 + 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/cmd/keymasterd/app.go b/cmd/keymasterd/app.go index b3209e56..4ca38153 100644 --- a/cmd/keymasterd/app.go +++ b/cmd/keymasterd/app.go @@ -1790,6 +1790,11 @@ func main() { os.Exit(1) } logger.Debugf(3, "After load verify") + startServerAfterLoad(runtimeState, realLogger) +} + +func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.Logger) { + var err error publicLogs := runtimeState.Config.Base.PublicLogs adminDashboard := newAdminDashboard(realLogger, publicLogs) @@ -1909,6 +1914,12 @@ func main() { serviceMux.HandleFunc(paths.VerifyAuthToken, runtimeState.VerifyAuthTokenHandler) } + // TODO: only enable these handlers if sshcertauth is enabled + serviceMux.HandleFunc(sshcertauth.DefaultCreateChallengePath, + runtimeState.sshCertAuthCreateChallengeHandler) + serviceMux.HandleFunc(sshcertauth.DefaultLoginWithChallengePath, + runtimeState.sshCertAuthLoginWithChallengeHandler) + serviceMux.HandleFunc("/", runtimeState.defaultPathHandler) cfg := &tls.Config{ diff --git a/cmd/keymasterd/auth_sshcert.go b/cmd/keymasterd/auth_sshcert.go index 85660c34..b13dc661 100644 --- a/cmd/keymasterd/auth_sshcert.go +++ b/cmd/keymasterd/auth_sshcert.go @@ -27,7 +27,8 @@ func (state *RuntimeState) initialzeSelfSSHCertAuthenticator() error { // CreateChallengeHandler is an example of how to write a handler for // the path to create the challenge -func (s *RuntimeState) CreateSSHCertAuthChallengeHandler(w http.ResponseWriter, r *http.Request) { +func (s *RuntimeState) sshCertAuthCreateChallengeHandler(w http.ResponseWriter, r *http.Request) { + // TODO: add some rate limiting err := s.sshCertAuthenticator.CreateChallengeHandler(w, r) if err != nil { // we are assuming bad request @@ -38,7 +39,7 @@ func (s *RuntimeState) CreateSSHCertAuthChallengeHandler(w http.ResponseWriter, } } -func (s *RuntimeState) LoginWithChallengeHandler(w http.ResponseWriter, r *http.Request) { +func (s *RuntimeState) sshCertAuthLoginWithChallengeHandler(w http.ResponseWriter, r *http.Request) { username, maxAge, userErrString, err := s.sshCertAuthenticator.LoginWithChallenge(r) if err != nil { s.logger.Printf("error=%s", err) @@ -46,7 +47,6 @@ func (s *RuntimeState) LoginWithChallengeHandler(w http.ResponseWriter, r *http. if userErrString == "" { errorCode = http.StatusInternalServerError } - //http.Error(w, userErrString, errorCode) s.writeFailureResponse(w, r, errorCode, userErrString) return } @@ -74,5 +74,4 @@ func (s *RuntimeState) LoginWithChallengeHandler(w http.ResponseWriter, r *http. w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(loginResponse) } - } diff --git a/cmd/keymasterd/certgen.go b/cmd/keymasterd/certgen.go index 98886781..6561542b 100644 --- a/cmd/keymasterd/certgen.go +++ b/cmd/keymasterd/certgen.go @@ -100,6 +100,11 @@ func (state *RuntimeState) certGenHandler(w http.ResponseWriter, r *http.Request AuthTypeWebauthForCLI) { sufficientAuthLevel = true } + if certPref == proto.AuthTypeSSHCert && + ((authData.AuthType & AuthTypeKeymasterSSHCert) == + AuthTypeKeymasterSSHCert) { + sufficientAuthLevel = true + } } // if you have u2f you can always get the cert if (authData.AuthType & AuthTypeU2F) == AuthTypeU2F { diff --git a/lib/webapi/v0/proto/api.go b/lib/webapi/v0/proto/api.go index 8e6f5a06..2fc23a1e 100644 --- a/lib/webapi/v0/proto/api.go +++ b/lib/webapi/v0/proto/api.go @@ -12,6 +12,7 @@ const ( AuthTypeOkta2FA = "Okta2FA" AuthTypeBootstrapOTP = "BootstrapOTP" AuthTypeWebauthForCLI = "WebauthForCLI" + AuthTypeSSHCert = "SSHCertificate" ) type LoginResponse struct { From 32c3d093ed2beba3745e6c340fcd0f069737a4cf Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Sun, 13 Oct 2024 18:22:43 -0700 Subject: [PATCH 03/10] first set of tests, the easy ones --- cmd/keymasterd/auth_sshcert_test.go | 57 +++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 cmd/keymasterd/auth_sshcert_test.go diff --git a/cmd/keymasterd/auth_sshcert_test.go b/cmd/keymasterd/auth_sshcert_test.go new file mode 100644 index 00000000..ef311f92 --- /dev/null +++ b/cmd/keymasterd/auth_sshcert_test.go @@ -0,0 +1,57 @@ +package main + +import ( + "net/http" + "os" + "testing" + + "github.com/cviecco/webauth-sshcert/lib/server/sshcertauth" +) + +func TestInitializeSSHAuthenticator(t *testing.T) { + state, passwdFile, err := setupValidRuntimeStateSigner(t) + if err != nil { + t.Fatal(err) + } + defer os.Remove(passwdFile.Name()) // clean up + state.sshCertAuthenticator = sshcertauth.NewAuthenticator( + []string{state.HostIdentity}, []string{}) + err = state.initialzeSelfSSHCertAuthenticator() + if err != nil { + t.Fatal(err) + } +} + +func TestSshCertAuthCreateChallengeHandlert(t *testing.T) { + state, passwdFile, err := setupValidRuntimeStateSigner(t) + if err != nil { + t.Fatal(err) + } + defer os.Remove(passwdFile.Name()) // clean up + state.sshCertAuthenticator = sshcertauth.NewAuthenticator( + []string{state.HostIdentity}, []string{}) + err = state.initialzeSelfSSHCertAuthenticator() + if err != nil { + t.Fatal(err) + } + // make call with bad data + //initially the request should fail for lack of preconditions + req, err := http.NewRequest("POST", redirectPath, nil) + if err != nil { + t.Fatal(err) + } + // oath2 config is invalid + _, err = checkRequestHandlerCode(req, state.sshCertAuthCreateChallengeHandler, http.StatusBadRequest) + if err != nil { + t.Fatal(err) + } + // simulaet good call, ignore result for now + goodURL := "foobar?nonce1=12345678901234567890123456789" + // TODO: replce this for a post + req2, err := http.NewRequest("GET", goodURL, nil) + _, err = checkRequestHandlerCode(req2, state.sshCertAuthCreateChallengeHandler, http.StatusOK) + if err != nil { + t.Fatal(err) + } + +} From 47cdbc2c59d4058c193bbcd1e17bb33d8e9aab46 Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Thu, 17 Oct 2024 14:49:41 -0700 Subject: [PATCH 04/10] add tests to develop branch --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cb4ccc7b..3d83ac1e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -14,10 +14,10 @@ name: "CodeQL" on: push: - branches: [ master ] + branches: [ 'master', 'develop' ] pull_request: # The branches below must be a subset of the branches above - branches: [ master ] + branches: [ 'master', 'develop' ] schedule: - cron: '32 14 * * 5' From 2aa533d4d0b39377f3bf8ea9beefb6dc3d4d97e3 Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Thu, 17 Oct 2024 16:04:27 -0700 Subject: [PATCH 05/10] cleanup --- cmd/keymasterd/auth_sshcert.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/cmd/keymasterd/auth_sshcert.go b/cmd/keymasterd/auth_sshcert.go index b13dc661..532a8573 100644 --- a/cmd/keymasterd/auth_sshcert.go +++ b/cmd/keymasterd/auth_sshcert.go @@ -60,18 +60,9 @@ func (s *RuntimeState) sshCertAuthLoginWithChallengeHandler(w http.ResponseWrite return } - returnAcceptType := getPreferredAcceptType(r) // TODO: The cert backend should depend also on per user preferences. loginResponse := proto.LoginResponse{Message: "success"} - switch returnAcceptType { - case "text/html": - loginDestination := getLoginDestination(r) - eventNotifier.PublishWebLoginEvent(username) - s.logger.Debugf(0, "redirecting to: %s\n", loginDestination) - http.Redirect(w, r, loginDestination, 302) - default: - // RODO needs eventnotifier? - w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(loginResponse) - } + // TODO needs eventnotifier? + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(loginResponse) } From e480b72b8c3ddb7459d4ae868ebb98d1508a15d9 Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Thu, 17 Oct 2024 16:09:39 -0700 Subject: [PATCH 06/10] forgot removal --- cmd/keymasterd/app.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/keymasterd/app.go b/cmd/keymasterd/app.go index 80770b24..804767aa 100644 --- a/cmd/keymasterd/app.go +++ b/cmd/keymasterd/app.go @@ -732,8 +732,6 @@ func (state *RuntimeState) setNewAuthCookieWithExpiration(w http.ResponseWriter, logger.Println(err) return "", err } - //expiration := time.Now().Add(time.Duration(maxAgeSecondsAuthCookie) * - // time.Second) authCookie := http.Cookie{ Name: authCookieName, Value: cookieVal, From e8dc19accb2834fc5bf3a0f526d9f9b9001afa2a Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Mon, 21 Oct 2024 11:26:32 -0700 Subject: [PATCH 07/10] enhance testing --- cmd/keymasterd/app.go | 39 +++++++++++++++++++---------- cmd/keymasterd/auth_oauth2_test.go | 13 +++++++--- cmd/keymasterd/auth_sshcert.go | 9 +++++++ cmd/keymasterd/auth_sshcert_test.go | 25 ++++++++++++++++++ 4 files changed, 69 insertions(+), 17 deletions(-) diff --git a/cmd/keymasterd/app.go b/cmd/keymasterd/app.go index 804767aa..b86284f8 100644 --- a/cmd/keymasterd/app.go +++ b/cmd/keymasterd/app.go @@ -223,6 +223,10 @@ type RuntimeState struct { totpLocalRateLimit map[string]totpRateLimitInfo totpLocalTateLimitMutex sync.Mutex sshCertAuthenticator *sshcertauth.Authenticator + serviceMux *http.ServeMux + serviceAccessLogger *serverlogger.Logger + adminAccessLogger *serverlogger.Logger + adminDashboard *adminDashboardType logger log.DebugLogger } @@ -1827,32 +1831,34 @@ func main() { } logger.Debugf(3, "After load verify") startServerAfterLoad(runtimeState, realLogger) + logger.Debugf(3, "After server initbase") + startListenersAndWaitForUnsealing(runtimeState) } func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.Logger) { var err error publicLogs := runtimeState.Config.Base.PublicLogs - adminDashboard := newAdminDashboard(realLogger, publicLogs) + runtimeState.adminDashboard = newAdminDashboard(realLogger, publicLogs) logBufOptions := logbuf.GetStandardOptions() accessLogDirectory := filepath.Join(logBufOptions.Directory, "access") logger.Debugf(1, "accesslogdir=%s\n", accessLogDirectory) - serviceAccessLogger := serverlogger.NewWithOptions("access", + runtimeState.serviceAccessLogger = serverlogger.NewWithOptions("access", logbuf.Options{MaxFileSize: 10 << 20, Quota: 100 << 20, MaxBufferLines: 100, Directory: accessLogDirectory}, stdlog.LstdFlags) adminAccesLogDirectory := filepath.Join(logBufOptions.Directory, "access-admin") - adminAccessLogger := serverlogger.NewWithOptions("access-admin", + runtimeState.adminAccessLogger = serverlogger.NewWithOptions("access-admin", logbuf.Options{MaxFileSize: 10 << 20, Quota: 100 << 20, MaxBufferLines: 100, Directory: adminAccesLogDirectory}, stdlog.LstdFlags) // Expose the registered metrics via HTTP. - http.Handle("/", adminDashboard) + http.Handle("/", runtimeState.adminDashboard) http.Handle("/prometheus_metrics", promhttp.Handler()) //lint:ignore SA1019 TODO: newer prometheus handler http.HandleFunc(secretInjectorPath, runtimeState.secretInjectorHandler) http.HandleFunc(readyzPath, runtimeState.readyzHandler) @@ -1951,12 +1957,19 @@ func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.L runtimeState.VerifyAuthTokenHandler) } // TODO: only enable these handlers if sshcertauth is enabled - serviceMux.HandleFunc(sshcertauth.DefaultCreateChallengePath, - runtimeState.sshCertAuthCreateChallengeHandler) - serviceMux.HandleFunc(sshcertauth.DefaultLoginWithChallengePath, - runtimeState.sshCertAuthLoginWithChallengeHandler) - + if runtimeState.isSelfSSHCertAuthenticatorEnabled() { + serviceMux.HandleFunc(sshcertauth.DefaultCreateChallengePath, + runtimeState.sshCertAuthCreateChallengeHandler) + serviceMux.HandleFunc(sshcertauth.DefaultLoginWithChallengePath, + runtimeState.sshCertAuthLoginWithChallengeHandler) + } serviceMux.HandleFunc("/", runtimeState.defaultPathHandler) + runtimeState.serviceMux = serviceMux +} + +func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) { + var err error + publicLogs := runtimeState.Config.Base.PublicLogs cfg := &tls.Config{ ClientCAs: runtimeState.ClientCAPool, @@ -1976,8 +1989,8 @@ func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.L } logFilterHandler := NewLogFilterHandler(http.DefaultServeMux, publicLogs, runtimeState) - serviceHTTPLogger := httpLogger{AccessLogger: serviceAccessLogger} - adminHTTPLogger := httpLogger{AccessLogger: adminAccessLogger} + serviceHTTPLogger := httpLogger{AccessLogger: runtimeState.serviceAccessLogger} + adminHTTPLogger := httpLogger{AccessLogger: runtimeState.adminAccessLogger} adminSrv := &http.Server{ Addr: runtimeState.Config.Base.AdminAddress, TLSConfig: cfg, @@ -2050,7 +2063,7 @@ func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.L } serviceSrv := &http.Server{ Addr: runtimeState.Config.Base.HttpAddress, - Handler: instrumentedwriter.NewLoggingHandler(serviceMux, serviceHTTPLogger), + Handler: instrumentedwriter.NewLoggingHandler(runtimeState.serviceMux, serviceHTTPLogger), TLSConfig: serviceTLSConfig, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, @@ -2061,7 +2074,7 @@ func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.L go func() { time.Sleep(time.Millisecond * 10) healthserver.SetReady() - adminDashboard.setReady() + runtimeState.adminDashboard.setReady() }() err = serviceSrv.ListenAndServeTLS("", "") if err != nil { diff --git a/cmd/keymasterd/auth_oauth2_test.go b/cmd/keymasterd/auth_oauth2_test.go index 649d177b..6bad957d 100644 --- a/cmd/keymasterd/auth_oauth2_test.go +++ b/cmd/keymasterd/auth_oauth2_test.go @@ -67,11 +67,16 @@ func init() { //logger = stdlog.New(os.Stderr, "", stdlog.LstdFlags) slogger := stdlog.New(os.Stderr, "", stdlog.LstdFlags) logger = debuglogger.New(slogger) - http.HandleFunc("/userinfo", userinfoHandler) - http.HandleFunc("/token", tokenHandler) - http.HandleFunc("/", handler) + testMux := http.NewServeMux() + testMux.HandleFunc("/userinfo", userinfoHandler) + testMux.HandleFunc("/token", tokenHandler) + testMux.HandleFunc("/", handler) + testServer := http.Server{ + Handler: testMux, + Addr: "127.0.0.1:12345", + } logger.Printf("about to start server") - go http.ListenAndServe("127.0.0.1:12345", nil) + go testServer.ListenAndServe() time.Sleep(20 * time.Millisecond) _, err := http.Get("http://localhost:12345") if err != nil { diff --git a/cmd/keymasterd/auth_sshcert.go b/cmd/keymasterd/auth_sshcert.go index 532a8573..03b561f7 100644 --- a/cmd/keymasterd/auth_sshcert.go +++ b/cmd/keymasterd/auth_sshcert.go @@ -25,6 +25,15 @@ func (state *RuntimeState) initialzeSelfSSHCertAuthenticator() error { return state.sshCertAuthenticator.UnsafeUpdateCaKeys(sshTrustedKeys) } +func (state *RuntimeState) isSelfSSHCertAuthenticatorEnabled() bool { + for _, certPref := range state.Config.Base.AllowedAuthBackendsForCerts { + if certPref == proto.AuthTypeSSHCert { + return true + } + } + return false +} + // CreateChallengeHandler is an example of how to write a handler for // the path to create the challenge func (s *RuntimeState) sshCertAuthCreateChallengeHandler(w http.ResponseWriter, r *http.Request) { diff --git a/cmd/keymasterd/auth_sshcert_test.go b/cmd/keymasterd/auth_sshcert_test.go index ef311f92..aa332c29 100644 --- a/cmd/keymasterd/auth_sshcert_test.go +++ b/cmd/keymasterd/auth_sshcert_test.go @@ -5,6 +5,8 @@ import ( "os" "testing" + "github.com/Cloud-Foundations/Dominator/lib/log/serverlogger" + "github.com/Cloud-Foundations/keymaster/lib/webapi/v0/proto" "github.com/cviecco/webauth-sshcert/lib/server/sshcertauth" ) @@ -22,6 +24,17 @@ func TestInitializeSSHAuthenticator(t *testing.T) { } } +func TestIsSelfSSHCertAuthenticatorEnabled(t *testing.T) { + state := RuntimeState{} + if state.isSelfSSHCertAuthenticatorEnabled() { + t.Fatal("it should not be enabled on empty state") + } + state.Config.Base.AllowedAuthBackendsForCerts = append(state.Config.Base.AllowedAuthBackendsForCerts, proto.AuthTypeSSHCert) + if !state.isSelfSSHCertAuthenticatorEnabled() { + t.Fatal("it should be enabled on empty state") + } +} + func TestSshCertAuthCreateChallengeHandlert(t *testing.T) { state, passwdFile, err := setupValidRuntimeStateSigner(t) if err != nil { @@ -53,5 +66,17 @@ func TestSshCertAuthCreateChallengeHandlert(t *testing.T) { if err != nil { t.Fatal(err) } +} + +func TestSshCertAuthLoginWithChallengeHandler(t *testing.T) { + state, passwdFile, err := setupValidRuntimeStateSigner(t) + if err != nil { + t.Fatal(err) + } + defer os.Remove(passwdFile.Name()) // clean up + state.Config.Base.AllowedAuthBackendsForCerts = append(state.Config.Base.AllowedAuthBackendsForCerts, proto.AuthTypeSSHCert) + realLogger := serverlogger.New("") //TODO, we need to find a simulator for this + startServerAfterLoad(state, realLogger) + //TODO: write the actual test, at this point we only have the endpoints initalized } From 999de5c22021bbfb2d827a9bcd12d0f3080b6bb9 Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Thu, 24 Oct 2024 20:27:35 -0700 Subject: [PATCH 08/10] splt services --- cmd/keymasterd/app.go | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/cmd/keymasterd/app.go b/cmd/keymasterd/app.go index b86284f8..e3b8cfe9 100644 --- a/cmd/keymasterd/app.go +++ b/cmd/keymasterd/app.go @@ -224,6 +224,8 @@ type RuntimeState struct { totpLocalTateLimitMutex sync.Mutex sshCertAuthenticator *sshcertauth.Authenticator serviceMux *http.ServeMux + serviceServer *http.Server + adminServer *http.Server serviceAccessLogger *serverlogger.Logger adminAccessLogger *serverlogger.Logger adminDashboard *adminDashboardType @@ -1832,7 +1834,10 @@ func main() { logger.Debugf(3, "After load verify") startServerAfterLoad(runtimeState, realLogger) logger.Debugf(3, "After server initbase") - startListenersAndWaitForUnsealing(runtimeState) + err = startListenersAndWaitForUnsealing(runtimeState) + if err != nil { + panic(err) + } } func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.Logger) { @@ -1967,7 +1972,7 @@ func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.L runtimeState.serviceMux = serviceMux } -func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) { +func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) error { var err error publicLogs := runtimeState.Config.Base.PublicLogs @@ -1991,7 +1996,7 @@ func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) { runtimeState) serviceHTTPLogger := httpLogger{AccessLogger: runtimeState.serviceAccessLogger} adminHTTPLogger := httpLogger{AccessLogger: runtimeState.adminAccessLogger} - adminSrv := &http.Server{ + runtimeState.adminServer = &http.Server{ Addr: runtimeState.Config.Base.AdminAddress, TLSConfig: cfg, Handler: instrumentedwriter.NewLoggingHandler(logFilterHandler, adminHTTPLogger), @@ -2003,8 +2008,8 @@ func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) { &tls.Config{ClientCAs: runtimeState.ClientCAPool, MinVersion: tls.VersionTLS12}, true) go func() { - err := adminSrv.ListenAndServeTLS("", "") - if err != nil { + err := runtimeState.adminServer.ListenAndServeTLS("", "") + if err != nil && err != http.ErrServerClosed { panic(err) } @@ -2017,18 +2022,18 @@ func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) { } isReady := <-runtimeState.SignerIsReady if isReady != true { - panic("got bad signer ready data") + return fmt.Errorf("got bad signer ready data") } err = runtimeState.initialzeSelfSSHCertAuthenticator() if err != nil { - logger.Fatalf("cannot inialize ssh identities for certauth %s", err) + return fmt.Errorf("cannot inialize ssh identities for certauth %s", err) } if len(runtimeState.Config.Ldap.LDAPTargetURLs) > 0 && !runtimeState.Config.Ldap.DisablePasswordCache { err = runtimeState.passwordChecker.UpdateStorage(runtimeState) if err != nil { - logger.Fatalf("Cannot update password checker") + return fmt.Errorf("Cannot update password checker %s", err) } } if runtimeState.ClientCAPool == nil { @@ -2037,7 +2042,7 @@ func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) { for _, derCert := range runtimeState.caCertDer { myCert, err := x509.ParseCertificate(derCert) if err != nil { - panic(err) + return err } runtimeState.ClientCAPool.AddCert(myCert) } @@ -2061,7 +2066,7 @@ func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) { tls.TLS_AES_256_GCM_SHA384, }, } - serviceSrv := &http.Server{ + runtimeState.serviceServer = &http.Server{ Addr: runtimeState.Config.Base.HttpAddress, Handler: instrumentedwriter.NewLoggingHandler(runtimeState.serviceMux, serviceHTTPLogger), TLSConfig: serviceTLSConfig, @@ -2076,8 +2081,9 @@ func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) { healthserver.SetReady() runtimeState.adminDashboard.setReady() }() - err = serviceSrv.ListenAndServeTLS("", "") - if err != nil { + err = runtimeState.serviceServer.ListenAndServeTLS("", "") + if err != nil && err != http.ErrServerClosed { panic(err) } + return err } From ae1393799e91cd416c0a1333ae72a3db328adeef Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Sat, 26 Oct 2024 15:00:48 -0700 Subject: [PATCH 09/10] addressing comments --- cmd/keymasterd/auth_sshcert.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cmd/keymasterd/auth_sshcert.go b/cmd/keymasterd/auth_sshcert.go index 03b561f7..0b776160 100644 --- a/cmd/keymasterd/auth_sshcert.go +++ b/cmd/keymasterd/auth_sshcert.go @@ -8,8 +8,8 @@ import ( "golang.org/x/crypto/ssh" ) -// Thus function can only be called after all known keymaster public keys -// have been loaded, that is after the server is ready +// This function can only be called after all known keymaster public keys +// have been loaded, that is, after the server is ready func (state *RuntimeState) initialzeSelfSSHCertAuthenticator() error { // build ssh pubkey list @@ -49,7 +49,7 @@ func (s *RuntimeState) sshCertAuthCreateChallengeHandler(w http.ResponseWriter, } func (s *RuntimeState) sshCertAuthLoginWithChallengeHandler(w http.ResponseWriter, r *http.Request) { - username, maxAge, userErrString, err := s.sshCertAuthenticator.LoginWithChallenge(r) + username, expiration, userErrString, err := s.sshCertAuthenticator.LoginWithChallenge(r) if err != nil { s.logger.Printf("error=%s", err) errorCode := http.StatusBadRequest @@ -59,9 +59,8 @@ func (s *RuntimeState) sshCertAuthLoginWithChallengeHandler(w http.ResponseWrite s.writeFailureResponse(w, r, errorCode, userErrString) return } - // TODO: make the maxAge the smaller of maxAge and now + 60s // Make new auth cookie - _, err = s.setNewAuthCookieWithExpiration(w, username, AuthTypeKeymasterSSHCert, maxAge) + _, err = s.setNewAuthCookieWithExpiration(w, username, AuthTypeKeymasterSSHCert, expiration) if err != nil { s.writeFailureResponse(w, r, http.StatusInternalServerError, "error internal") From 2900b168a532e7ba089634c75eaaeea20fea1135 Mon Sep 17 00:00:00 2001 From: Camilo Viecco Date: Sun, 27 Oct 2024 14:23:18 -0700 Subject: [PATCH 10/10] cleanup --- cmd/keymasterd/app.go | 21 +++++++++++++-------- cmd/keymasterd/auth_sshcert_test.go | 3 ++- cmd/keymasterd/idp_oidc_test.go | 12 ------------ 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/cmd/keymasterd/app.go b/cmd/keymasterd/app.go index e3b8cfe9..7bb6ace6 100644 --- a/cmd/keymasterd/app.go +++ b/cmd/keymasterd/app.go @@ -223,6 +223,7 @@ type RuntimeState struct { totpLocalRateLimit map[string]totpRateLimitInfo totpLocalTateLimitMutex sync.Mutex sshCertAuthenticator *sshcertauth.Authenticator + adminMux *http.ServeMux serviceMux *http.ServeMux serviceServer *http.Server adminServer *http.Server @@ -1832,7 +1833,7 @@ func main() { os.Exit(1) } logger.Debugf(3, "After load verify") - startServerAfterLoad(runtimeState, realLogger) + startServerAfterLoad(runtimeState, http.DefaultServeMux, realLogger) logger.Debugf(3, "After server initbase") err = startListenersAndWaitForUnsealing(runtimeState) if err != nil { @@ -1840,7 +1841,10 @@ func main() { } } -func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.Logger) { +// This function inializes paths and application loggers. +// However since the grpc lib uses the defaultservermux we need to pass it in +// actual production code as we cannot register the same path to a mux +func startServerAfterLoad(runtimeState *RuntimeState, adminMux *http.ServeMux, realLogger *serverlogger.Logger) { var err error publicLogs := runtimeState.Config.Base.PublicLogs @@ -1863,10 +1867,11 @@ func startServerAfterLoad(runtimeState *RuntimeState, realLogger *serverlogger.L stdlog.LstdFlags) // Expose the registered metrics via HTTP. - http.Handle("/", runtimeState.adminDashboard) - http.Handle("/prometheus_metrics", promhttp.Handler()) //lint:ignore SA1019 TODO: newer prometheus handler - http.HandleFunc(secretInjectorPath, runtimeState.secretInjectorHandler) - http.HandleFunc(readyzPath, runtimeState.readyzHandler) + adminMux.Handle("/", runtimeState.adminDashboard) + adminMux.Handle("/prometheus_metrics", promhttp.Handler()) //lint:ignore SA1019 TODO: newer prometheus handler + adminMux.HandleFunc(secretInjectorPath, runtimeState.secretInjectorHandler) + adminMux.HandleFunc(readyzPath, runtimeState.readyzHandler) + runtimeState.adminMux = adminMux serviceMux := http.NewServeMux() serviceMux.HandleFunc(certgenPath, runtimeState.certGenHandler) @@ -1992,7 +1997,7 @@ func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) error { tls.TLS_AES_256_GCM_SHA384, }, } - logFilterHandler := NewLogFilterHandler(http.DefaultServeMux, publicLogs, + logFilterHandler := NewLogFilterHandler(runtimeState.adminMux, publicLogs, runtimeState) serviceHTTPLogger := httpLogger{AccessLogger: runtimeState.serviceAccessLogger} adminHTTPLogger := httpLogger{AccessLogger: runtimeState.adminAccessLogger} @@ -2075,7 +2080,7 @@ func startListenersAndWaitForUnsealing(runtimeState *RuntimeState) error { IdleTimeout: 120 * time.Second, } - http.Handle(eventmon.HttpPath, eventNotifier) + runtimeState.adminMux.Handle(eventmon.HttpPath, eventNotifier) go func() { time.Sleep(time.Millisecond * 10) healthserver.SetReady() diff --git a/cmd/keymasterd/auth_sshcert_test.go b/cmd/keymasterd/auth_sshcert_test.go index aa332c29..ced2410b 100644 --- a/cmd/keymasterd/auth_sshcert_test.go +++ b/cmd/keymasterd/auth_sshcert_test.go @@ -76,7 +76,8 @@ func TestSshCertAuthLoginWithChallengeHandler(t *testing.T) { defer os.Remove(passwdFile.Name()) // clean up state.Config.Base.AllowedAuthBackendsForCerts = append(state.Config.Base.AllowedAuthBackendsForCerts, proto.AuthTypeSSHCert) realLogger := serverlogger.New("") //TODO, we need to find a simulator for this - startServerAfterLoad(state, realLogger) + adminMux := http.NewServeMux() + startServerAfterLoad(state, adminMux, realLogger) //TODO: write the actual test, at this point we only have the endpoints initalized } diff --git a/cmd/keymasterd/idp_oidc_test.go b/cmd/keymasterd/idp_oidc_test.go index 68aa1d71..d1f6bda2 100644 --- a/cmd/keymasterd/idp_oidc_test.go +++ b/cmd/keymasterd/idp_oidc_test.go @@ -22,18 +22,6 @@ func init() { //logger = stdlog.New(os.Stderr, "", stdlog.LstdFlags) slogger := stdlog.New(os.Stderr, "", stdlog.LstdFlags) logger = debuglogger.New(slogger) - /* - http.HandleFunc("/userinfo", userinfoHandler) - http.HandleFunc("/token", tokenHandler) - http.HandleFunc("/", handler) - logger.Printf("about to start server") - go http.ListenAndServe(":12345", nil) - time.Sleep(20 * time.Millisecond) - _, err := http.Get("http://localhost:12345") - if err != nil { - logger.Fatal(err) - } - */ } func TestIDPOpenIDCMetadataHandler(t *testing.T) {