From 9e619fc020963bc0c1c7664d163d93a1b5dc4d0a Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Sat, 29 Jan 2022 12:59:31 -0500 Subject: [PATCH 001/204] Making client authentication mode configurable --- app.go | 24 +++++++++++++++++++++--- cmd/headscale/cli/utils.go | 8 ++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/app.go b/app.go index 3ba384b..6accaf9 100644 --- a/app.go +++ b/app.go @@ -87,8 +87,9 @@ type Config struct { TLSLetsEncryptCacheDir string TLSLetsEncryptChallengeType string - TLSCertPath string - TLSKeyPath string + TLSCertPath string + TLSKeyPath string + TLSClientAuthMode string ACMEURL string ACMEEmail string @@ -644,12 +645,29 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { if !strings.HasPrefix(h.cfg.ServerURL, "https://") { log.Warn().Msg("Listening with TLS but ServerURL does not start with https://") } + + // Leaving flexibility here to support other authentication modes + // if desired. + var client_auth_mode tls.ClientAuthType + msg := "Client authentication (mTLS) " + if(h.cfg.TLSClientAuthMode == "disabled"){ + log.Warn().Msg(msg + "is disabled") + client_auth_mode = tls.NoClientCert + }else if (h.cfg.TLSClientAuthMode == "relaxed"){ + log.Warn().Msg(msg + "is relaxed. Client certs will be required but will not be verified.") + client_auth_mode = tls.RequireAnyClientCert + }else{ + log.Warn().Msg(msg + "is enforced. Disable or relax in the configuration file.") + client_auth_mode = tls.RequireAndVerifyClientCert + } + tlsConfig := &tls.Config{ - ClientAuth: tls.RequireAnyClientCert, + ClientAuth: client_auth_mode, NextProtos: []string{"http/1.1"}, Certificates: make([]tls.Certificate, 1), MinVersion: tls.VersionTLS12, } + tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(h.cfg.TLSCertPath, h.cfg.TLSKeyPath) return tlsConfig, err diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index a485664..4faf905 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -40,6 +40,7 @@ func LoadConfig(path string) error { viper.SetDefault("tls_letsencrypt_cache_dir", "/var/www/.cache") viper.SetDefault("tls_letsencrypt_challenge_type", "HTTP-01") + viper.SetDefault("tls_client_auth_mode", "disabled") viper.SetDefault("ip_prefix", "100.64.0.0/10") @@ -80,6 +81,12 @@ func LoadConfig(path string) error { !strings.HasPrefix(viper.GetString("server_url"), "https://") { errorText += "Fatal config error: server_url must start with https:// or http://\n" } + + auth_mode := viper.GetString("tls_client_auth_mode") + if (auth_mode != "disabled" && auth_mode != "enforced"){ + errorText += "Invalid tls_client_auth_mode supplied. Accepted values: disabled, enforced." + } + if errorText != "" { //nolint return errors.New(strings.TrimSuffix(errorText, "\n")) @@ -251,6 +258,7 @@ func getHeadscaleConfig() headscale.Config { TLSCertPath: absPath(viper.GetString("tls_cert_path")), TLSKeyPath: absPath(viper.GetString("tls_key_path")), + TLSClientAuthMode: viper.GetString("tls_client_auth_mode"), DNSConfig: dnsConfig, From 5935b13b6780180d717cd66a13657c043c11905b Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Sat, 29 Jan 2022 13:35:08 -0500 Subject: [PATCH 002/204] refining --- app.go | 19 ++++++++++++------- cmd/headscale/cli/utils.go | 4 ++-- docs/tls.md | 19 +++++++++++++++++++ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/app.go b/app.go index 6accaf9..7301757 100644 --- a/app.go +++ b/app.go @@ -646,21 +646,26 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { log.Warn().Msg("Listening with TLS but ServerURL does not start with https://") } - // Leaving flexibility here to support other authentication modes - // if desired. var client_auth_mode tls.ClientAuthType - msg := "Client authentication (mTLS) " if(h.cfg.TLSClientAuthMode == "disabled"){ - log.Warn().Msg(msg + "is disabled") + // Client cert is _not_ required. client_auth_mode = tls.NoClientCert }else if (h.cfg.TLSClientAuthMode == "relaxed"){ - log.Warn().Msg(msg + "is relaxed. Client certs will be required but will not be verified.") + // Client cert required, but not verified. client_auth_mode = tls.RequireAnyClientCert - }else{ - log.Warn().Msg(msg + "is enforced. Disable or relax in the configuration file.") + }else if (h.cfg.TLSClientAuthMode == "enforced"){ + // Client cert is required and verified. client_auth_mode = tls.RequireAndVerifyClientCert + }else{ + return nil, errors.New( + "Invalid tls_client_auth_mode provided: " + + h.cfg.TLSClientAuthMode) } + log.Info().Msg(fmt.Sprintf( + "Client authentication (mTLS) is \"%s\". See the docs to learn about configuring this setting.", + h.cfg.TLSClientAuthMode)) + tlsConfig := &tls.Config{ ClientAuth: client_auth_mode, NextProtos: []string{"http/1.1"}, diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 4faf905..1cbfcf6 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -83,8 +83,8 @@ func LoadConfig(path string) error { } auth_mode := viper.GetString("tls_client_auth_mode") - if (auth_mode != "disabled" && auth_mode != "enforced"){ - errorText += "Invalid tls_client_auth_mode supplied. Accepted values: disabled, enforced." + if (auth_mode != "disabled" && auth_mode != "relaxed" && auth_mode != "enforced"){ + errorText += "Invalid tls_client_auth_mode supplied. Accepted values: disabled, relaxed, enforced." } if errorText != "" { diff --git a/docs/tls.md b/docs/tls.md index 557cdf0..f8818ce 100644 --- a/docs/tls.md +++ b/docs/tls.md @@ -29,3 +29,22 @@ headscale can also be configured to expose its web service via TLS. To configure tls_cert_path: "" tls_key_path: "" ``` + +### Configuring Mutual TLS Authentication (mTLS) + +mTLS is a method by which an HTTPS server authenticates clients, e.g. Tailscale, +using TLS certificates. The capability can be configured by by applying one of +the following values to the `tls_client_auth_mode` setting in the configuration +file. + +| Value | Behavior | +| ----- | -------- | +| `disabled` | Disable mTLS (default). | +| `relaxed` | A client certificate is required, but it is not verified. | +| `enforced` | Requires clients to supply a certificate that is verified. | + + +```yaml +tls_client_auth_mode: "" +``` + From c98a559b4df7222953d5fba6cd781c1cc391efa0 Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Sat, 29 Jan 2022 14:15:33 -0500 Subject: [PATCH 003/204] linting/formatting --- app.go | 44 +++++++++++++++++++------------------- cmd/headscale/cli/utils.go | 16 +++++++------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/app.go b/app.go index 7301757..a375165 100644 --- a/app.go +++ b/app.go @@ -87,9 +87,9 @@ type Config struct { TLSLetsEncryptCacheDir string TLSLetsEncryptChallengeType string - TLSCertPath string - TLSKeyPath string - TLSClientAuthMode string + TLSCertPath string + TLSKeyPath string + TLSClientAuthMode string ACMEURL string ACMEEmail string @@ -646,28 +646,28 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { log.Warn().Msg("Listening with TLS but ServerURL does not start with https://") } - var client_auth_mode tls.ClientAuthType - if(h.cfg.TLSClientAuthMode == "disabled"){ - // Client cert is _not_ required. - client_auth_mode = tls.NoClientCert - }else if (h.cfg.TLSClientAuthMode == "relaxed"){ - // Client cert required, but not verified. - client_auth_mode = tls.RequireAnyClientCert - }else if (h.cfg.TLSClientAuthMode == "enforced"){ - // Client cert is required and verified. - client_auth_mode = tls.RequireAndVerifyClientCert - }else{ - return nil, errors.New( - "Invalid tls_client_auth_mode provided: " + - h.cfg.TLSClientAuthMode) - } + var clientAuthMode tls.ClientAuthType + if h.cfg.TLSClientAuthMode == "disabled" { + // Client cert is _not_ required. + clientAuthMode = tls.NoClientCert + } else if h.cfg.TLSClientAuthMode == "relaxed" { + // Client cert required, but not verified. + clientAuthMode = tls.RequireAnyClientCert + } else if h.cfg.TLSClientAuthMode == "enforced" { + // Client cert is required and verified. + clientAuthMode = tls.RequireAndVerifyClientCert + } else { + return nil, errors.New( + "Invalid tls_clientAuthMode provided: " + + h.cfg.TLSClientAuthMode) + } - log.Info().Msg(fmt.Sprintf( - "Client authentication (mTLS) is \"%s\". See the docs to learn about configuring this setting.", - h.cfg.TLSClientAuthMode)) + log.Info().Msg(fmt.Sprintf( + "Client authentication (mTLS) is \"%s\". See the docs to learn about configuring this setting.", + h.cfg.TLSClientAuthMode)) tlsConfig := &tls.Config{ - ClientAuth: client_auth_mode, + ClientAuth: clientAuthMode, NextProtos: []string{"http/1.1"}, Certificates: make([]tls.Certificate, 1), MinVersion: tls.VersionTLS12, diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 1cbfcf6..1f9092e 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -40,7 +40,7 @@ func LoadConfig(path string) error { viper.SetDefault("tls_letsencrypt_cache_dir", "/var/www/.cache") viper.SetDefault("tls_letsencrypt_challenge_type", "HTTP-01") - viper.SetDefault("tls_client_auth_mode", "disabled") + viper.SetDefault("tls_client_auth_mode", "disabled") viper.SetDefault("ip_prefix", "100.64.0.0/10") @@ -82,10 +82,10 @@ func LoadConfig(path string) error { errorText += "Fatal config error: server_url must start with https:// or http://\n" } - auth_mode := viper.GetString("tls_client_auth_mode") - if (auth_mode != "disabled" && auth_mode != "relaxed" && auth_mode != "enforced"){ - errorText += "Invalid tls_client_auth_mode supplied. Accepted values: disabled, relaxed, enforced." - } + clientAuthMode := viper.GetString("tls_client_auth_mode") + if clientAuthMode != "disabled" && clientAuthMode != "relaxed" && clientAuthMode != "enforced" { + errorText += "Invalid tls_client_auth_mode supplied. Accepted values: disabled, relaxed, enforced." + } if errorText != "" { //nolint @@ -256,9 +256,9 @@ func getHeadscaleConfig() headscale.Config { ), TLSLetsEncryptChallengeType: viper.GetString("tls_letsencrypt_challenge_type"), - TLSCertPath: absPath(viper.GetString("tls_cert_path")), - TLSKeyPath: absPath(viper.GetString("tls_key_path")), - TLSClientAuthMode: viper.GetString("tls_client_auth_mode"), + TLSCertPath: absPath(viper.GetString("tls_cert_path")), + TLSKeyPath: absPath(viper.GetString("tls_key_path")), + TLSClientAuthMode: viper.GetString("tls_client_auth_mode"), DNSConfig: dnsConfig, From d44b2a7c014b98178743421b5ebc0b7b65100cb3 Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Sun, 30 Jan 2022 07:26:28 -0500 Subject: [PATCH 004/204] adding default for tls_client_auth_mode --- config-example.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config-example.yaml b/config-example.yaml index 3301669..3d8fe88 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -85,6 +85,13 @@ acme_email: "" # Domain name to request a TLS certificate for: tls_letsencrypt_hostname: "" +# Client (Tailscale/Browser) authentication mode (mTLS) +# Acceptable values: +# - disabled: client authentication disabled +# - relaxed: client certificate is required but not verified +# - enforced: client certificate is required and verified +tls_client_auth_mode: disabled + # Path to store certificates and metadata needed by # letsencrypt tls_letsencrypt_cache_dir: /var/lib/headscale/cache From 310e7b15c7d436205ff598f131118f45b3fa0be8 Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Sun, 30 Jan 2022 10:46:57 -0500 Subject: [PATCH 005/204] making alternatives constants --- app.go | 22 +++++++++++++--------- docs/tls.md | 10 ++++------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/app.go b/app.go index a375165..26d7b95 100644 --- a/app.go +++ b/app.go @@ -61,6 +61,10 @@ const ( errUnsupportedLetsEncryptChallengeType = Error( "unknown value for Lets Encrypt challenge type", ) + + DisabledClientAuth = "disabled" + RelaxedClientAuth = "relaxed" + EnforcedClientAuth = "enforced" ) // Config contains the initial Headscale configuration. @@ -647,19 +651,19 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { } var clientAuthMode tls.ClientAuthType - if h.cfg.TLSClientAuthMode == "disabled" { + switch h.cfg.TLSClientAuthMode { + case DisabledClientAuth: // Client cert is _not_ required. clientAuthMode = tls.NoClientCert - } else if h.cfg.TLSClientAuthMode == "relaxed" { - // Client cert required, but not verified. + case RelaxedClientAuth: + // Client cert required, but _not verified_. clientAuthMode = tls.RequireAnyClientCert - } else if h.cfg.TLSClientAuthMode == "enforced" { - // Client cert is required and verified. + case EnforcedClientAuth: + // Client cert is _required and verified_. clientAuthMode = tls.RequireAndVerifyClientCert - } else { - return nil, errors.New( - "Invalid tls_clientAuthMode provided: " + - h.cfg.TLSClientAuthMode) + default: + return nil, Error("Invalid tls_client_auth_mode provided: " + + h.cfg.TLSClientAuthMode) } log.Info().Msg(fmt.Sprintf( diff --git a/docs/tls.md b/docs/tls.md index f8818ce..19cf16a 100644 --- a/docs/tls.md +++ b/docs/tls.md @@ -37,14 +37,12 @@ using TLS certificates. The capability can be configured by by applying one of the following values to the `tls_client_auth_mode` setting in the configuration file. -| Value | Behavior | -| ----- | -------- | -| `disabled` | Disable mTLS (default). | -| `relaxed` | A client certificate is required, but it is not verified. | +| Value | Behavior | +| ---------- | ---------------------------------------------------------- | +| `disabled` | Disable mTLS (default). | +| `relaxed` | A client certificate is required, but it is not verified. | | `enforced` | Requires clients to supply a certificate that is verified. | - ```yaml tls_client_auth_mode: "" ``` - From 0c3fd16113c2d8209cb6575bcb30a3b072482e99 Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Mon, 31 Jan 2022 07:18:50 -0500 Subject: [PATCH 006/204] refining and adding tests --- app.go | 41 ++++++++++++++++++++++++++--------------- app_test.go | 22 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/app.go b/app.go index 26d7b95..8d2a2b1 100644 --- a/app.go +++ b/app.go @@ -650,21 +650,11 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { log.Warn().Msg("Listening with TLS but ServerURL does not start with https://") } - var clientAuthMode tls.ClientAuthType - switch h.cfg.TLSClientAuthMode { - case DisabledClientAuth: - // Client cert is _not_ required. - clientAuthMode = tls.NoClientCert - case RelaxedClientAuth: - // Client cert required, but _not verified_. - clientAuthMode = tls.RequireAnyClientCert - case EnforcedClientAuth: - // Client cert is _required and verified_. - clientAuthMode = tls.RequireAndVerifyClientCert - default: - return nil, Error("Invalid tls_client_auth_mode provided: " + - h.cfg.TLSClientAuthMode) - } + clientAuthMode, err := h.GetClientAuthMode() + + if err != nil { + return nil, err + } log.Info().Msg(fmt.Sprintf( "Client authentication (mTLS) is \"%s\". See the docs to learn about configuring this setting.", @@ -683,6 +673,27 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { } } +// Look up the TLS constant relative to user-supplied TLS client +// authentication mode. +func (h *Headscale) GetClientAuthMode() (tls.ClientAuthType, error) { + + switch h.cfg.TLSClientAuthMode { + case DisabledClientAuth: + // Client cert is _not_ required. + return tls.NoClientCert, nil + case RelaxedClientAuth: + // Client cert required, but _not verified_. + return tls.RequireAnyClientCert, nil + case EnforcedClientAuth: + // Client cert is _required and verified_. + return tls.RequireAndVerifyClientCert, nil + default: + return tls.NoClientCert, Error("Invalid tls_client_auth_mode provided: " + + h.cfg.TLSClientAuthMode) + } + +} + func (h *Headscale) setLastStateChangeToNow(namespace string) { now := time.Now().UTC() lastStateUpdate.WithLabelValues("", "headscale").Set(float64(now.Unix())) diff --git a/app_test.go b/app_test.go index bff1393..a53a880 100644 --- a/app_test.go +++ b/app_test.go @@ -63,3 +63,25 @@ func (s *Suite) ResetDB(c *check.C) { } app.db = db } + +// Enusre an error is returned when an invalid auth mode +// is supplied. +func (s *Suite) TestInvalidClientAuthMode(c *check.C){ + app.cfg.TLSClientAuthMode = "invalid" + _, err := app.GetClientAuthMode() + c.Assert(err, check.NotNil) +} + +// Ensure that all client auth modes return a nil error +func (s *Suite) TestAuthModes(c *check.C){ + + var modes = []string{"disabled", "relaxed", "enforced"} + + for _, v := range modes { + app.cfg.TLSClientAuthMode = v + _, err := app.GetClientAuthMode() + c.Assert(err, check.IsNil) + } + +} + From 9de5c7f8b8a6836197f555b8ed05fd7a0df41012 Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Mon, 31 Jan 2022 07:22:17 -0500 Subject: [PATCH 007/204] updating default --- cmd/headscale/cli/.utils.go.swp | Bin 0 -> 24576 bytes cmd/headscale/cli/utils.go | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 cmd/headscale/cli/.utils.go.swp diff --git a/cmd/headscale/cli/.utils.go.swp b/cmd/headscale/cli/.utils.go.swp new file mode 100644 index 0000000000000000000000000000000000000000..fbd933abe05eba73d62b6cfcf550855fe57a20f6 GIT binary patch literal 24576 zcmeI3dyr&TS-=|tLZg@vL5N!A*$#<4o5}6jyqS>b?96O-WM_A>vr8bGO>?LFcF*1I zzPG*i_RP-a1%D6|vI&ailQI&51j;H(R3M59#Y@2wBnb(zBq6>DRgolGSXOELednC} z=;_{_7~>yS^;UkF?t9PkJLi1o`@VB}W$LX9i|R7xf)fAED3y*r^nJH+PE@-6he{>ErEX0I{&g)moB_u$CTtbyRuFF$e9P9clL3@u>{5v7)xL*fw2U}5*SNh zEP=5E#uE7dFM*`@veGSd{5v7)xL*fw2U}5*SNhEP=5E#u6AyU@U>L1jZ8hKahaiER|kIxv!A`0O$Xy z|NpP2mrBpVlkhlv6}|v}0)GG>g?r(Ba2wnN5gY*@cEcI)><^bpkHTl*ci`9H7I+6- z4~O9(ya_IaOW-x|%&SYKC*Xd#3u5r$ZSZDz6L6eadObYOU4<{hpTn(i6`TpLfhT^j zRQfjjA>0qY1n+~l!ZuLw{a2Mre+6HId%%V3;V}Fpl;Nx8QYnF#z<<56RQgZ&92|p7 z;iIo8mEI3e{y?epPw(gQMzw%9`a=9OM;zNGW z^o|`?SE%iLooO~BM4{i7%ZqWlTG{3L9j~d9Q1#p>_7tfmmER7+$Pe0%<5VU{UoOu_ zQPqp02}gfhPNHgsl$A+I&o}eD6Sf@^hEY|2_gjiAYTFem@H^@T(;{iYq<%hqg=BV? zq}r-2rc`c)k(U5O(|^DV2@%OahT%r6SepO0$gWJf1HEYi`G92s?4T(eb??sk{ATwcZVzo{Iau z9?zPNnrSq=Ucyk5y6?r)s_Dn>3S&R1BCq2flMh~i_#33I==x1*GZeNcWl1B_OcizR zxoX6FThz&3rxi$F%A2w?oSVj|S{c5Kk~$Z`IxLX3S5G#2o^m5k z?LKf|>HMi3$_<+8z@FvvXZ9@Z<-3u@aKBGoB5ju`QYa@A$O|mWHm@iYqqVMaqku&` zt=3n)K=orj4|R7njFZ6adS<)}tx|5RGFd2*#bmzB%|u!8SQIXaSRhDP^$@PQ=%Ncz zjgIH2jvpspPlYSVK(|n3^WF)}5jhrMX5YGU1X{KUVyw2hLUN zrYma2Yq)*X2V=^>G<2afBM!SBIp|;PCyD%}@KzKCi3(eVW+$s|LYtd@NGV zqGuYa>N#zPAy$4bkq*Tw>UTWRHr3)pwOVOtvKKn5XS?Z{p6cZnFs@e&O%W!%ESjy$ zN=MXAwBocFREeW?L83fXzBjxu(sD%?XpQ4VNxkPLt2Oy{)Z5TsCRGq7Y9&lo?eZAi z;6|D`Z{>|Qo}_bW(OJ?|fs8J?xR}#6XIVvWl-JzI=sww2PT%dO>M_(_)b-;Sfk@d?;iZ>OjV`{BNmAAj zcP;7%`R!LnO4J+FaE;A?{aJ5M7zQVC-x@uK=P(L_DFedq43F`spyl{S)8;DRH|1;M@hw6dh6@!HAg=# zG#iT}>@qqnZTM0sl4DeIbP^j`Kk7Kxc%){@;5y0%NYJ60P^m^Cl9B;_t;Gk+Ire#LDZ#ZzDb zOih(242!9%lT{MD1bx}tX@uRHY?*P5`79r>nKr*Baii6i7k=O+j@zp7M>b1&)DC+` z+m0X9Hr#Hxbsj!2g?}Smi){c4&{RWNQU(vP3z1EHkYr5l`-b8WjxEF;i zof`0RZHKCGM?KAXr0=qjg5sU^windeVL{4kJ2n+MoT`0RfV z55p(nLvR9agPS3SLvSrz4SQh`X5l=TfGRwOU;jn84?YCg$Fl5Gk9_N#MS&Wa3Qg%lZ=Q~JfOBcJG5CzO^A!nx>dzTG7@RMc# zxOd4#Qooc(1_}5XyC;j{Rq>$mz+KjGo@VAwEANmPJ$X-Q*rMCB-K%5wn9bW+BvLdR zc6&&n8v4z~qMKl~iWeh6mBN!eGHHsE;>-5qa8s#^KCr7-D^iBj#KiT3de`k?;OWp~ z2ZL?j!rZK`kmN)kd3%Tw$#vNLp$;8F@OVYDB!R>dOaxGOz;--#B;n>FB`qO`$nD|t z5CIDNL@TsRB?3&W%y0R`2Xrt&LI?)81+l9`ynV4^F84-p}<3JscoX z8;gmuEH0RzY|w|5FqG)8j+ko42Mf6(5lTYL$F&<;nO2pZ9`UG1Rn&PZadg3x*_<4b z!VRSfRULY&r(75rA39J3uZ_$osF55K-&Bk!XV(0kOgll(vu-f4q$imBi(;|j;Z{YA z`%RQrM@~hARNXT{^T?#uQ`sZbtGlTSOucU%Ys;#Tr+xhJftje?R67yHBT3hy7Ij&i zXE$nV+g}@mig-ft!TAJ?y-M+^nAX}&kQrN_)Tx<~CX61&&P>#nFuI;~ggF;+%P3-B zKk4<8T^(2A-i1+H?h`tWWAj>~*5=aXN(5tx1(kFH z>pxbHNaQ^Wyqnmv(T0r4K!&t;q|Y;yne{N{{8?>sx?9A|g>tLJ5o7C1qg)e)7dq$^AM)4tV zX$I<;L#_#DRs#QWDz_{LcQz08+D{YGJZYV76PpcNf~(q`f-!PtJ?M!oO|W&aU5XA2 zn$^NX(+cMrJnsb?gsbXPEqX>kz?t2%;G{2PIhM<^F3LAeprQGvmE<(#`UH9OBi&~y z4zq*S%o5*bdLe^2-+Sb^tg~amoXqKMRf6{vA=|M&*^%8-1kupjr}qDG`%7oYc`zT+`~45%?>_*) z4%fol;c}?JE8#o%_g{q1!Dm6v_fJ3vcEeThWAHHk{WswKa2T$GbK!gV@qYtff&1WB z;cc)Vu7>mBWgve3WAG?^6Fv@i!F%9#5dVHV{0n~ir{Ndj4%h?R;S6}H%$YoV1bT2S z>;m!6PlwOrcYhjgg(h4F2VoohIGhg8;cMRr>kvZ(3-Ag!4PFY5;AejjZh&h+eD4e3 z%bfRr0X_?#f&1V%{0v+Sj}d?QYj_m?2tEaJC*Z^IA-EUb2^YhU!e4Uc{~K^Sv|t75 za6McN`(Q6@gMVjSABAtipTeDR2xPoR-2o_<7nV%Cb6S~yHvXn8rE}uHuQrk z;p|B+Pndu)>VWUrd40L8-`1r~S*~SH!>G2V<|PwIxNEfUO*+a=gPqd-0gg z2C}8XNxR8aG3l20zD%$&auZBoZ3A0Jp<#~1rFsqK7+hqMPZXwgMbVFDh|?n4lyj&KXRw%@m;~l18KM-Uy=$V%nNjhVjETn_m3M$H|PQK2bc?aAwI0^=&m|*k)AP;9^F- zI7lyK{6-gb>cKPvXd9W!Wmanb614X%VRWcuP(Q0<(+4Z-@ z>Z4_*f~{6up^`jl{!mw(t@+VQGEcq5I^4Vpw_bxoD{$2M%j^FitiG++US4cWLye}F z1!LrzEtBE7W$vC1X4k%NK~EH~tfs1BVd*3}W$*`!8?iKoH?u;Pt+vpCq^7IctdzRW zl~aH5U^6v&1M~3YD+62A#uUX+PgN_i#On5;l2X$(4a>;{KiDJS>h01Y)u6F4t@?ux zL|e$!5R=Y27r4UqfxH$Al&h`zKQWVId4oGL@Ir1A%L{9N<~C)1%~#BdO-&dWg1J7% zHUXFP7O`$^y_L3K#GkirAg48ZJ#Z(SfNP)z+hGDugNN|(KL&Sz+yVG$I1AnYU&qgvvwyj_FL(7X zgeUOnzYQM%Ip04UD)1^O!?*C|e;F|J4L>7IZVUr z;WQ}0bNKdu2Y(AE;28KIzYBPlv3v#|frml-{*S@0fcz#v{C^qmC3w;QrOtrZXL{4j z0&$p2a)=^vNCJxas=12L;Ih6=XI>dAB+HgY{j8l>h}X&5EPQ2~v~fk*glv40hoXiK za%IodA@8iIxG8=&H@AO&d3hjyXZ=3yFyRYJ*wsecE1wWIasWS(Fm4pyp7 zMA@6>yp=u{FJ>jWFl%CZGt0Qu;wGoBiVcv+UmW+jm8{R$Y#@-En3BObO-inIN(*!8 z(%-Z&^s+QdLa8$*_RCAro|&w75<)zx1znUY`3@b{X=H#*6jv0S34ZHvw`dy#qz}m? z=z751x0K+vezuba&5vr9bS>4i6e_bHMT%)`W|J$-Q9z?pH|^6`ob|2AY=dVPH+#;AbXkN; z$C0iv@$4qyFv8e!zg^-&^hpknwIEu3ekW77*4~gqVFKQ(E`cZFON8|K5+>&pjiN(# zP8TCa^mxQo13eld40@Tbm*PQ9m6;@yQ>L7pu5%W~(Gxxe^4okoPN?wIGp~3!D0g_Z z?I|-~k8alw76KRbvc}1`o!X+`?1j*RJiQ**ti8zX)C2A|)cq`1JzXP4fmXImsH*40 z6E+}(KtuYpKAHW9p&KG}G)4o5#k?bp!XI*M4f-|c+;v|u6hRL@uXH52?b{F&cO`B(d{nN{iBu3}qHa}@h23hpQ z_RIG|2Xd<-zuPn|M-38`*Vmvbg=_!C-wJ3+=GjdjjO#JfszMRcDu!TYc5&XGkqo7F z8(mL+wPrdXDd)K?)EOaJozjz+w%E+?;s<_d;8xei51@>+aiR3@`9_pB@;3syo8;yI zQ#Poqnd3fRL>+2+kp*=EyUvK=6rc#?h$ z{O%x4uYdVwq^jFBteJ;?@sRywA?--99rAL{XELU}8EWbt{Zla!+R!L(uF4#wnbsk& zLOr|fPuZSFSM%Qm=~18C*~8u(k*~SJjvo{Bmf@M($uH07#ZVJTC2!JH5-}K^O5UWY z Date: Mon, 31 Jan 2022 10:27:43 -0500 Subject: [PATCH 008/204] linting again --- app.go | 39 ++++++++++++++++++--------------------- app_test.go | 27 ++++++++++++--------------- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/app.go b/app.go index 62d284b..b3725ee 100644 --- a/app.go +++ b/app.go @@ -657,11 +657,10 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { log.Warn().Msg("Listening with TLS but ServerURL does not start with https://") } - clientAuthMode, err := h.GetClientAuthMode() - - if err != nil { - return nil, err - } + clientAuthMode, err := h.GetClientAuthMode() + if err != nil { + return nil, err + } log.Info().Msg(fmt.Sprintf( "Client authentication (mTLS) is \"%s\". See the docs to learn about configuring this setting.", @@ -683,22 +682,20 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { // Look up the TLS constant relative to user-supplied TLS client // authentication mode. func (h *Headscale) GetClientAuthMode() (tls.ClientAuthType, error) { - - switch h.cfg.TLSClientAuthMode { - case DisabledClientAuth: - // Client cert is _not_ required. - return tls.NoClientCert, nil - case RelaxedClientAuth: - // Client cert required, but _not verified_. - return tls.RequireAnyClientCert, nil - case EnforcedClientAuth: - // Client cert is _required and verified_. - return tls.RequireAndVerifyClientCert, nil - default: - return tls.NoClientCert, Error("Invalid tls_client_auth_mode provided: " + - h.cfg.TLSClientAuthMode) - } - + switch h.cfg.TLSClientAuthMode { + case DisabledClientAuth: + // Client cert is _not_ required. + return tls.NoClientCert, nil + case RelaxedClientAuth: + // Client cert required, but _not verified_. + return tls.RequireAnyClientCert, nil + case EnforcedClientAuth: + // Client cert is _required and verified_. + return tls.RequireAndVerifyClientCert, nil + default: + return tls.NoClientCert, Error("Invalid tls_client_auth_mode provided: " + + h.cfg.TLSClientAuthMode) + } } func (h *Headscale) setLastStateChangeToNow(namespace string) { diff --git a/app_test.go b/app_test.go index a53a880..94b6ef0 100644 --- a/app_test.go +++ b/app_test.go @@ -66,22 +66,19 @@ func (s *Suite) ResetDB(c *check.C) { // Enusre an error is returned when an invalid auth mode // is supplied. -func (s *Suite) TestInvalidClientAuthMode(c *check.C){ - app.cfg.TLSClientAuthMode = "invalid" - _, err := app.GetClientAuthMode() - c.Assert(err, check.NotNil) +func (s *Suite) TestInvalidClientAuthMode(c *check.C) { + app.cfg.TLSClientAuthMode = "invalid" + _, err := app.GetClientAuthMode() + c.Assert(err, check.NotNil) } -// Ensure that all client auth modes return a nil error -func (s *Suite) TestAuthModes(c *check.C){ - - var modes = []string{"disabled", "relaxed", "enforced"} - - for _, v := range modes { - app.cfg.TLSClientAuthMode = v - _, err := app.GetClientAuthMode() - c.Assert(err, check.IsNil) - } +// Ensure that all client auth modes return a nil error. +func (s *Suite) TestAuthModes(c *check.C) { + modes := []string{"disabled", "relaxed", "enforced"} + for _, v := range modes { + app.cfg.TLSClientAuthMode = v + _, err := app.GetClientAuthMode() + c.Assert(err, check.IsNil) + } } - From 9b7d657cbe4ae7f648798a7080819f3863f6b7c8 Mon Sep 17 00:00:00 2001 From: Jamie Greeff Date: Wed, 29 Dec 2021 09:58:10 +0000 Subject: [PATCH 009/204] Return all peers instead of peers in same namespace --- dns.go | 6 +++- machine.go | 87 ++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/dns.go b/dns.go index 8ecd993..37daa88 100644 --- a/dns.go +++ b/dns.go @@ -163,7 +163,11 @@ func getMapResponseDNSConfig( dnsConfig = dnsConfigOrig.Clone() dnsConfig.Domains = append( dnsConfig.Domains, - fmt.Sprintf("%s.%s", machine.Namespace.Name, baseDomain), + fmt.Sprintf( + "%s.%s", + strings.Replace(machine.Namespace.Name, "@", ".", -1), // Replace @ with . for valid domain for machine + baseDomain, + ), ) namespaceSet := set.New(set.ThreadSafe) diff --git a/machine.go b/machine.go index 2b46298..aef310c 100644 --- a/machine.go +++ b/machine.go @@ -119,6 +119,33 @@ func (machine Machine) isExpired() bool { return time.Now().UTC().After(*machine.Expiry) } +// Our Pineapple fork of Headscale ignores namespaces when dealing with peers +// and instead passes ALL peers across all namespaces to each client. Access between clients +// is then enforced with ACL policies. +func (h *Headscale) getAllPeers(machine *Machine) (Machines, error) { + log.Trace(). + Caller(). + Str("machine", machine.Name). + Msg("Finding all peers") + + machines := Machines{} + if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", + machine.MachineKey).Find(&machines).Error; err != nil { + log.Error().Err(err).Msg("Error accessing db") + + return Machines{}, err + } + + sort.Slice(machines, func(i, j int) bool { return machines[i].ID < machines[j].ID }) + + log.Trace(). + Caller(). + Str("machine", machine.Name). + Msgf("Found all machines: %s", machines.String()) + + return machines, nil +} + func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { log.Trace(). Caller(). @@ -206,7 +233,40 @@ func (h *Headscale) getSharedTo(machine *Machine) (Machines, error) { } func (h *Headscale) getPeers(machine *Machine) (Machines, error) { - direct, err := h.getDirectPeers(machine) + // direct, err := h.getDirectPeers(machine) + // if err != nil { + // log.Error(). + // Caller(). + // Err(err). + // Msg("Cannot fetch peers") + + // return Machines{}, err + // } + + // shared, err := h.getShared(machine) + // if err != nil { + // log.Error(). + // Caller(). + // Err(err). + // Msg("Cannot fetch peers") + + // return Machines{}, err + // } + + // sharedTo, err := h.getSharedTo(machine) + // if err != nil { + // log.Error(). + // Caller(). + // Err(err). + // Msg("Cannot fetch peers") + + // return Machines{}, err + // } + + // peers := append(direct, shared...) + // peers = append(peers, sharedTo...) + + peers, err := h.getAllPeers(machine) if err != nil { log.Error(). Caller(). @@ -216,29 +276,6 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) { return Machines{}, err } - shared, err := h.getShared(machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") - - return Machines{}, err - } - - sharedTo, err := h.getSharedTo(machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") - - return Machines{}, err - } - - peers := append(direct, shared...) - peers = append(peers, sharedTo...) - sort.Slice(peers, func(i, j int) bool { return peers[i].ID < peers[j].ID }) log.Trace(). @@ -597,7 +634,7 @@ func (machine Machine) toNode( hostname = fmt.Sprintf( "%s.%s.%s", machine.Name, - machine.Namespace.Name, + strings.Replace(machine.Namespace.Name, "@", ".", -1), // Replace @ with . for valid domain for machine baseDomain, ) } else { From e482dfeed4a06e7d9be966a8068dd06b826f686d Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Thu, 3 Feb 2022 19:53:11 +0100 Subject: [PATCH 010/204] feat(machine): add ACLFilter if ACL's are enabled. This commit change the default behaviour and remove the notion of namespaces between the hosts. It allows all namespaces to be only filtered by the ACLs. This behavior is closer to tailsnet. --- machine.go | 133 ++++++++++++++++++++++++++++++++---------------- machine_test.go | 84 ++++++++++++++++++++++++++++++ utils.go | 9 ++++ 3 files changed, 183 insertions(+), 43 deletions(-) diff --git a/machine.go b/machine.go index aef310c..231c179 100644 --- a/machine.go +++ b/machine.go @@ -119,14 +119,21 @@ func (machine Machine) isExpired() bool { return time.Now().UTC().After(*machine.Expiry) } -// Our Pineapple fork of Headscale ignores namespaces when dealing with peers -// and instead passes ALL peers across all namespaces to each client. Access between clients -// is then enforced with ACL policies. -func (h *Headscale) getAllPeers(machine *Machine) (Machines, error) { +func containsAddresses(inputs []string, addrs MachineAddresses) bool { + for _, addr := range addrs.ToStringSlice() { + if containsString(inputs, addr) { + return true + } + } + return false +} + +// getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. +func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). Caller(). Str("machine", machine.Name). - Msg("Finding all peers") + Msg("Finding peers filtered by ACLs") machines := Machines{} if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", @@ -135,15 +142,50 @@ func (h *Headscale) getAllPeers(machine *Machine) (Machines, error) { return Machines{}, err } + mMachines := make(map[uint64]Machine) - sort.Slice(machines, func(i, j int) bool { return machines[i].ID < machines[j].ID }) + // Aclfilter peers here. We are itering through machines in all namespaces and search through the computed aclRules + // for match between rule SrcIPs and DstPorts. If the rule is a match we allow the machine to be viewable. + + // FIXME: On official control plane if a rule allow user A to talk to user B but NO rule allows user B to talk to + // user A. The behaviour is the following + // + // On official tailscale control plane: + // on first `tailscale status`` on node A we can see node B. The `tailscale status` command on node B doesn't show node A + // We can successfully establish a communication from A to B. When it's done, if we run the `tailscale status` command + // on node B again we can now see node A. It's not possible to establish a communication from node B to node A. + // On this implementation of the feature + // on any `tailscale status` command on node A we can see node B. The `tailscale status` command on node B DOES show A. + // + // I couldn't find a way to not clutter the output of `tailscale status` with all nodes that we could be talking to. + // In order to do this we would need to be able to identify that node A want to talk to node B but that Node B doesn't know + // how to talk to node A and then add the peering resource. + + for _, m := range machines { + for _, rule := range h.aclRules { + var dst []string + for _, d := range rule.DstPorts { + dst = append(dst, d.IP) + } + if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, m.IPAddresses) || containsString(dst, "*"))) || + (containsAddresses(rule.SrcIPs, m.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { + mMachines[m.ID] = m + } + } + } + + var authorizedMachines Machines + for _, m := range mMachines { + authorizedMachines = append(authorizedMachines, m) + } + sort.Slice(authorizedMachines, func(i, j int) bool { return authorizedMachines[i].ID < authorizedMachines[j].ID }) log.Trace(). Caller(). Str("machine", machine.Name). - Msgf("Found all machines: %s", machines.String()) + Msgf("Found some machines: %s", machines.String()) - return machines, nil + return authorizedMachines, nil } func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { @@ -233,47 +275,52 @@ func (h *Headscale) getSharedTo(machine *Machine) (Machines, error) { } func (h *Headscale) getPeers(machine *Machine) (Machines, error) { - // direct, err := h.getDirectPeers(machine) - // if err != nil { - // log.Error(). - // Caller(). - // Err(err). - // Msg("Cannot fetch peers") + var peers Machines + var err error + // If ACLs rules are defined, filter visible host list with the ACLs + // else use the classic namespace scope + if h.aclPolicy != nil { + peers, err = h.getFilteredByACLPeers(machine) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Cannot fetch peers") - // return Machines{}, err - // } + return Machines{}, err + } + } else { + direct, err := h.getDirectPeers(machine) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Cannot fetch peers") - // shared, err := h.getShared(machine) - // if err != nil { - // log.Error(). - // Caller(). - // Err(err). - // Msg("Cannot fetch peers") + return Machines{}, err + } - // return Machines{}, err - // } + shared, err := h.getShared(machine) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Cannot fetch peers") - // sharedTo, err := h.getSharedTo(machine) - // if err != nil { - // log.Error(). - // Caller(). - // Err(err). - // Msg("Cannot fetch peers") + return Machines{}, err + } - // return Machines{}, err - // } + sharedTo, err := h.getSharedTo(machine) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Cannot fetch peers") - // peers := append(direct, shared...) - // peers = append(peers, sharedTo...) - - peers, err := h.getAllPeers(machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") - - return Machines{}, err + return Machines{}, err + } + peers = append(direct, shared...) + peers = append(peers, sharedTo...) } sort.Slice(peers, func(i, j int) bool { return peers[i].ID < peers[j].ID }) diff --git a/machine_test.go b/machine_test.go index ff1dc91..f84603a 100644 --- a/machine_test.go +++ b/machine_test.go @@ -1,6 +1,7 @@ package headscale import ( + "fmt" "strconv" "time" @@ -154,6 +155,89 @@ func (s *Suite) TestGetDirectPeers(c *check.C) { c.Assert(peersOfMachine0[8].Name, check.Equals, "testmachine10") } +func (s *Suite) TestGetACLFilteredPeers(c *check.C) { + type base struct { + namespace *Namespace + key *PreAuthKey + } + + var stor []base + + for _, name := range []string{"test", "admin"} { + namespace, err := app.CreateNamespace(name) + c.Assert(err, check.IsNil) + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + stor = append(stor, base{namespace, pak}) + + } + + _, err := app.GetMachineByID(0) + c.Assert(err, check.NotNil) + + for index := 0; index <= 10; index++ { + machine := Machine{ + ID: uint64(index), + MachineKey: "foo" + strconv.Itoa(index), + NodeKey: "bar" + strconv.Itoa(index), + DiscoKey: "faa" + strconv.Itoa(index), + IPAddress: fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1)), + Name: "testmachine" + strconv.Itoa(index), + NamespaceID: stor[index%2].namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(stor[index%2].key.ID), + } + app.db.Save(&machine) + } + + app.aclPolicy = &ACLPolicy{ + Groups: map[string][]string{ + "group:test": {"admin"}, + }, + Hosts: map[string]netaddr.IPPrefix{}, + TagOwners: map[string][]string{}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"admin"}, Ports: []string{"*:*"}}, + {Action: "accept", Users: []string{"test"}, Ports: []string{"test:*"}}, + }, + Tests: []ACLTest{}, + } + + rules, err := app.generateACLRules() + c.Assert(err, check.IsNil) + app.aclRules = rules + + adminMachine, err := app.GetMachineByID(1) + c.Logf("Machine(%v), namespace: %v", adminMachine.Name, adminMachine.Namespace) + c.Assert(err, check.IsNil) + + testMachine, err := app.GetMachineByID(2) + c.Logf("Machine(%v), namespace: %v", testMachine.Name, testMachine.Namespace) + c.Assert(err, check.IsNil) + + _, err = testMachine.GetHostInfo() + c.Assert(err, check.IsNil) + + peersOfTestMachine, err := app.getFilteredByACLPeers(testMachine) + c.Assert(err, check.IsNil) + + peersOfAdminMachine, err := app.getFilteredByACLPeers(adminMachine) + c.Assert(err, check.IsNil) + + c.Log(peersOfTestMachine) + c.Assert(len(peersOfTestMachine), check.Equals, 4) + c.Assert(peersOfTestMachine[0].Name, check.Equals, "testmachine4") + c.Assert(peersOfTestMachine[1].Name, check.Equals, "testmachine6") + c.Assert(peersOfTestMachine[3].Name, check.Equals, "testmachine10") + + c.Log(peersOfAdminMachine) + c.Assert(len(peersOfAdminMachine), check.Equals, 9) + c.Assert(peersOfAdminMachine[0].Name, check.Equals, "testmachine2") + c.Assert(peersOfAdminMachine[2].Name, check.Equals, "testmachine4") + c.Assert(peersOfAdminMachine[5].Name, check.Equals, "testmachine7") +} + func (s *Suite) TestExpireMachine(c *check.C) { namespace, err := app.CreateNamespace("test") c.Assert(err, check.IsNil) diff --git a/utils.go b/utils.go index a6be8cc..794971a 100644 --- a/utils.go +++ b/utils.go @@ -212,6 +212,15 @@ func (h *Headscale) getUsedIPs() ([]netaddr.IP, error) { return ips, nil } +func containsString(ss []string, s string) bool { + for _, v := range ss { + if v == s { + return true + } + } + return false +} + func containsIPs(ips []netaddr.IP, ip netaddr.IP) bool { for _, v := range ips { if v == ip { From e9949b4c70e5a0bc0599e10d854ece73976c06e4 Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Thu, 3 Feb 2022 20:00:41 +0100 Subject: [PATCH 011/204] feat(acls): simplify updating rules --- acls.go | 8 +++++--- machine_test.go | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/acls.go b/acls.go index 326625b..e2b2a27 100644 --- a/acls.go +++ b/acls.go @@ -69,14 +69,16 @@ func (h *Headscale) LoadACLPolicy(path string) error { } h.aclPolicy = &policy + return h.UpdateACLRules() +} + +func (h *Headscale) UpdateACLRules() error { rules, err := h.generateACLRules() if err != nil { return err } - h.aclRules = rules - log.Trace().Interface("ACL", rules).Msg("ACL rules generated") - + h.aclRules = rules return nil } diff --git a/machine_test.go b/machine_test.go index f84603a..56fdf1f 100644 --- a/machine_test.go +++ b/machine_test.go @@ -204,9 +204,8 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { Tests: []ACLTest{}, } - rules, err := app.generateACLRules() + err = app.UpdateACLRules() c.Assert(err, check.IsNil) - app.aclRules = rules adminMachine, err := app.GetMachineByID(1) c.Logf("Machine(%v), namespace: %v", adminMachine.Name, adminMachine.Namespace) From fb45138fc19fffeb336e46c0a859ee9c711240be Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Sat, 5 Feb 2022 17:18:39 +0100 Subject: [PATCH 012/204] feat(acls): check acl owners and add bunch of tests --- acls.go | 96 ++++++++++++++------- acls_test.go | 220 ++++++++++++++++++++++++++++++++++++++++++++++++ machine_test.go | 2 +- 3 files changed, 287 insertions(+), 31 deletions(-) diff --git a/acls.go b/acls.go index e2b2a27..c86e315 100644 --- a/acls.go +++ b/acls.go @@ -2,6 +2,7 @@ package headscale import ( "encoding/json" + "errors" "fmt" "io" "os" @@ -90,8 +91,6 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { return nil, errInvalidAction } - filterRule := tailcfg.FilterRule{} - srcIPs := []string{} for innerIndex, user := range acl.Users { srcs, err := h.generateACLPolicySrcIP(user) @@ -103,7 +102,6 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { } srcIPs = append(srcIPs, srcs...) } - filterRule.SrcIPs = srcIPs destPorts := []tailcfg.NetPortRange{} for innerIndex, ports := range acl.Ports { @@ -174,17 +172,23 @@ func (h *Headscale) generateACLPolicyDestPorts( return dests, nil } +// expandalias has an input of either +// - a namespace +// - a group +// - a tag +// and transform these in IPAddresses func (h *Headscale) expandAlias(alias string) ([]string, error) { if alias == "*" { return []string{"*"}, nil } if strings.HasPrefix(alias, "group:") { - if _, ok := h.aclPolicy.Groups[alias]; !ok { - return nil, errInvalidGroup + namespaces, err := h.expandGroup(alias) + if err != nil { + return nil, err } ips := []string{} - for _, n := range h.aclPolicy.Groups[alias] { + for _, n := range namespaces { nodes, err := h.ListMachinesInNamespace(n) if err != nil { return nil, errInvalidNamespace @@ -198,40 +202,35 @@ func (h *Headscale) expandAlias(alias string) ([]string, error) { } if strings.HasPrefix(alias, "tag:") { - if _, ok := h.aclPolicy.TagOwners[alias]; !ok { - return nil, errInvalidTag - } - - // This will have HORRIBLE performance. - // We need to change the data model to better store tags - machines := []Machine{} - if err := h.db.Where("registered").Find(&machines).Error; err != nil { + var ips []string + owners, err := h.expandTagOwners(alias) + if err != nil { return nil, err } - ips := []string{} - for _, machine := range machines { - hostinfo := tailcfg.Hostinfo{} - if len(machine.HostInfo) != 0 { - hi, err := machine.HostInfo.MarshalJSON() + for _, namespace := range owners { + machines, err := h.ListMachinesInNamespace(namespace) + if err != nil { + if errors.Is(err, errNamespaceNotFound) { + continue + } else { + return nil, err + } + } + for _, machine := range machines { + if len(machine.HostInfo) == 0 { + continue + } + hi, err := machine.GetHostInfo() if err != nil { return nil, err } - err = json.Unmarshal(hi, &hostinfo) - if err != nil { - return nil, err - } - - // FIXME: Check TagOwners allows this - for _, t := range hostinfo.RequestTags { - if alias[4:] == t { + for _, t := range hi.RequestTags { + if alias == t { ips = append(ips, machine.IPAddresses.ToStringSlice()...) - - break } } } } - return ips, nil } @@ -266,6 +265,43 @@ func (h *Headscale) expandAlias(alias string) ([]string, error) { return nil, errInvalidUserSection } +// expandTagOwners will return a list of namespace. An owner can be either a namespace or a group +// a group cannot be composed of groups +func (h *Headscale) expandTagOwners(owner string) ([]string, error) { + var owners []string + ows, ok := h.aclPolicy.TagOwners[owner] + if !ok { + return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, owner) + } + for _, ow := range ows { + if strings.HasPrefix(ow, "group:") { + gs, err := h.expandGroup(ow) + if err != nil { + return []string{}, err + } + owners = append(owners, gs...) + } else { + owners = append(owners, ow) + } + } + return owners, nil +} + +// expandGroup will return the list of namespace inside the group +// after some validation +func (h *Headscale) expandGroup(group string) ([]string, error) { + gs, ok := h.aclPolicy.Groups[group] + if !ok { + return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) + } + for _, g := range gs { + if strings.HasPrefix(g, "group:") { + return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) + } + } + return gs, nil +} + func (h *Headscale) expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { if portsStr == "*" { return &[]tailcfg.PortRange{ diff --git a/acls_test.go b/acls_test.go index c35f4f8..f2fb6a0 100644 --- a/acls_test.go +++ b/acls_test.go @@ -1,7 +1,11 @@ package headscale import ( + "errors" + "gopkg.in/check.v1" + "gorm.io/datatypes" + "inet.af/netaddr" ) func (s *Suite) TestWrongPath(c *check.C) { @@ -52,6 +56,222 @@ func (s *Suite) TestBasicRule(c *check.C) { c.Assert(rules, check.NotNil) } +func (s *Suite) TestInvalidAction(c *check.C) { + app.aclPolicy = &ACLPolicy{ + ACLs: []ACL{ + {Action: "invalidAction", Users: []string{"*"}, Ports: []string{"*:*"}}, + }, + } + err := app.UpdateACLRules() + c.Assert(errors.Is(err, errInvalidAction), check.Equals, true) +} + +func (s *Suite) TestInvalidGroupInGroup(c *check.C) { + // this ACL is wrong because the group in users sections doesn't exist + app.aclPolicy = &ACLPolicy{ + Groups: Groups{"group:test": []string{"foo"}, "group:error": []string{"foo", "group:test"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"group:error"}, Ports: []string{"*:*"}}, + }, + } + err := app.UpdateACLRules() + c.Assert(errors.Is(err, errInvalidGroup), check.Equals, true) +} + +func (s *Suite) TestInvalidTagOwners(c *check.C) { + // this ACL is wrong because no tagOwners own the requested tag for the server + app.aclPolicy = &ACLPolicy{ + ACLs: []ACL{ + {Action: "accept", Users: []string{"tag:foo"}, Ports: []string{"*:*"}}, + }, + } + err := app.UpdateACLRules() + c.Assert(errors.Is(err, errInvalidTag), check.Equals, true) +} + +// this test should validate that we can expand a group in a TagOWner section and +// match properly the IP's of the related hosts. The owner is valid and the tag is also valid. +// the tag is matched in the Users section +func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { + namespace, err := app.CreateNamespace("foo") + c.Assert(err, check.IsNil) + + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + + _, err = app.GetMachine("foo", "testmachine") + c.Assert(err, check.NotNil) + b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + machine := Machine{ + ID: 0, + MachineKey: "foo", + NodeKey: "bar", + DiscoKey: "faa", + Name: "testmachine", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + + app.aclPolicy = &ACLPolicy{ + Groups: Groups{"group:test": []string{"foo", "foobar"}}, + TagOwners: TagOwners{"tag:test": []string{"bar", "group:test"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"tag:test"}, Ports: []string{"*:*"}}, + }, + } + err = app.UpdateACLRules() + c.Assert(err, check.IsNil) + c.Assert(app.aclRules, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs[0], check.Equals, "100.64.0.1") +} + +// this test should validate that we can expand a group in a TagOWner section and +// match properly the IP's of the related hosts. The owner is valid and the tag is also valid. +// the tag is matched in the Ports section +func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { + namespace, err := app.CreateNamespace("foo") + c.Assert(err, check.IsNil) + + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + + _, err = app.GetMachine("foo", "testmachine") + c.Assert(err, check.NotNil) + b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + machine := Machine{ + ID: 1, + MachineKey: "foo", + NodeKey: "bar", + DiscoKey: "faa", + Name: "testmachine", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + + app.aclPolicy = &ACLPolicy{ + Groups: Groups{"group:test": []string{"foo", "foobar"}}, + TagOwners: TagOwners{"tag:test": []string{"bar", "group:test"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"*"}, Ports: []string{"tag:test:*"}}, + }, + } + err = app.UpdateACLRules() + c.Assert(err, check.IsNil) + c.Assert(app.aclRules, check.HasLen, 1) + c.Assert(app.aclRules[0].DstPorts, check.HasLen, 1) + c.Assert(app.aclRules[0].DstPorts[0].IP, check.Equals, "100.64.0.1") +} + +// need a test with: +// tag on a host that isn't owned by a tag owners. So the namespace +// of the host should be valid +func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { + namespace, err := app.CreateNamespace("foo") + c.Assert(err, check.IsNil) + + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + + _, err = app.GetMachine("foo", "testmachine") + c.Assert(err, check.NotNil) + b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}") + machine := Machine{ + ID: 1, + MachineKey: "foo", + NodeKey: "bar", + DiscoKey: "faa", + Name: "testmachine", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + + app.aclPolicy = &ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"foo"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"foo"}, Ports: []string{"*:*"}}, + }, + } + err = app.UpdateACLRules() + c.Assert(err, check.IsNil) + c.Assert(app.aclRules, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs[0], check.Equals, "100.64.0.1") +} + +// tag on a host is owned by a tag owner, the tag is valid. +// an ACL rule is matching the tag to a namespace. It should not be valid since the +// host should be tied to the tag now. +func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { + namespace, err := app.CreateNamespace("foo") + c.Assert(err, check.IsNil) + + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + + _, err = app.GetMachine("foo", "webserver") + c.Assert(err, check.NotNil) + b := []byte("{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}") + machine := Machine{ + ID: 1, + MachineKey: "foo", + NodeKey: "bar", + DiscoKey: "faa", + Name: "webserver", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + _, err = app.GetMachine("foo", "user") + b = []byte("{\"OS\":\"debian\",\"Hostname\":\"user\"}") + c.Assert(err, check.NotNil) + machine = Machine{ + ID: 2, + MachineKey: "foo2", + NodeKey: "bar2", + DiscoKey: "faab", + Name: "user", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + + app.aclPolicy = &ACLPolicy{ + TagOwners: TagOwners{"tag:webapp": []string{"foo"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"foo"}, Ports: []string{"tag:webapp:80,443"}}, + }, + } + err = app.UpdateACLRules() + c.Assert(err, check.IsNil) + c.Logf("Rules: %v", app.aclRules) + c.Assert(app.aclRules, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 0) +} + func (s *Suite) TestPortRange(c *check.C) { err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_range.hujson") c.Assert(err, check.IsNil) diff --git a/machine_test.go b/machine_test.go index 56fdf1f..203289a 100644 --- a/machine_test.go +++ b/machine_test.go @@ -181,7 +181,7 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { MachineKey: "foo" + strconv.Itoa(index), NodeKey: "bar" + strconv.Itoa(index), DiscoKey: "faa" + strconv.Itoa(index), - IPAddress: fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1)), + IPAddresses: MachineAddresses{netaddr.MustParseIP(fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1)))}, Name: "testmachine" + strconv.Itoa(index), NamespaceID: stor[index%2].namespace.ID, Registered: true, From 97eac3b9389e5eb17dc901f15bdb4882d0e7a167 Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Sun, 6 Feb 2022 17:55:12 +0100 Subject: [PATCH 013/204] feat(acl): update frequently the aclRules This call should be done quite at each modification of a server resources like RequestTags. When a server changes it's tag we should rebuild the ACL rules. When a server is added to headscale we also should update the ACLRules. --- poll.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/poll.go b/poll.go index dd3956f..c2a51d1 100644 --- a/poll.go +++ b/poll.go @@ -91,6 +91,12 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { machine.DiscoKey = DiscoPublicKeyStripPrefix(req.DiscoKey) now := time.Now().UTC() + // update ACLRules with peer informations (to update server tags if necessary) + err = h.UpdateACLRules() + if err != nil { + log.Error().Caller().Str("func", "handleAuthKey").Str("machine", machine.Name).Err(err) + } + // From Tailscale client: // // ReadOnly is whether the client just wants to fetch the MapResponse, From de5994644790b6948d1d39b12a59dfb9931df797 Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Mon, 7 Feb 2022 16:12:05 +0100 Subject: [PATCH 014/204] feat(acls): rewrite functions to be testable Rewrite some function to get rid of the dependency on Headscale object. This allows us to write succinct test that are more easy to review and implement. The improvements of the tests allowed to write the removal of the tagged hosts from the namespace as specified here: https://tailscale.com/kb/1068/acl-tags/ --- acls.go | 187 ++++++++++-------- acls_test.go | 521 ++++++++++++++++++++++++++++++++++++++++++++++++++- machine.go | 13 ++ 3 files changed, 646 insertions(+), 75 deletions(-) diff --git a/acls.go b/acls.go index c86e315..9dd1260 100644 --- a/acls.go +++ b/acls.go @@ -2,7 +2,6 @@ package headscale import ( "encoding/json" - "errors" "fmt" "io" "os" @@ -86,6 +85,11 @@ func (h *Headscale) UpdateACLRules() error { func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { rules := []tailcfg.FilterRule{} + machines, err := h.ListAllMachines() + if err != nil { + return nil, err + } + for index, acl := range h.aclPolicy.ACLs { if acl.Action != "accept" { return nil, errInvalidAction @@ -93,7 +97,7 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { srcIPs := []string{} for innerIndex, user := range acl.Users { - srcs, err := h.generateACLPolicySrcIP(user) + srcs, err := h.generateACLPolicySrcIP(machines, *h.aclPolicy, user) if err != nil { log.Error(). Msgf("Error parsing ACL %d, User %d", index, innerIndex) @@ -105,7 +109,7 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { destPorts := []tailcfg.NetPortRange{} for innerIndex, ports := range acl.Ports { - dests, err := h.generateACLPolicyDestPorts(ports) + dests, err := h.generateACLPolicyDestPorts(machines, *h.aclPolicy, ports) if err != nil { log.Error(). Msgf("Error parsing ACL %d, Port %d", index, innerIndex) @@ -124,11 +128,13 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { return rules, nil } -func (h *Headscale) generateACLPolicySrcIP(u string) ([]string, error) { - return h.expandAlias(u) +func (h *Headscale) generateACLPolicySrcIP(machines []Machine, aclPolicy ACLPolicy, u string) ([]string, error) { + return expandAlias(machines, aclPolicy, u) } func (h *Headscale) generateACLPolicyDestPorts( + machines []Machine, + aclPolicy ACLPolicy, d string, ) ([]tailcfg.NetPortRange, error) { tokens := strings.Split(d, ":") @@ -149,11 +155,11 @@ func (h *Headscale) generateACLPolicyDestPorts( alias = fmt.Sprintf("%s:%s", tokens[0], tokens[1]) } - expanded, err := h.expandAlias(alias) + expanded, err := expandAlias(machines, aclPolicy, alias) if err != nil { return nil, err } - ports, err := h.expandPorts(tokens[len(tokens)-1]) + ports, err := expandPorts(tokens[len(tokens)-1]) if err != nil { return nil, err } @@ -177,52 +183,40 @@ func (h *Headscale) generateACLPolicyDestPorts( // - a group // - a tag // and transform these in IPAddresses -func (h *Headscale) expandAlias(alias string) ([]string, error) { +func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]string, error) { + ips := []string{} if alias == "*" { return []string{"*"}, nil } if strings.HasPrefix(alias, "group:") { - namespaces, err := h.expandGroup(alias) + namespaces, err := expandGroup(aclPolicy, alias) if err != nil { - return nil, err + return ips, err } - ips := []string{} for _, n := range namespaces { - nodes, err := h.ListMachinesInNamespace(n) - if err != nil { - return nil, errInvalidNamespace - } + nodes := listMachinesInNamespace(machines, n) for _, node := range nodes { ips = append(ips, node.IPAddresses.ToStringSlice()...) } } - return ips, nil } if strings.HasPrefix(alias, "tag:") { - var ips []string - owners, err := h.expandTagOwners(alias) + owners, err := expandTagOwners(aclPolicy, alias) if err != nil { - return nil, err + return ips, err } for _, namespace := range owners { - machines, err := h.ListMachinesInNamespace(namespace) - if err != nil { - if errors.Is(err, errNamespaceNotFound) { - continue - } else { - return nil, err - } - } + machines := listMachinesInNamespace(machines, namespace) for _, machine := range machines { if len(machine.HostInfo) == 0 { continue } hi, err := machine.GetHostInfo() if err != nil { - return nil, err + return ips, err } for _, t := range hi.RequestTags { if alias == t { @@ -234,75 +228,75 @@ func (h *Headscale) expandAlias(alias string) ([]string, error) { return ips, nil } - n, err := h.GetNamespace(alias) - if err == nil { - nodes, err := h.ListMachinesInNamespace(n.Name) - if err != nil { - return nil, err - } - ips := []string{} - for _, n := range nodes { - ips = append(ips, n.IPAddresses.ToStringSlice()...) - } - + // if alias is a namespace + nodes := listMachinesInNamespace(machines, alias) + nodes, err := excludeCorrectlyTaggedNodes(aclPolicy, nodes, alias) + if err != nil { + return ips, err + } + for _, n := range nodes { + ips = append(ips, n.IPAddresses.ToStringSlice()...) + } + if len(ips) > 0 { return ips, nil } - if h, ok := h.aclPolicy.Hosts[alias]; ok { + // if alias is an host + if h, ok := aclPolicy.Hosts[alias]; ok { return []string{h.String()}, nil } + // if alias is an IP ip, err := netaddr.ParseIP(alias) if err == nil { return []string{ip.String()}, nil } + // if alias is an CIDR cidr, err := netaddr.ParseIPPrefix(alias) if err == nil { return []string{cidr.String()}, nil } - return nil, errInvalidUserSection + return ips, errInvalidUserSection } -// expandTagOwners will return a list of namespace. An owner can be either a namespace or a group -// a group cannot be composed of groups -func (h *Headscale) expandTagOwners(owner string) ([]string, error) { - var owners []string - ows, ok := h.aclPolicy.TagOwners[owner] - if !ok { - return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, owner) +// excludeCorrectlyTaggedNodes will remove from the list of input nodes the ones +// that are correctly tagged since they should not be listed as being in the namespace +// we assume in this function that we only have nodes from 1 namespace. +func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace string) ([]Machine, error) { + out := []Machine{} + tags := []string{} + for tag, ns := range aclPolicy.TagOwners { + if containsString(ns, namespace) { + tags = append(tags, tag) + } } - for _, ow := range ows { - if strings.HasPrefix(ow, "group:") { - gs, err := h.expandGroup(ow) - if err != nil { - return []string{}, err + // for each machine if tag is in tags list, don't append it. + for _, machine := range nodes { + if len(machine.HostInfo) == 0 { + out = append(out, machine) + continue + } + hi, err := machine.GetHostInfo() + if err != nil { + return out, err + } + found := false + for _, t := range hi.RequestTags { + if containsString(tags, t) { + found = true + break } - owners = append(owners, gs...) - } else { - owners = append(owners, ow) + } + if !found { + out = append(out, machine) } } - return owners, nil + return out, nil } -// expandGroup will return the list of namespace inside the group -// after some validation -func (h *Headscale) expandGroup(group string) ([]string, error) { - gs, ok := h.aclPolicy.Groups[group] - if !ok { - return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) - } - for _, g := range gs { - if strings.HasPrefix(g, "group:") { - return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) - } - } - return gs, nil -} - -func (h *Headscale) expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { +func expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { if portsStr == "*" { return &[]tailcfg.PortRange{ {First: portRangeBegin, Last: portRangeEnd}, @@ -344,3 +338,50 @@ func (h *Headscale) expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { return &ports, nil } + +func listMachinesInNamespace(machines []Machine, namespace string) []Machine { + out := []Machine{} + for _, machine := range machines { + if machine.Namespace.Name == namespace { + out = append(out, machine) + } + } + return out +} + +// expandTagOwners will return a list of namespace. An owner can be either a namespace or a group +// a group cannot be composed of groups +func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { + var owners []string + ows, ok := aclPolicy.TagOwners[tag] + if !ok { + return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, tag) + } + for _, ow := range ows { + if strings.HasPrefix(ow, "group:") { + gs, err := expandGroup(aclPolicy, ow) + if err != nil { + return []string{}, err + } + owners = append(owners, gs...) + } else { + owners = append(owners, ow) + } + } + return owners, nil +} + +// expandGroup will return the list of namespace inside the group +// after some validation +func expandGroup(aclPolicy ACLPolicy, group string) ([]string, error) { + gs, ok := aclPolicy.Groups[group] + if !ok { + return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) + } + for _, g := range gs { + if strings.HasPrefix(g, "group:") { + return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) + } + } + return gs, nil +} diff --git a/acls_test.go b/acls_test.go index f2fb6a0..8bedb47 100644 --- a/acls_test.go +++ b/acls_test.go @@ -2,10 +2,13 @@ package headscale import ( "errors" + "reflect" + "testing" "gopkg.in/check.v1" "gorm.io/datatypes" "inet.af/netaddr" + "tailscale.com/tailcfg" ) func (s *Suite) TestWrongPath(c *check.C) { @@ -267,9 +270,16 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { } err = app.UpdateACLRules() c.Assert(err, check.IsNil) - c.Logf("Rules: %v", app.aclRules) c.Assert(app.aclRules, check.HasLen, 1) - c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 0) + c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs[0], check.Equals, "100.64.0.2") + c.Assert(app.aclRules[0].DstPorts, check.HasLen, 2) + c.Assert(app.aclRules[0].DstPorts[0].Ports.First, check.Equals, uint16(80)) + c.Assert(app.aclRules[0].DstPorts[0].Ports.Last, check.Equals, uint16(80)) + c.Assert(app.aclRules[0].DstPorts[0].IP, check.Equals, "100.64.0.1") + c.Assert(app.aclRules[0].DstPorts[1].Ports.First, check.Equals, uint16(443)) + c.Assert(app.aclRules[0].DstPorts[1].Ports.Last, check.Equals, uint16(443)) + c.Assert(app.aclRules[0].DstPorts[1].IP, check.Equals, "100.64.0.1") } func (s *Suite) TestPortRange(c *check.C) { @@ -385,3 +395,510 @@ func (s *Suite) TestPortGroup(c *check.C) { c.Assert(len(ips), check.Equals, 1) c.Assert(rules[0].SrcIPs[0], check.Equals, ips[0].String()) } + +func Test_expandGroup(t *testing.T) { + type args struct { + aclPolicy ACLPolicy + group string + } + tests := []struct { + name string + args args + want []string + wantErr bool + }{ + { + name: "simple test", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:test": []string{"g1", "foo", "test"}, "group:foo": []string{"foo", "test"}}, + }, + group: "group:test", + }, + want: []string{"g1", "foo", "test"}, + wantErr: false, + }, + { + name: "InexistantGroup", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:test": []string{"g1", "foo", "test"}, "group:foo": []string{"foo", "test"}}, + }, + group: "group:bar", + }, + want: []string{}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := expandGroup(tt.args.aclPolicy, tt.args.group) + if (err != nil) != tt.wantErr { + t.Errorf("expandGroup() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("expandGroup() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_expandTagOwners(t *testing.T) { + type args struct { + aclPolicy ACLPolicy + tag string + } + tests := []struct { + name string + args args + want []string + wantErr bool + }{ + { + name: "simple tag", + args: args{ + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"namespace1"}}, + }, + tag: "tag:test", + }, + want: []string{"namespace1"}, + wantErr: false, + }, + { + name: "tag and group", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"n1", "bar"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo"}}, + }, + tag: "tag:test", + }, + want: []string{"n1", "bar"}, + wantErr: false, + }, + { + name: "namespace and group", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"n1", "bar"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo", "home"}}, + }, + tag: "tag:test", + }, + want: []string{"n1", "bar", "home"}, + wantErr: false, + }, + { + name: "invalid tag", + args: args{ + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:foo": []string{"group:foo", "home"}}, + }, + tag: "tag:test", + }, + want: []string{}, + wantErr: true, + }, + { + name: "invalid group", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:bar": []string{"n1", "foo"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo", "home"}}, + }, + tag: "tag:test", + }, + want: []string{}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := expandTagOwners(tt.args.aclPolicy, tt.args.tag) + if (err != nil) != tt.wantErr { + t.Errorf("expandTagOwners() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("expandTagOwners() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_expandPorts(t *testing.T) { + type args struct { + portsStr string + } + tests := []struct { + name string + args args + want *[]tailcfg.PortRange + wantErr bool + }{ + { + name: "wildcard", + args: args{portsStr: "*"}, + want: &[]tailcfg.PortRange{ + {First: portRangeBegin, Last: portRangeEnd}, + }, + wantErr: false, + }, + { + name: "two ports", + args: args{portsStr: "80,443"}, + want: &[]tailcfg.PortRange{ + {First: 80, Last: 80}, + {First: 443, Last: 443}, + }, + wantErr: false, + }, + { + name: "a range and a port", + args: args{portsStr: "80-1024,443"}, + want: &[]tailcfg.PortRange{ + {First: 80, Last: 1024}, + {First: 443, Last: 443}, + }, + wantErr: false, + }, + { + name: "out of bounds", + args: args{portsStr: "854038"}, + want: nil, + wantErr: true, + }, + { + name: "wrong port", + args: args{portsStr: "85a38"}, + want: nil, + wantErr: true, + }, + { + name: "wrong port in first", + args: args{portsStr: "a-80"}, + want: nil, + wantErr: true, + }, + { + name: "wrong port in last", + args: args{portsStr: "80-85a38"}, + want: nil, + wantErr: true, + }, + { + name: "wrong port format", + args: args{portsStr: "80-85a38-3"}, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := expandPorts(tt.args.portsStr) + if (err != nil) != tt.wantErr { + t.Errorf("expandPorts() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("expandPorts() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_listMachinesInNamespace(t *testing.T) { + type args struct { + machines []Machine + namespace string + } + tests := []struct { + name string + args args + want []Machine + }{ + { + name: "1 machine in namespace", + args: args{ + machines: []Machine{ + {Namespace: Namespace{Name: "test"}}, + }, + namespace: "test", + }, + want: []Machine{ + {Namespace: Namespace{Name: "test"}}, + }, + }, + { + name: "3 machines, 2 in namespace", + args: args{ + machines: []Machine{ + {ID: 1, Namespace: Namespace{Name: "test"}}, + {ID: 2, Namespace: Namespace{Name: "foo"}}, + {ID: 3, Namespace: Namespace{Name: "foo"}}, + }, + namespace: "foo", + }, + want: []Machine{ + {ID: 2, Namespace: Namespace{Name: "foo"}}, + {ID: 3, Namespace: Namespace{Name: "foo"}}, + }, + }, + { + name: "5 machines, 0 in namespace", + args: args{ + machines: []Machine{ + {ID: 1, Namespace: Namespace{Name: "test"}}, + {ID: 2, Namespace: Namespace{Name: "foo"}}, + {ID: 3, Namespace: Namespace{Name: "foo"}}, + {ID: 4, Namespace: Namespace{Name: "foo"}}, + {ID: 5, Namespace: Namespace{Name: "foo"}}, + }, + namespace: "bar", + }, + want: []Machine{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := listMachinesInNamespace(tt.args.machines, tt.args.namespace); !reflect.DeepEqual(got, tt.want) { + t.Errorf("listMachinesInNamespace() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_expandAlias(t *testing.T) { + type args struct { + machines []Machine + aclPolicy ACLPolicy + alias string + } + tests := []struct { + name string + args args + want []string + wantErr bool + }{ + { + name: "wildcard", + args: args{ + alias: "*", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.78.84.227")}}, + }, + aclPolicy: ACLPolicy{}, + }, + want: []string{"*"}, + wantErr: false, + }, + { + name: "simple group", + args: args{ + alias: "group:foo", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + }, + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"foo", "bar"}}, + }, + }, + want: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + wantErr: false, + }, + { + name: "wrong group", + args: args{ + alias: "group:test", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + }, + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"foo", "bar"}}, + }, + }, + want: []string{}, + wantErr: true, + }, + { + name: "simple ipaddress", + args: args{ + alias: "10.0.0.3", + machines: []Machine{}, + aclPolicy: ACLPolicy{}, + }, + want: []string{"10.0.0.3"}, + wantErr: false, + }, + { + name: "private network", + args: args{ + alias: "homeNetwork", + machines: []Machine{}, + aclPolicy: ACLPolicy{ + Hosts: Hosts{"homeNetwork": netaddr.MustParseIPPrefix("192.168.1.0/24")}, + }, + }, + want: []string{"192.168.1.0/24"}, + wantErr: false, + }, + { + name: "simple host", + args: args{ + alias: "10.0.0.1", + machines: []Machine{}, + aclPolicy: ACLPolicy{}, + }, + want: []string{"10.0.0.1"}, + wantErr: false, + }, + { + name: "simple CIDR", + args: args{ + alias: "10.0.0.0/16", + machines: []Machine{}, + aclPolicy: ACLPolicy{}, + }, + want: []string{"10.0.0.0/16"}, + wantErr: false, + }, + { + name: "simple tag", + args: args{ + alias: "tag:test", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"foo"}}, + }, + }, + want: []string{"100.64.0.1", "100.64.0.2"}, + wantErr: false, + }, + { + name: "No tag defined", + args: args{ + alias: "tag:foo", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + }, + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"foo", "bar"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo"}}, + }, + }, + want: []string{}, + wantErr: true, + }, + { + name: "list host in namespace without correctly tagged servers", + args: args{ + alias: "foo", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"foo"}}, + }, + }, + want: []string{"100.64.0.4"}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := expandAlias(tt.args.machines, tt.args.aclPolicy, tt.args.alias) + if (err != nil) != tt.wantErr { + t.Errorf("expandAlias() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("expandAlias() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_excludeCorrectlyTaggedNodes(t *testing.T) { + type args struct { + aclPolicy ACLPolicy + nodes []Machine + namespace string + } + tests := []struct { + name string + args args + want []Machine + wantErr bool + }{ + { + name: "exclude nodes with valid tags", + args: args{ + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"foo"}}, + }, + nodes: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + namespace: "foo", + }, + want: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + wantErr: false, + }, + { + name: "all nodes have invalid tags, don't exclude them", + args: args{ + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:foo": []string{"foo"}}, + }, + nodes: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + namespace: "foo", + }, + want: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := excludeCorrectlyTaggedNodes(tt.args.aclPolicy, tt.args.nodes, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("excludeCorrectlyTaggedNodes() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("excludeCorrectlyTaggedNodes() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/machine.go b/machine.go index 231c179..01fc927 100644 --- a/machine.go +++ b/machine.go @@ -119,6 +119,19 @@ func (machine Machine) isExpired() bool { return time.Now().UTC().After(*machine.Expiry) } +func (h *Headscale) ListAllMachines() ([]Machine, error) { + machines := []Machine{} + if err := h.db.Preload("AuthKey"). + Preload("AuthKey.Namespace"). + Preload("Namespace"). + Where("registered"). + Find(&machines).Error; err != nil { + return nil, err + } + + return machines, nil +} + func containsAddresses(inputs []string, addrs MachineAddresses) bool { for _, addr := range addrs.ToStringSlice() { if containsString(inputs, addr) { From 7b5ba9f78156b7ef1abe3abf9bc0d731396488b5 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 13:54:44 +0100 Subject: [PATCH 015/204] docs(acl): add configuration example to explain acls --- docs/README.md | 8 ++++ docs/acls.md | 126 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 docs/acls.md diff --git a/docs/README.md b/docs/README.md index 1ac1522..4b5d084 100644 --- a/docs/README.md +++ b/docs/README.md @@ -39,6 +39,14 @@ use namespaces (which are the equivalent to user/logins in Tailscale.com). Please check https://tailscale.com/kb/1018/acls/, and `./tests/acls/` in this repo for working examples. +When using ACL's the Namespace borders are no longer applied. All machines +whichever the Namespace have the ability to communicate with other hosts as +long as the ACL's permits this exchange. + +The [ACLs](acls.md) document should help understand a fictional case of setting +up ACLs in a small company. All concepts presented in this document could be +applied outside of business oriented usage. + ### Apple devices An endpoint with information on how to connect your Apple devices (currently macOS only) is available at `/apple` on your running instance. diff --git a/docs/acls.md b/docs/acls.md new file mode 100644 index 0000000..89e8b55 --- /dev/null +++ b/docs/acls.md @@ -0,0 +1,126 @@ + +# ACLs use case example + +Let's build an example use case for a small business (It may be the place where +ACL's are the most useful). + +We have a small company with a boss, an admin, two developers and an intern. + +The boss should have access to all servers but not to the users hosts. Admin +should also have access to all hosts except that their permissions should be +limited to maintaining the hosts (for example purposes). The developers can do +anything they want on dev hosts, but only watch on productions hosts. Intern +can only interact with the development servers. + +Each user have at least a device connected to the network and we have some +servers. + +- database.prod +- database.dev +- app-server1.prod +- app-server1.dev +- billing.internal + +## Setup of the network + +Let's create the namespaces. Each user should have his own namespace. The users +here are represented as namespaces. + +```bash +headscale namespaces create boss +headscale namespaces create admin1 +headscale namespaces create dev1 +headscale namespaces create dev2 +headscale namespaces create intern1 +``` + +We don't need to create namespaces for the servers because the servers will be +tagged. When registering the servers we will need to add the flag +`--advertised-tags=tag:,tag:`, and the user (namespace) that is +registering the server should be allowed to do it. Since anyone can add tags to +a server they can register, the check of the tags is done on headscale server +and only valid tags are applied. A tag is valid if the namespace that is +registering it is allowed to do it. + +Here are the ACL's to implement the same permissions as above: + +```json +{ + // groups are collections of users having a common scope. A user can be in multiple groups + // groups cannot be composed of groups + "groups": { + "group:boss": ["boss"], + "group:dev": ["dev1","dev2"], + "group:admin": ["admin1"], + "group:intern": ["intern1"], + }, + // tagOwners in tailscale is an association between a TAG and the people allowed to set this TAG on a server. + // This is documented [here](https://tailscale.com/kb/1068/acl-tags#defining-a-tag) + // and explained [here](https://tailscale.com/blog/rbac-like-it-was-meant-to-be/) + "tagOwners": { + // the administrators can add servers in production + "tag:prod-databases": ["group:admin"], + "tag:prod-app-servers": ["group:admin"], + + // the boss can tag any server as internal + "tag:internal": ["group:boss"], + + // dev can add servers for dev purposes as well as admins + "tag:dev-databases": ["group:admin","group:dev"], + "tag:dev-app-servers": ["group:admin", "group:dev"], + + // interns cannot add servers + }, + "acls": [ + // boss have access to all servers + {"action":"accept", + "users":["group:boss"], + "ports":[ + "tag:prod-databases:*", + "tag:prod-app-servers:*", + "tag:internal:*", + "tag:dev-databases:*", + "tag:dev-app-servers:*", + ] + }, + + // admin have only access to administrative ports of the servers + {"action":"accept", + "users":["group:admin"], + "ports":[ + "tag:prod-databases:22", + "tag:prod-app-servers:22", + "tag:internal:22", + "tag:dev-databases:22", + "tag:dev-app-servers:22", + ] + }, + + // developers have access to databases servers and application servers on all ports + // they can only view the applications servers in prod and have no access to databases servers in production + {"action":"accept", "users":["group:dev"], "ports":[ + "tag:dev-databases:*", + "tag:dev-app-servers:*", + "tag:prod-app-servers:80,443", + ] + }, + + // servers should be able to talk to database. Database should not be able to initiate connections to + // applications servers + {"action":"accept", "users":["tag:dev-app-servers"], "ports":["tag:dev-databases:5432"]}, + {"action":"accept", "users":["tag:prod-app-servers"], "ports":["tag:prod-databases:5432"]}, + + // interns have access to dev-app-servers only in reading mode + {"action":"accept", "users":["group:intern"], "ports":["tag:dev-app-servers:80,443"]}, + + // We still have to allow internal namespaces communications since nothing guarantees that each user have + // their own namespaces. + {"action":"accept", "users":["boss"], "ports":["boss:*"]}, + {"action":"accept", "users":["dev1"], "ports":["dev1:*"]}, + {"action":"accept", "users":["dev2"], "ports":["dev2:*"]}, + {"action":"accept", "users":["admin1"], "ports":["admin1:*"]}, + {"action":"accept", "users":["intern1"], "ports":["intern1:*"]}, + ] +} +``` + From aceaba60f174703eedefa2b9775e8c4026000988 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 14:02:18 +0100 Subject: [PATCH 016/204] docs(changelog): bump changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e4416..1642701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ **TBD (TBD):** +**BREAKING**: +- ACLs have been rewritten and the behavior is different from before. It's now more aligned to tailscale's view of the feature. Namespaces are viewed as users and can communicate with each others. Tags should now work correctly and adding a host to Headscale should now reload the rules. The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features. + + **0.13.0 (2022-xx-xx):** **Features**: From 9cedbbafd46ad3034967a25f1901f8fe04ee4bf7 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 15:26:54 +0100 Subject: [PATCH 017/204] chore(all): update some files for linter --- acls.go | 31 +++++++++------ acls_test.go | 101 +++++++++++++++++++++++++----------------------- api.go | 22 ++++++++++- dns.go | 4 +- machine.go | 13 ++++--- machine_test.go | 3 +- poll.go | 17 +++++++- 7 files changed, 118 insertions(+), 73 deletions(-) diff --git a/acls.go b/acls.go index 9dd1260..3d6b194 100644 --- a/acls.go +++ b/acls.go @@ -20,7 +20,6 @@ const ( errInvalidUserSection = Error("invalid user section") errInvalidGroup = Error("invalid group") errInvalidTag = Error("invalid tag") - errInvalidNamespace = Error("invalid namespace") errInvalidPortFormat = Error("invalid port format") ) @@ -69,6 +68,7 @@ func (h *Headscale) LoadACLPolicy(path string) error { } h.aclPolicy = &policy + return h.UpdateACLRules() } @@ -79,6 +79,7 @@ func (h *Headscale) UpdateACLRules() error { } log.Trace().Interface("ACL", rules).Msg("ACL rules generated") h.aclRules = rules + return nil } @@ -182,7 +183,7 @@ func (h *Headscale) generateACLPolicyDestPorts( // - a namespace // - a group // - a tag -// and transform these in IPAddresses +// and transform these in IPAddresses. func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]string, error) { ips := []string{} if alias == "*" { @@ -200,6 +201,7 @@ func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]strin ips = append(ips, node.IPAddresses.ToStringSlice()...) } } + return ips, nil } @@ -225,6 +227,7 @@ func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]strin } } } + return ips, nil } @@ -276,6 +279,7 @@ func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace for _, machine := range nodes { if len(machine.HostInfo) == 0 { out = append(out, machine) + continue } hi, err := machine.GetHostInfo() @@ -286,6 +290,7 @@ func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace for _, t := range hi.RequestTags { if containsString(tags, t) { found = true + break } } @@ -293,6 +298,7 @@ func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace out = append(out, machine) } } + return out, nil } @@ -346,42 +352,45 @@ func listMachinesInNamespace(machines []Machine, namespace string) []Machine { out = append(out, machine) } } + return out } // expandTagOwners will return a list of namespace. An owner can be either a namespace or a group -// a group cannot be composed of groups +// a group cannot be composed of groups. func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { var owners []string ows, ok := aclPolicy.TagOwners[tag] if !ok { return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, tag) } - for _, ow := range ows { - if strings.HasPrefix(ow, "group:") { - gs, err := expandGroup(aclPolicy, ow) + for _, owner := range ows { + if strings.HasPrefix(owner, "group:") { + gs, err := expandGroup(aclPolicy, owner) if err != nil { return []string{}, err } owners = append(owners, gs...) } else { - owners = append(owners, ow) + owners = append(owners, owner) } } + return owners, nil } // expandGroup will return the list of namespace inside the group -// after some validation +// after some validation. func expandGroup(aclPolicy ACLPolicy, group string) ([]string, error) { - gs, ok := aclPolicy.Groups[group] + groups, ok := aclPolicy.Groups[group] if !ok { return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) } - for _, g := range gs { + for _, g := range groups { if strings.HasPrefix(g, "group:") { return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) } } - return gs, nil + + return groups, nil } diff --git a/acls_test.go b/acls_test.go index 8bedb47..786de0f 100644 --- a/acls_test.go +++ b/acls_test.go @@ -94,7 +94,7 @@ func (s *Suite) TestInvalidTagOwners(c *check.C) { // this test should validate that we can expand a group in a TagOWner section and // match properly the IP's of the related hosts. The owner is valid and the tag is also valid. -// the tag is matched in the Users section +// the tag is matched in the Users section. func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { namespace, err := app.CreateNamespace("foo") c.Assert(err, check.IsNil) @@ -104,7 +104,7 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") machine := Machine{ ID: 0, MachineKey: "foo", @@ -116,7 +116,7 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) @@ -136,7 +136,7 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { // this test should validate that we can expand a group in a TagOWner section and // match properly the IP's of the related hosts. The owner is valid and the tag is also valid. -// the tag is matched in the Ports section +// the tag is matched in the Ports section. func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { namespace, err := app.CreateNamespace("foo") c.Assert(err, check.IsNil) @@ -146,7 +146,7 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") machine := Machine{ ID: 1, MachineKey: "foo", @@ -158,7 +158,7 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) @@ -178,7 +178,7 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { // need a test with: // tag on a host that isn't owned by a tag owners. So the namespace -// of the host should be valid +// of the host should be valid. func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { namespace, err := app.CreateNamespace("foo") c.Assert(err, check.IsNil) @@ -188,7 +188,7 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}") + hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}") machine := Machine{ ID: 1, MachineKey: "foo", @@ -200,7 +200,7 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) @@ -229,7 +229,7 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { _, err = app.GetMachine("foo", "webserver") c.Assert(err, check.NotNil) - b := []byte("{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}") + hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}") machine := Machine{ ID: 1, MachineKey: "foo", @@ -241,11 +241,11 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) _, err = app.GetMachine("foo", "user") - b = []byte("{\"OS\":\"debian\",\"Hostname\":\"user\"}") + hostInfo = []byte("{\"OS\":\"debian\",\"Hostname\":\"user\"}") c.Assert(err, check.NotNil) machine = Machine{ ID: 2, @@ -258,7 +258,7 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) @@ -430,15 +430,16 @@ func Test_expandGroup(t *testing.T) { wantErr: true, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := expandGroup(tt.args.aclPolicy, tt.args.group) - if (err != nil) != tt.wantErr { - t.Errorf("expandGroup() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := expandGroup(test.args.aclPolicy, test.args.group) + if (err != nil) != test.wantErr { + t.Errorf("expandGroup() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("expandGroup() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("expandGroup() = %v, want %v", got, test.want) } }) } @@ -514,15 +515,16 @@ func Test_expandTagOwners(t *testing.T) { wantErr: true, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := expandTagOwners(tt.args.aclPolicy, tt.args.tag) - if (err != nil) != tt.wantErr { - t.Errorf("expandTagOwners() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := expandTagOwners(test.args.aclPolicy, test.args.tag) + if (err != nil) != test.wantErr { + t.Errorf("expandTagOwners() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("expandTagOwners() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("expandTagOwners() = %v, want %v", got, test.want) } }) } @@ -595,15 +597,16 @@ func Test_expandPorts(t *testing.T) { wantErr: true, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := expandPorts(tt.args.portsStr) - if (err != nil) != tt.wantErr { - t.Errorf("expandPorts() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := expandPorts(test.args.portsStr) + if (err != nil) != test.wantErr { + t.Errorf("expandPorts() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("expandPorts() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("expandPorts() = %v, want %v", got, test.want) } }) } @@ -824,15 +827,16 @@ func Test_expandAlias(t *testing.T) { wantErr: false, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := expandAlias(tt.args.machines, tt.args.aclPolicy, tt.args.alias) - if (err != nil) != tt.wantErr { - t.Errorf("expandAlias() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := expandAlias(test.args.machines, test.args.aclPolicy, test.args.alias) + if (err != nil) != test.wantErr { + t.Errorf("expandAlias() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("expandAlias() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("expandAlias() = %v, want %v", got, test.want) } }) } @@ -889,15 +893,16 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { wantErr: false, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := excludeCorrectlyTaggedNodes(tt.args.aclPolicy, tt.args.nodes, tt.args.namespace) - if (err != nil) != tt.wantErr { - t.Errorf("excludeCorrectlyTaggedNodes() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := excludeCorrectlyTaggedNodes(test.args.aclPolicy, test.args.nodes, test.args.namespace) + if (err != nil) != test.wantErr { + t.Errorf("excludeCorrectlyTaggedNodes() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("excludeCorrectlyTaggedNodes() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("excludeCorrectlyTaggedNodes() = %v, want %v", got, test.want) } }) } diff --git a/api.go b/api.go index 020ded0..073be5e 100644 --- a/api.go +++ b/api.go @@ -261,7 +261,16 @@ func (h *Headscale) getMapResponse( var respBody []byte if req.Compress == "zstd" { - src, _ := json.Marshal(resp) + src, err := json.Marshal(resp) + if err != nil { + log.Error(). + Caller(). + Str("func", "getMapResponse"). + Err(err). + Msg("Failed to marshal response for the client") + + return nil, err + } encoder, _ := zstd.NewWriter(nil) srcCompressed := encoder.EncodeAll(src, nil) @@ -290,7 +299,16 @@ func (h *Headscale) getMapKeepAliveResponse( var respBody []byte var err error if mapRequest.Compress == "zstd" { - src, _ := json.Marshal(mapResponse) + src, err := json.Marshal(mapResponse) + if err != nil { + log.Error(). + Caller(). + Str("func", "getMapKeepAliveResponse"). + Err(err). + Msg("Failed to marshal keepalive response for the client") + + return nil, err + } encoder, _ := zstd.NewWriter(nil) srcCompressed := encoder.EncodeAll(src, nil) respBody = h.privateKey.SealTo(machineKey, srcCompressed) diff --git a/dns.go b/dns.go index 37daa88..085a14e 100644 --- a/dns.go +++ b/dns.go @@ -165,7 +165,7 @@ func getMapResponseDNSConfig( dnsConfig.Domains, fmt.Sprintf( "%s.%s", - strings.Replace(machine.Namespace.Name, "@", ".", -1), // Replace @ with . for valid domain for machine + strings.ReplaceAll(machine.Namespace.Name, "@", "."), // Replace @ with . for valid domain for machine baseDomain, ), ) @@ -176,7 +176,7 @@ func getMapResponseDNSConfig( namespaceSet.Add(p.Namespace) } for _, namespace := range namespaceSet.List() { - dnsRoute := fmt.Sprintf("%s.%s", namespace.(Namespace).Name, baseDomain) + var dnsRoute string = fmt.Sprintf("%v.%v", namespace.(Namespace).Name, baseDomain) dnsConfig.Routes[dnsRoute] = nil } } else { diff --git a/machine.go b/machine.go index 01fc927..cb70bf1 100644 --- a/machine.go +++ b/machine.go @@ -138,6 +138,7 @@ func containsAddresses(inputs []string, addrs MachineAddresses) bool { return true } } + return false } @@ -174,20 +175,20 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { // In order to do this we would need to be able to identify that node A want to talk to node B but that Node B doesn't know // how to talk to node A and then add the peering resource. - for _, m := range machines { + for _, mchn := range machines { for _, rule := range h.aclRules { var dst []string for _, d := range rule.DstPorts { dst = append(dst, d.IP) } - if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, m.IPAddresses) || containsString(dst, "*"))) || - (containsAddresses(rule.SrcIPs, m.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { - mMachines[m.ID] = m + if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, mchn.IPAddresses) || containsString(dst, "*"))) || + (containsAddresses(rule.SrcIPs, mchn.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { + mMachines[mchn.ID] = mchn } } } - var authorizedMachines Machines + authorizedMachines := make([]Machine, 0, len(mMachines)) for _, m := range mMachines { authorizedMachines = append(authorizedMachines, m) } @@ -694,7 +695,7 @@ func (machine Machine) toNode( hostname = fmt.Sprintf( "%s.%s.%s", machine.Name, - strings.Replace(machine.Namespace.Name, "@", ".", -1), // Replace @ with . for valid domain for machine + strings.ReplaceAll(machine.Namespace.Name, "@", "."), // Replace @ with . for valid domain for machine baseDomain, ) } else { diff --git a/machine_test.go b/machine_test.go index 203289a..df00067 100644 --- a/machine_test.go +++ b/machine_test.go @@ -161,7 +161,7 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { key *PreAuthKey } - var stor []base + stor := make([]base, 0) for _, name := range []string{"test", "admin"} { namespace, err := app.CreateNamespace(name) @@ -169,7 +169,6 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) stor = append(stor, base{namespace, pak}) - } _, err := app.GetMachineByID(0) diff --git a/poll.go b/poll.go index c2a51d1..f00f748 100644 --- a/poll.go +++ b/poll.go @@ -85,7 +85,10 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { Str("machine", machine.Name). Msg("Found machine in database") - hostinfo, _ := json.Marshal(req.Hostinfo) + hostinfo, err := json.Marshal(req.Hostinfo) + if err != nil { + return + } machine.Name = req.Hostinfo.Hostname machine.HostInfo = datatypes.JSON(hostinfo) machine.DiscoKey = DiscoPublicKeyStripPrefix(req.DiscoKey) @@ -106,7 +109,17 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { // The intended use is for clients to discover the DERP map at start-up // before their first real endpoint update. if !req.ReadOnly { - endpoints, _ := json.Marshal(req.Endpoints) + endpoints, err := json.Marshal(req.Endpoints) + if err != nil { + log.Error(). + Caller(). + Str("func", "PollNetMapHandler"). + Err(err). + Msg("Failed to mashal requested endpoints for the client") + ctx.String(http.StatusInternalServerError, ":(") + + return + } machine.Endpoints = datatypes.JSON(endpoints) machine.LastSeen = &now } From d8c4c3163b6fe9bba05fa2dd2566910ebf749c31 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 15:54:51 +0100 Subject: [PATCH 018/204] chore(fmt): apply make fmt command --- CHANGELOG.md | 2 +- acls.go | 35 +++++- acls_test.go | 302 +++++++++++++++++++++++++++++++++++++++++------- dns.go | 6 +- docs/acls.md | 155 ++++++++++++++----------- machine.go | 11 +- machine_test.go | 12 +- poll.go | 6 +- 8 files changed, 399 insertions(+), 130 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1642701..62808b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,8 @@ **TBD (TBD):** **BREAKING**: -- ACLs have been rewritten and the behavior is different from before. It's now more aligned to tailscale's view of the feature. Namespaces are viewed as users and can communicate with each others. Tags should now work correctly and adding a host to Headscale should now reload the rules. The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features. +- ACLs have been rewritten and the behavior is different from before. It's now more aligned to tailscale's view of the feature. Namespaces are viewed as users and can communicate with each others. Tags should now work correctly and adding a host to Headscale should now reload the rules. The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features. **0.13.0 (2022-xx-xx):** diff --git a/acls.go b/acls.go index 3d6b194..d5d3988 100644 --- a/acls.go +++ b/acls.go @@ -129,7 +129,11 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { return rules, nil } -func (h *Headscale) generateACLPolicySrcIP(machines []Machine, aclPolicy ACLPolicy, u string) ([]string, error) { +func (h *Headscale) generateACLPolicySrcIP( + machines []Machine, + aclPolicy ACLPolicy, + u string, +) ([]string, error) { return expandAlias(machines, aclPolicy, u) } @@ -184,7 +188,11 @@ func (h *Headscale) generateACLPolicyDestPorts( // - a group // - a tag // and transform these in IPAddresses. -func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]string, error) { +func expandAlias( + machines []Machine, + aclPolicy ACLPolicy, + alias string, +) ([]string, error) { ips := []string{} if alias == "*" { return []string{"*"}, nil @@ -267,7 +275,11 @@ func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]strin // excludeCorrectlyTaggedNodes will remove from the list of input nodes the ones // that are correctly tagged since they should not be listed as being in the namespace // we assume in this function that we only have nodes from 1 namespace. -func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace string) ([]Machine, error) { +func excludeCorrectlyTaggedNodes( + aclPolicy ACLPolicy, + nodes []Machine, + namespace string, +) ([]Machine, error) { out := []Machine{} tags := []string{} for tag, ns := range aclPolicy.TagOwners { @@ -362,7 +374,11 @@ func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { var owners []string ows, ok := aclPolicy.TagOwners[tag] if !ok { - return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, tag) + return []string{}, fmt.Errorf( + "%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", + errInvalidTag, + tag, + ) } for _, owner := range ows { if strings.HasPrefix(owner, "group:") { @@ -384,11 +400,18 @@ func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { func expandGroup(aclPolicy ACLPolicy, group string) ([]string, error) { groups, ok := aclPolicy.Groups[group] if !ok { - return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) + return []string{}, fmt.Errorf( + "group %v isn't registered. %w", + group, + errInvalidGroup, + ) } for _, g := range groups { if strings.HasPrefix(g, "group:") { - return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) + return []string{}, fmt.Errorf( + "%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", + errInvalidGroup, + ) } } diff --git a/acls_test.go b/acls_test.go index 786de0f..f8407d4 100644 --- a/acls_test.go +++ b/acls_test.go @@ -72,7 +72,10 @@ func (s *Suite) TestInvalidAction(c *check.C) { func (s *Suite) TestInvalidGroupInGroup(c *check.C) { // this ACL is wrong because the group in users sections doesn't exist app.aclPolicy = &ACLPolicy{ - Groups: Groups{"group:test": []string{"foo"}, "group:error": []string{"foo", "group:test"}}, + Groups: Groups{ + "group:test": []string{"foo"}, + "group:error": []string{"foo", "group:test"}, + }, ACLs: []ACL{ {Action: "accept", Users: []string{"group:error"}, Ports: []string{"*:*"}}, }, @@ -104,7 +107,9 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + hostInfo := []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ) machine := Machine{ ID: 0, MachineKey: "foo", @@ -146,7 +151,9 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + hostInfo := []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ) machine := Machine{ ID: 1, MachineKey: "foo", @@ -188,7 +195,9 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}") + hostInfo := []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}", + ) machine := Machine{ ID: 1, MachineKey: "foo", @@ -229,7 +238,9 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { _, err = app.GetMachine("foo", "webserver") c.Assert(err, check.NotNil) - hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}") + hostInfo := []byte( + "{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}", + ) machine := Machine{ ID: 1, MachineKey: "foo", @@ -265,7 +276,11 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { app.aclPolicy = &ACLPolicy{ TagOwners: TagOwners{"tag:webapp": []string{"foo"}}, ACLs: []ACL{ - {Action: "accept", Users: []string{"foo"}, Ports: []string{"tag:webapp:80,443"}}, + { + Action: "accept", + Users: []string{"foo"}, + Ports: []string{"tag:webapp:80,443"}, + }, }, } err = app.UpdateACLRules() @@ -411,7 +426,10 @@ func Test_expandGroup(t *testing.T) { name: "simple test", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:test": []string{"g1", "foo", "test"}, "group:foo": []string{"foo", "test"}}, + Groups: Groups{ + "group:test": []string{"g1", "foo", "test"}, + "group:foo": []string{"foo", "test"}, + }, }, group: "group:test", }, @@ -422,7 +440,10 @@ func Test_expandGroup(t *testing.T) { name: "InexistantGroup", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:test": []string{"g1", "foo", "test"}, "group:foo": []string{"foo", "test"}}, + Groups: Groups{ + "group:test": []string{"g1", "foo", "test"}, + "group:foo": []string{"foo", "test"}, + }, }, group: "group:bar", }, @@ -666,7 +687,10 @@ func Test_listMachinesInNamespace(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := listMachinesInNamespace(tt.args.machines, tt.args.namespace); !reflect.DeepEqual(got, tt.want) { + if got := listMachinesInNamespace(tt.args.machines, tt.args.namespace); !reflect.DeepEqual( + got, + tt.want, + ) { t.Errorf("listMachinesInNamespace() = %v, want %v", got, tt.want) } }) @@ -691,7 +715,11 @@ func Test_expandAlias(t *testing.T) { alias: "*", machines: []Machine{ {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.78.84.227")}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.78.84.227"), + }, + }, }, aclPolicy: ACLPolicy{}, }, @@ -703,10 +731,30 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "group:foo", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "test"}, + }, }, aclPolicy: ACLPolicy{ Groups: Groups{"group:foo": []string{"foo", "bar"}}, @@ -720,10 +768,30 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "group:test", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "test"}, + }, }, aclPolicy: ACLPolicy{ Groups: Groups{"group:foo": []string{"foo", "bar"}}, @@ -748,7 +816,9 @@ func Test_expandAlias(t *testing.T) { alias: "homeNetwork", machines: []Machine{}, aclPolicy: ACLPolicy{ - Hosts: Hosts{"homeNetwork": netaddr.MustParseIPPrefix("192.168.1.0/24")}, + Hosts: Hosts{ + "homeNetwork": netaddr.MustParseIPPrefix("192.168.1.0/24"), + }, }, }, want: []string{"192.168.1.0/24"}, @@ -779,10 +849,36 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "tag:test", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "foo"}, + }, }, aclPolicy: ACLPolicy{ TagOwners: TagOwners{"tag:test": []string{"foo"}}, @@ -796,10 +892,30 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "tag:foo", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "test"}, + }, }, aclPolicy: ACLPolicy{ Groups: Groups{"group:foo": []string{"foo", "bar"}}, @@ -814,10 +930,36 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "foo", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "foo"}, + }, }, aclPolicy: ACLPolicy{ TagOwners: TagOwners{"tag:test": []string{"foo"}}, @@ -829,7 +971,11 @@ func Test_expandAlias(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := expandAlias(test.args.machines, test.args.aclPolicy, test.args.alias) + got, err := expandAlias( + test.args.machines, + test.args.aclPolicy, + test.args.alias, + ) if (err != nil) != test.wantErr { t.Errorf("expandAlias() error = %v, wantErr %v", err, test.wantErr) @@ -861,14 +1007,38 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { TagOwners: TagOwners{"tag:test": []string{"foo"}}, }, nodes: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "foo"}, + }, }, namespace: "foo", }, want: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, + Namespace: Namespace{Name: "foo"}, + }, }, wantErr: false, }, @@ -879,25 +1049,69 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { TagOwners: TagOwners{"tag:foo": []string{"foo"}}, }, nodes: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "foo"}, + }, }, namespace: "foo", }, want: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, + Namespace: Namespace{Name: "foo"}, + }, }, wantErr: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := excludeCorrectlyTaggedNodes(test.args.aclPolicy, test.args.nodes, test.args.namespace) + got, err := excludeCorrectlyTaggedNodes( + test.args.aclPolicy, + test.args.nodes, + test.args.namespace, + ) if (err != nil) != test.wantErr { - t.Errorf("excludeCorrectlyTaggedNodes() error = %v, wantErr %v", err, test.wantErr) + t.Errorf( + "excludeCorrectlyTaggedNodes() error = %v, wantErr %v", + err, + test.wantErr, + ) return } diff --git a/dns.go b/dns.go index 085a14e..be6238f 100644 --- a/dns.go +++ b/dns.go @@ -165,7 +165,11 @@ func getMapResponseDNSConfig( dnsConfig.Domains, fmt.Sprintf( "%s.%s", - strings.ReplaceAll(machine.Namespace.Name, "@", "."), // Replace @ with . for valid domain for machine + strings.ReplaceAll( + machine.Namespace.Name, + "@", + ".", + ), // Replace @ with . for valid domain for machine baseDomain, ), ) diff --git a/docs/acls.md b/docs/acls.md index 89e8b55..63e7c6b 100644 --- a/docs/acls.md +++ b/docs/acls.md @@ -1,4 +1,3 @@ - # ACLs use case example Let's build an example use case for a small business (It may be the place where @@ -46,81 +45,97 @@ Here are the ACL's to implement the same permissions as above: ```json { - // groups are collections of users having a common scope. A user can be in multiple groups - // groups cannot be composed of groups - "groups": { - "group:boss": ["boss"], - "group:dev": ["dev1","dev2"], - "group:admin": ["admin1"], - "group:intern": ["intern1"], + // groups are collections of users having a common scope. A user can be in multiple groups + // groups cannot be composed of groups + "groups": { + "group:boss": ["boss"], + "group:dev": ["dev1", "dev2"], + "group:admin": ["admin1"], + "group:intern": ["intern1"] + }, + // tagOwners in tailscale is an association between a TAG and the people allowed to set this TAG on a server. + // This is documented [here](https://tailscale.com/kb/1068/acl-tags#defining-a-tag) + // and explained [here](https://tailscale.com/blog/rbac-like-it-was-meant-to-be/) + "tagOwners": { + // the administrators can add servers in production + "tag:prod-databases": ["group:admin"], + "tag:prod-app-servers": ["group:admin"], + + // the boss can tag any server as internal + "tag:internal": ["group:boss"], + + // dev can add servers for dev purposes as well as admins + "tag:dev-databases": ["group:admin", "group:dev"], + "tag:dev-app-servers": ["group:admin", "group:dev"] + + // interns cannot add servers + }, + "acls": [ + // boss have access to all servers + { + "action": "accept", + "users": ["group:boss"], + "ports": [ + "tag:prod-databases:*", + "tag:prod-app-servers:*", + "tag:internal:*", + "tag:dev-databases:*", + "tag:dev-app-servers:*" + ] }, - // tagOwners in tailscale is an association between a TAG and the people allowed to set this TAG on a server. - // This is documented [here](https://tailscale.com/kb/1068/acl-tags#defining-a-tag) - // and explained [here](https://tailscale.com/blog/rbac-like-it-was-meant-to-be/) - "tagOwners": { - // the administrators can add servers in production - "tag:prod-databases": ["group:admin"], - "tag:prod-app-servers": ["group:admin"], - // the boss can tag any server as internal - "tag:internal": ["group:boss"], - - // dev can add servers for dev purposes as well as admins - "tag:dev-databases": ["group:admin","group:dev"], - "tag:dev-app-servers": ["group:admin", "group:dev"], - - // interns cannot add servers + // admin have only access to administrative ports of the servers + { + "action": "accept", + "users": ["group:admin"], + "ports": [ + "tag:prod-databases:22", + "tag:prod-app-servers:22", + "tag:internal:22", + "tag:dev-databases:22", + "tag:dev-app-servers:22" + ] }, - "acls": [ - // boss have access to all servers - {"action":"accept", - "users":["group:boss"], - "ports":[ - "tag:prod-databases:*", - "tag:prod-app-servers:*", - "tag:internal:*", - "tag:dev-databases:*", - "tag:dev-app-servers:*", - ] - }, - // admin have only access to administrative ports of the servers - {"action":"accept", - "users":["group:admin"], - "ports":[ - "tag:prod-databases:22", - "tag:prod-app-servers:22", - "tag:internal:22", - "tag:dev-databases:22", - "tag:dev-app-servers:22", - ] - }, + // developers have access to databases servers and application servers on all ports + // they can only view the applications servers in prod and have no access to databases servers in production + { + "action": "accept", + "users": ["group:dev"], + "ports": [ + "tag:dev-databases:*", + "tag:dev-app-servers:*", + "tag:prod-app-servers:80,443" + ] + }, - // developers have access to databases servers and application servers on all ports - // they can only view the applications servers in prod and have no access to databases servers in production - {"action":"accept", "users":["group:dev"], "ports":[ - "tag:dev-databases:*", - "tag:dev-app-servers:*", - "tag:prod-app-servers:80,443", - ] - }, + // servers should be able to talk to database. Database should not be able to initiate connections to + // applications servers + { + "action": "accept", + "users": ["tag:dev-app-servers"], + "ports": ["tag:dev-databases:5432"] + }, + { + "action": "accept", + "users": ["tag:prod-app-servers"], + "ports": ["tag:prod-databases:5432"] + }, - // servers should be able to talk to database. Database should not be able to initiate connections to - // applications servers - {"action":"accept", "users":["tag:dev-app-servers"], "ports":["tag:dev-databases:5432"]}, - {"action":"accept", "users":["tag:prod-app-servers"], "ports":["tag:prod-databases:5432"]}, + // interns have access to dev-app-servers only in reading mode + { + "action": "accept", + "users": ["group:intern"], + "ports": ["tag:dev-app-servers:80,443"] + }, - // interns have access to dev-app-servers only in reading mode - {"action":"accept", "users":["group:intern"], "ports":["tag:dev-app-servers:80,443"]}, - - // We still have to allow internal namespaces communications since nothing guarantees that each user have - // their own namespaces. - {"action":"accept", "users":["boss"], "ports":["boss:*"]}, - {"action":"accept", "users":["dev1"], "ports":["dev1:*"]}, - {"action":"accept", "users":["dev2"], "ports":["dev2:*"]}, - {"action":"accept", "users":["admin1"], "ports":["admin1:*"]}, - {"action":"accept", "users":["intern1"], "ports":["intern1:*"]}, - ] + // We still have to allow internal namespaces communications since nothing guarantees that each user have + // their own namespaces. + { "action": "accept", "users": ["boss"], "ports": ["boss:*"] }, + { "action": "accept", "users": ["dev1"], "ports": ["dev1:*"] }, + { "action": "accept", "users": ["dev2"], "ports": ["dev2:*"] }, + { "action": "accept", "users": ["admin1"], "ports": ["admin1:*"] }, + { "action": "accept", "users": ["intern1"], "ports": ["intern1:*"] } + ] } ``` - diff --git a/machine.go b/machine.go index cb70bf1..ba677f1 100644 --- a/machine.go +++ b/machine.go @@ -192,7 +192,10 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { for _, m := range mMachines { authorizedMachines = append(authorizedMachines, m) } - sort.Slice(authorizedMachines, func(i, j int) bool { return authorizedMachines[i].ID < authorizedMachines[j].ID }) + sort.Slice( + authorizedMachines, + func(i, j int) bool { return authorizedMachines[i].ID < authorizedMachines[j].ID }, + ) log.Trace(). Caller(). @@ -695,7 +698,11 @@ func (machine Machine) toNode( hostname = fmt.Sprintf( "%s.%s.%s", machine.Name, - strings.ReplaceAll(machine.Namespace.Name, "@", "."), // Replace @ with . for valid domain for machine + strings.ReplaceAll( + machine.Namespace.Name, + "@", + ".", + ), // Replace @ with . for valid domain for machine baseDomain, ) } else { diff --git a/machine_test.go b/machine_test.go index df00067..f9e58be 100644 --- a/machine_test.go +++ b/machine_test.go @@ -176,11 +176,13 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { for index := 0; index <= 10; index++ { machine := Machine{ - ID: uint64(index), - MachineKey: "foo" + strconv.Itoa(index), - NodeKey: "bar" + strconv.Itoa(index), - DiscoKey: "faa" + strconv.Itoa(index), - IPAddresses: MachineAddresses{netaddr.MustParseIP(fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1)))}, + ID: uint64(index), + MachineKey: "foo" + strconv.Itoa(index), + NodeKey: "bar" + strconv.Itoa(index), + DiscoKey: "faa" + strconv.Itoa(index), + IPAddresses: MachineAddresses{ + netaddr.MustParseIP(fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1))), + }, Name: "testmachine" + strconv.Itoa(index), NamespaceID: stor[index%2].namespace.ID, Registered: true, diff --git a/poll.go b/poll.go index f00f748..96db43f 100644 --- a/poll.go +++ b/poll.go @@ -97,7 +97,11 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { // update ACLRules with peer informations (to update server tags if necessary) err = h.UpdateACLRules() if err != nil { - log.Error().Caller().Str("func", "handleAuthKey").Str("machine", machine.Name).Err(err) + log.Error(). + Caller(). + Str("func", "handleAuthKey"). + Str("machine", machine.Name). + Err(err) } // From Tailscale client: From 5f642eef76e497c03e0409aefa691d7602822bf3 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 18:24:37 +0100 Subject: [PATCH 019/204] chore(lint): more lint fixing --- acls_test.go | 10 +++++----- dns.go | 10 ++++++++-- utils.go | 1 + 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/acls_test.go b/acls_test.go index f8407d4..2bd5bf9 100644 --- a/acls_test.go +++ b/acls_test.go @@ -685,13 +685,13 @@ func Test_listMachinesInNamespace(t *testing.T) { want: []Machine{}, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := listMachinesInNamespace(tt.args.machines, tt.args.namespace); !reflect.DeepEqual( + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if got := listMachinesInNamespace(test.args.machines, test.args.namespace); !reflect.DeepEqual( got, - tt.want, + test.want, ) { - t.Errorf("listMachinesInNamespace() = %v, want %v", got, tt.want) + t.Errorf("listMachinesInNamespace() = %v, want %v", got, test.want) } }) } diff --git a/dns.go b/dns.go index be6238f..45e0fae 100644 --- a/dns.go +++ b/dns.go @@ -179,8 +179,14 @@ func getMapResponseDNSConfig( for _, p := range peers { namespaceSet.Add(p.Namespace) } - for _, namespace := range namespaceSet.List() { - var dnsRoute string = fmt.Sprintf("%v.%v", namespace.(Namespace).Name, baseDomain) + for _, ns := range namespaceSet.List() { + namespace, ok := ns.(Namespace) + if !ok { + dnsConfig = dnsConfigOrig + + continue + } + dnsRoute := fmt.Sprintf("%v.%v", namespace.Name, baseDomain) dnsConfig.Routes[dnsRoute] = nil } } else { diff --git a/utils.go b/utils.go index 794971a..3cee5e3 100644 --- a/utils.go +++ b/utils.go @@ -218,6 +218,7 @@ func containsString(ss []string, s string) bool { return true } } + return false } From f073d8f43c0334db46dccdb66083e7c3a07925a5 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 18:32:20 +0100 Subject: [PATCH 020/204] chore(lint): ignore linting on test_expandalias This is a false positive on the way the function is built. Small tests cases are all inside this functions, making it big. --- acls_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/acls_test.go b/acls_test.go index 2bd5bf9..e68a01f 100644 --- a/acls_test.go +++ b/acls_test.go @@ -697,6 +697,7 @@ func Test_listMachinesInNamespace(t *testing.T) { } } +// nolint func Test_expandAlias(t *testing.T) { type args struct { machines []Machine From a6b7bc5939bbf6e638b38f0d8d81b251845447e1 Mon Sep 17 00:00:00 2001 From: e-zk Date: Sun, 20 Feb 2022 03:14:51 +1000 Subject: [PATCH 021/204] Fix spelling error --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 1ac1522..89c74a7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,7 +10,7 @@ please ask on [Discord](https://discord.gg/XcQxk2VHjx) instead of opening an Iss ### How-to - [Running headscale on Linux](running-headscale-linux.md) -- [Control headscale remotly](remote-cli.md) +- [Control headscale remotely](remote-cli.md) - [Using a Windows client with headscale](windows-client.md) ### References From 3db88d27de119895bafd78f08e1523d3fd5e7919 Mon Sep 17 00:00:00 2001 From: ohdearaugustin Date: Mon, 14 Feb 2022 22:58:01 +0100 Subject: [PATCH 022/204] github/workflows: init renovatebot --- .github/renovate.json | 7 +++++++ .github/workflows/renovatebot.yml | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 .github/renovate.json create mode 100644 .github/workflows/renovatebot.yml diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000..85962d7 --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,7 @@ +{ + "extends": ["config:base"]", + "baseBranches": ["main"], + "branchPrefix": "renovateaction", + "extends": ["config:base", ":rebaseStalePrs"], + "enabledManagers": ["dockerfile", "go", "github-actions"] +} diff --git a/.github/workflows/renovatebot.yml b/.github/workflows/renovatebot.yml new file mode 100644 index 0000000..d602332 --- /dev/null +++ b/.github/workflows/renovatebot.yml @@ -0,0 +1,26 @@ +--- +name: Renovate +on: + schedule: + - cron: '* * 5,20 * *' #Every 5th and 20th of the month + workflow_dispatch: +jobs: + renovate: + runs-on: ubuntu-latest + steps: + - name: Get token + id: get_token + uses: machine-learning-apps/actions-app-token@master + with: + APP_PEM: ${{ secrets.RENOVATEBOT_SECRET }} + APP_ID: ${{ secrets.RENOVATEBOT_APP_ID }} + + - name: Checkout + uses: actions/checkout@v2.0.0 + + - name: Self-hosted Renovate + uses: renovatebot/github-action@v31.81.2 + with: + configurationFile: .github/renovate.json + token: 'x-access-token:${{ steps.get_token.outputs.app_token }}' + onboarding: false From a19550adbfcab8b0a8044a9ec4cb96530f0ac9ec Mon Sep 17 00:00:00 2001 From: ohdearaugustin Date: Mon, 14 Feb 2022 23:03:03 +0100 Subject: [PATCH 023/204] prettier: renovatebot.yml --- .github/workflows/renovatebot.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/renovatebot.yml b/.github/workflows/renovatebot.yml index d602332..3f91256 100644 --- a/.github/workflows/renovatebot.yml +++ b/.github/workflows/renovatebot.yml @@ -2,8 +2,8 @@ name: Renovate on: schedule: - - cron: '* * 5,20 * *' #Every 5th and 20th of the month - workflow_dispatch: + - cron: "* * 5,20 * *" # Every 5th and 20th of the month + workflow_dispatch: jobs: renovate: runs-on: ubuntu-latest @@ -22,5 +22,5 @@ jobs: uses: renovatebot/github-action@v31.81.2 with: configurationFile: .github/renovate.json - token: 'x-access-token:${{ steps.get_token.outputs.app_token }}' + token: "x-access-token:${{ steps.get_token.outputs.app_token }}" onboarding: false From fe6d47030f42954fc2d8c85712b4318c873f365a Mon Sep 17 00:00:00 2001 From: ohdearaugustin Date: Mon, 14 Feb 2022 23:33:55 +0100 Subject: [PATCH 024/204] renovatebot: configure --- .github/renovate.json | 37 ++++++++++++++++++++++++++++--- .github/workflows/renovatebot.yml | 5 +++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 85962d7..ce38ba9 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,7 +1,38 @@ { - "extends": ["config:base"]", "baseBranches": ["main"], - "branchPrefix": "renovateaction", + "username": "renovate-release", + "gitAuthor": "Renovate Bot ", + "branchPrefix": "renovateaction/", + "onboarding": false, "extends": ["config:base", ":rebaseStalePrs"], - "enabledManagers": ["dockerfile", "go", "github-actions"] + "ignorePresets": [":prHourlyLimit2"], + "enabledManagers": ["dockerfile", "gomod", "github-actions","regex" ], + "includeForks": true, + "repositories": ["juanfont/headscale"], + "platform": "github", + "packageRules": [ + { + "matchDatasources": ["go"], + "groupName": "Go modules", + "groupSlug": "gomod", + "separateMajorMinor": false + }, + { + "matchDatasources": ["docker"], + "groupName": "Dockerfiles", + "groupSlug": "dockerfiles" + } + ], + "regexManagers": [ + { + "fileMatch": [ + ".github/workflows/.*.yml$" + ], + "matchStrings": [ + "\\s*go-version:\\s*\"?(?.*?)\"?\\n" + ], + "datasourceTemplate": "golang-version", + "depNameTemplate": "actions/go-version" + } + ] } diff --git a/.github/workflows/renovatebot.yml b/.github/workflows/renovatebot.yml index 3f91256..53b976c 100644 --- a/.github/workflows/renovatebot.yml +++ b/.github/workflows/renovatebot.yml @@ -19,8 +19,9 @@ jobs: uses: actions/checkout@v2.0.0 - name: Self-hosted Renovate - uses: renovatebot/github-action@v31.81.2 + uses: renovatebot/github-action@v31.81.3 with: configurationFile: .github/renovate.json token: "x-access-token:${{ steps.get_token.outputs.app_token }}" - onboarding: false + # env: + # LOG_LEVEL: "debug" From e9f13b603128d9536f75be48199cda5f1f222070 Mon Sep 17 00:00:00 2001 From: ohdearaugustin Date: Sat, 19 Feb 2022 20:28:08 +0100 Subject: [PATCH 025/204] CODEOWNER: add renovate config ohdearaugustin --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 565684f..fa1c06d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,3 +7,4 @@ Dockerfile* @ohdearaugustin .goreleaser.yaml @ohdearaugustin /docs/ @ohdearaugustin /.github/workflows/ @ohdearaugustin +/.github/renovate.json @ohdearaugustin From 8798efd3536bb7ee7883de909f69c12b3715f06a Mon Sep 17 00:00:00 2001 From: ohdearaugustin Date: Sat, 19 Feb 2022 21:04:01 +0100 Subject: [PATCH 026/204] contributor: set specific version --- .github/workflows/contributors.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index e27b6ed..4a73009 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -4,13 +4,13 @@ on: push: branches: - main - + workflow_dispatch: jobs: add-contributors: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: BobAnkh/add-contributors@master + - uses: BobAnkh/add-contributors@v0.2.2 with: CONTRIBUTOR: "## Contributors" COLUMN_PER_ROW: "6" From 5245f1accc5fd7f85ecbe6f4e59599659f3b72d8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 19 Feb 2022 22:48:26 +0000 Subject: [PATCH 027/204] docs(README): update contributors --- README.md | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 168 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1d86380..e7ba664 100644 --- a/README.md +++ b/README.md @@ -122,13 +122,6 @@ make build - + + + + + - - + + + + + + + + + + + + + - - + + + + + + + + + + - - + + + + + + + + + + + - - + + - - + + - - - + + + - - + + - - + + - - + + + + - - + + + + - - + + - - + + - - + + - - + + - - - + + - - - - - + + - - + + - - + + - - + + - - + + - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + + - - - + + + - - + + - -
- - Juan -
- Juan Font -
-
Kristoffer @@ -136,6 +129,13 @@ make build Kristoffer Dalby + + Juan +
+ Juan Font +
+
Ward @@ -150,6 +150,13 @@ make build ohdearaugustin + + Alessandro +
+ Alessandro (Ale) Segala +
+
unreality/ @@ -157,6 +164,15 @@ make build unreality
+ + Eugen +
+ Eugen Biegler +
+
Aaron @@ -164,8 +180,27 @@ make build Aaron Bieber
+ + Fernando +
+ Fernando De Lucchi +
+
+ + Hoàng +
+ Hoàng Đức Hiếu +
+
+ + Michael +
+ Michael G. +
+
Paul @@ -173,6 +208,8 @@ make build Paul Tötterman
Casey @@ -187,6 +224,20 @@ make build Silver Bullet + + Stefan +
+ Stefan Majer +
+
+ + lachy-2849/ +
+ lachy-2849 +
+
thomas/ @@ -194,6 +245,29 @@ make build thomas + + Abraham +
+ Abraham Ingersoll +
+
+ + Adrien +
+ Adrien Raffin-Caboisse +
+
+ + Artem +
+ Artem Klevtsov +
+
Arthur @@ -201,6 +275,13 @@ make build Arthur Woimbée + + Bryan +
+ Bryan Stenson +
+
Felix @@ -208,8 +289,6 @@ make build Felix Kronlage-Dammers
Felix @@ -217,6 +296,43 @@ make build Felix Yan
+ + JJGadgets/ +
+ JJGadgets +
+
+ + Jim +
+ Jim Tittsler +
+
+ + Pierre +
+ Pierre Carru +
+
+ + rcursaru/ +
+ rcursaru +
+
+ + Ryan +
+ Ryan Fowler +
+
Shaanan @@ -224,6 +340,15 @@ make build Shaanan Cohney
+ + Tanner/ +
+ Tanner +
+
Teteros/ @@ -252,8 +377,6 @@ make build Tjerk Woudsma
Zakhar @@ -261,6 +384,15 @@ make build Zakhar Bessarab
+ + ZiYuan/ +
+ ZiYuan +
+
derelm/ @@ -268,6 +400,13 @@ make build derelm + + e-zk/ +
+ e-zk +
+
ignoramous/ @@ -275,6 +414,22 @@ make build ignoramous + + lion24/ +
+ lion24 +
+
+ + Wakeful-Cloud/ +
+ Wakeful-Cloud +
+
zy/ From 385dd9cc34cabb0c7c1a2dcdf92c4bd055db1f52 Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Sun, 20 Feb 2022 09:06:14 -0500 Subject: [PATCH 028/204] refactoring --- app.go | 49 +++++++++++++++----------------- cmd/headscale/cli/.utils.go.swp | Bin 24576 -> 0 bytes cmd/headscale/cli/utils.go | 17 ++++++++--- config-example.yaml | 2 +- docs/tls.md | 2 +- 5 files changed, 38 insertions(+), 32 deletions(-) delete mode 100644 cmd/headscale/cli/.utils.go.swp diff --git a/app.go b/app.go index 2e11248..2e4fb4b 100644 --- a/app.go +++ b/app.go @@ -94,7 +94,7 @@ type Config struct { TLSCertPath string TLSKeyPath string - TLSClientAuthMode string + TLSClientAuthMode tls.ClientAuthType ACMEURL string ACMEEmail string @@ -153,6 +153,27 @@ type Headscale struct { requestedExpiryCache *cache.Cache } +// Look up the TLS constant relative to user-supplied TLS client +// authentication mode. If an unknown mode is supplied, the default +// value, tls.RequireAnyClientCert, is returned. The returned boolean +// indicates if the supplied mode was valid. +func LookupTLSClientAuthMode(mode string) (tls.ClientAuthType, bool) { + switch mode { + case DisabledClientAuth: + // Client cert is _not_ required. + return tls.NoClientCert, true + case RelaxedClientAuth: + // Client cert required, but _not verified_. + return tls.RequireAnyClientCert, true + case EnforcedClientAuth: + // Client cert is _required and verified_. + return tls.RequireAndVerifyClientCert, true + default: + // Return the default when an unknown value is supplied. + return tls.RequireAnyClientCert, false + } +} + // NewHeadscale returns the Headscale app. func NewHeadscale(cfg Config) (*Headscale, error) { privKey, err := readOrCreatePrivateKey(cfg.PrivateKeyPath) @@ -655,17 +676,12 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { log.Warn().Msg("Listening with TLS but ServerURL does not start with https://") } - clientAuthMode, err := h.GetClientAuthMode() - if err != nil { - return nil, err - } - log.Info().Msg(fmt.Sprintf( "Client authentication (mTLS) is \"%s\". See the docs to learn about configuring this setting.", h.cfg.TLSClientAuthMode)) tlsConfig := &tls.Config{ - ClientAuth: clientAuthMode, + ClientAuth: h.cfg.TLSClientAuthMode, NextProtos: []string{"http/1.1"}, Certificates: make([]tls.Certificate, 1), MinVersion: tls.VersionTLS12, @@ -677,25 +693,6 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { } } -// Look up the TLS constant relative to user-supplied TLS client -// authentication mode. -func (h *Headscale) GetClientAuthMode() (tls.ClientAuthType, error) { - switch h.cfg.TLSClientAuthMode { - case DisabledClientAuth: - // Client cert is _not_ required. - return tls.NoClientCert, nil - case RelaxedClientAuth: - // Client cert required, but _not verified_. - return tls.RequireAnyClientCert, nil - case EnforcedClientAuth: - // Client cert is _required and verified_. - return tls.RequireAndVerifyClientCert, nil - default: - return tls.NoClientCert, Error("Invalid tls_client_auth_mode provided: " + - h.cfg.TLSClientAuthMode) - } -} - func (h *Headscale) setLastStateChangeToNow(namespace string) { now := time.Now().UTC() lastStateUpdate.WithLabelValues("", "headscale").Set(float64(now.Unix())) diff --git a/cmd/headscale/cli/.utils.go.swp b/cmd/headscale/cli/.utils.go.swp deleted file mode 100644 index fbd933abe05eba73d62b6cfcf550855fe57a20f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 zcmeI3dyr&TS-=|tLZg@vL5N!A*$#<4o5}6jyqS>b?96O-WM_A>vr8bGO>?LFcF*1I zzPG*i_RP-a1%D6|vI&ailQI&51j;H(R3M59#Y@2wBnb(zBq6>DRgolGSXOELednC} z=;_{_7~>yS^;UkF?t9PkJLi1o`@VB}W$LX9i|R7xf)fAED3y*r^nJH+PE@-6he{>ErEX0I{&g)moB_u$CTtbyRuFF$e9P9clL3@u>{5v7)xL*fw2U}5*SNh zEP=5E#uE7dFM*`@veGSd{5v7)xL*fw2U}5*SNhEP=5E#u6AyU@U>L1jZ8hKahaiER|kIxv!A`0O$Xy z|NpP2mrBpVlkhlv6}|v}0)GG>g?r(Ba2wnN5gY*@cEcI)><^bpkHTl*ci`9H7I+6- z4~O9(ya_IaOW-x|%&SYKC*Xd#3u5r$ZSZDz6L6eadObYOU4<{hpTn(i6`TpLfhT^j zRQfjjA>0qY1n+~l!ZuLw{a2Mre+6HId%%V3;V}Fpl;Nx8QYnF#z<<56RQgZ&92|p7 z;iIo8mEI3e{y?epPw(gQMzw%9`a=9OM;zNGW z^o|`?SE%iLooO~BM4{i7%ZqWlTG{3L9j~d9Q1#p>_7tfmmER7+$Pe0%<5VU{UoOu_ zQPqp02}gfhPNHgsl$A+I&o}eD6Sf@^hEY|2_gjiAYTFem@H^@T(;{iYq<%hqg=BV? zq}r-2rc`c)k(U5O(|^DV2@%OahT%r6SepO0$gWJf1HEYi`G92s?4T(eb??sk{ATwcZVzo{Iau z9?zPNnrSq=Ucyk5y6?r)s_Dn>3S&R1BCq2flMh~i_#33I==x1*GZeNcWl1B_OcizR zxoX6FThz&3rxi$F%A2w?oSVj|S{c5Kk~$Z`IxLX3S5G#2o^m5k z?LKf|>HMi3$_<+8z@FvvXZ9@Z<-3u@aKBGoB5ju`QYa@A$O|mWHm@iYqqVMaqku&` zt=3n)K=orj4|R7njFZ6adS<)}tx|5RGFd2*#bmzB%|u!8SQIXaSRhDP^$@PQ=%Ncz zjgIH2jvpspPlYSVK(|n3^WF)}5jhrMX5YGU1X{KUVyw2hLUN zrYma2Yq)*X2V=^>G<2afBM!SBIp|;PCyD%}@KzKCi3(eVW+$s|LYtd@NGV zqGuYa>N#zPAy$4bkq*Tw>UTWRHr3)pwOVOtvKKn5XS?Z{p6cZnFs@e&O%W!%ESjy$ zN=MXAwBocFREeW?L83fXzBjxu(sD%?XpQ4VNxkPLt2Oy{)Z5TsCRGq7Y9&lo?eZAi z;6|D`Z{>|Qo}_bW(OJ?|fs8J?xR}#6XIVvWl-JzI=sww2PT%dO>M_(_)b-;Sfk@d?;iZ>OjV`{BNmAAj zcP;7%`R!LnO4J+FaE;A?{aJ5M7zQVC-x@uK=P(L_DFedq43F`spyl{S)8;DRH|1;M@hw6dh6@!HAg=# zG#iT}>@qqnZTM0sl4DeIbP^j`Kk7Kxc%){@;5y0%NYJ60P^m^Cl9B;_t;Gk+Ire#LDZ#ZzDb zOih(242!9%lT{MD1bx}tX@uRHY?*P5`79r>nKr*Baii6i7k=O+j@zp7M>b1&)DC+` z+m0X9Hr#Hxbsj!2g?}Smi){c4&{RWNQU(vP3z1EHkYr5l`-b8WjxEF;i zof`0RZHKCGM?KAXr0=qjg5sU^windeVL{4kJ2n+MoT`0RfV z55p(nLvR9agPS3SLvSrz4SQh`X5l=TfGRwOU;jn84?YCg$Fl5Gk9_N#MS&Wa3Qg%lZ=Q~JfOBcJG5CzO^A!nx>dzTG7@RMc# zxOd4#Qooc(1_}5XyC;j{Rq>$mz+KjGo@VAwEANmPJ$X-Q*rMCB-K%5wn9bW+BvLdR zc6&&n8v4z~qMKl~iWeh6mBN!eGHHsE;>-5qa8s#^KCr7-D^iBj#KiT3de`k?;OWp~ z2ZL?j!rZK`kmN)kd3%Tw$#vNLp$;8F@OVYDB!R>dOaxGOz;--#B;n>FB`qO`$nD|t z5CIDNL@TsRB?3&W%y0R`2Xrt&LI?)81+l9`ynV4^F84-p}<3JscoX z8;gmuEH0RzY|w|5FqG)8j+ko42Mf6(5lTYL$F&<;nO2pZ9`UG1Rn&PZadg3x*_<4b z!VRSfRULY&r(75rA39J3uZ_$osF55K-&Bk!XV(0kOgll(vu-f4q$imBi(;|j;Z{YA z`%RQrM@~hARNXT{^T?#uQ`sZbtGlTSOucU%Ys;#Tr+xhJftje?R67yHBT3hy7Ij&i zXE$nV+g}@mig-ft!TAJ?y-M+^nAX}&kQrN_)Tx<~CX61&&P>#nFuI;~ggF;+%P3-B zKk4<8T^(2A-i1+H?h`tWWAj>~*5=aXN(5tx1(kFH z>pxbHNaQ^Wyqnmv(T0r4K!&t;q|Y;yne{N{{8?>sx?9A|g>tLJ5o7C1qg)e)7dq$^AM)4tV zX$I<;L#_#DRs#QWDz_{LcQz08+D{YGJZYV76PpcNf~(q`f-!PtJ?M!oO|W&aU5XA2 zn$^NX(+cMrJnsb?gsbXPEqX>kz?t2%;G{2PIhM<^F3LAeprQGvmE<(#`UH9OBi&~y z4zq*S%o5*bdLe^2-+Sb^tg~amoXqKMRf6{vA=|M&*^%8-1kupjr}qDG`%7oYc`zT+`~45%?>_*) z4%fol;c}?JE8#o%_g{q1!Dm6v_fJ3vcEeThWAHHk{WswKa2T$GbK!gV@qYtff&1WB z;cc)Vu7>mBWgve3WAG?^6Fv@i!F%9#5dVHV{0n~ir{Ndj4%h?R;S6}H%$YoV1bT2S z>;m!6PlwOrcYhjgg(h4F2VoohIGhg8;cMRr>kvZ(3-Ag!4PFY5;AejjZh&h+eD4e3 z%bfRr0X_?#f&1V%{0v+Sj}d?QYj_m?2tEaJC*Z^IA-EUb2^YhU!e4Uc{~K^Sv|t75 za6McN`(Q6@gMVjSABAtipTeDR2xPoR-2o_<7nV%Cb6S~yHvXn8rE}uHuQrk z;p|B+Pndu)>VWUrd40L8-`1r~S*~SH!>G2V<|PwIxNEfUO*+a=gPqd-0gg z2C}8XNxR8aG3l20zD%$&auZBoZ3A0Jp<#~1rFsqK7+hqMPZXwgMbVFDh|?n4lyj&KXRw%@m;~l18KM-Uy=$V%nNjhVjETn_m3M$H|PQK2bc?aAwI0^=&m|*k)AP;9^F- zI7lyK{6-gb>cKPvXd9W!Wmanb614X%VRWcuP(Q0<(+4Z-@ z>Z4_*f~{6up^`jl{!mw(t@+VQGEcq5I^4Vpw_bxoD{$2M%j^FitiG++US4cWLye}F z1!LrzEtBE7W$vC1X4k%NK~EH~tfs1BVd*3}W$*`!8?iKoH?u;Pt+vpCq^7IctdzRW zl~aH5U^6v&1M~3YD+62A#uUX+PgN_i#On5;l2X$(4a>;{KiDJS>h01Y)u6F4t@?ux zL|e$!5R=Y27r4UqfxH$Al&h`zKQWVId4oGL@Ir1A%L{9N<~C)1%~#BdO-&dWg1J7% zHUXFP7O`$^y_L3K#GkirAg48ZJ#Z(SfNP)z+hGDugNN|(KL&Sz+yVG$I1AnYU&qgvvwyj_FL(7X zgeUOnzYQM%Ip04UD)1^O!?*C|e;F|J4L>7IZVUr z;WQ}0bNKdu2Y(AE;28KIzYBPlv3v#|frml-{*S@0fcz#v{C^qmC3w;QrOtrZXL{4j z0&$p2a)=^vNCJxas=12L;Ih6=XI>dAB+HgY{j8l>h}X&5EPQ2~v~fk*glv40hoXiK za%IodA@8iIxG8=&H@AO&d3hjyXZ=3yFyRYJ*wsecE1wWIasWS(Fm4pyp7 zMA@6>yp=u{FJ>jWFl%CZGt0Qu;wGoBiVcv+UmW+jm8{R$Y#@-En3BObO-inIN(*!8 z(%-Z&^s+QdLa8$*_RCAro|&w75<)zx1znUY`3@b{X=H#*6jv0S34ZHvw`dy#qz}m? z=z751x0K+vezuba&5vr9bS>4i6e_bHMT%)`W|J$-Q9z?pH|^6`ob|2AY=dVPH+#;AbXkN; z$C0iv@$4qyFv8e!zg^-&^hpknwIEu3ekW77*4~gqVFKQ(E`cZFON8|K5+>&pjiN(# zP8TCa^mxQo13eld40@Tbm*PQ9m6;@yQ>L7pu5%W~(Gxxe^4okoPN?wIGp~3!D0g_Z z?I|-~k8alw76KRbvc}1`o!X+`?1j*RJiQ**ti8zX)C2A|)cq`1JzXP4fmXImsH*40 z6E+}(KtuYpKAHW9p&KG}G)4o5#k?bp!XI*M4f-|c+;v|u6hRL@uXH52?b{F&cO`B(d{nN{iBu3}qHa}@h23hpQ z_RIG|2Xd<-zuPn|M-38`*Vmvbg=_!C-wJ3+=GjdjjO#JfszMRcDu!TYc5&XGkqo7F z8(mL+wPrdXDd)K?)EOaJozjz+w%E+?;s<_d;8xei51@>+aiR3@`9_pB@;3syo8;yI zQ#Poqnd3fRL>+2+kp*=EyUvK=6rc#?h$ z{O%x4uYdVwq^jFBteJ;?@sRywA?--99rAL{XELU}8EWbt{Zla!+R!L(uF4#wnbsk& zLOr|fPuZSFSM%Qm=~18C*~8u(k*~SJjvo{Bmf@M($uH07#ZVJTC2!JH5-}K^O5UWY z Date: Sun, 20 Feb 2022 20:47:12 +0100 Subject: [PATCH 029/204] Apply suggestions from code review on changelog Co-authored-by: Kristoffer Dalby --- CHANGELOG.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62808b8..cd582af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,24 @@ **TBD (TBD):** +**0.14.0 (2022-xx-xx):** + +**UPCOMING BREAKING**: +From the **next** version (`0.15.0`), all machines will be able to communicate regardless of +if they are in the same namespace. This means that the behaviour currently limited to ACLs +will become default. From version `0.15.0`, all limitation of communications must be done +with ACLs. + +This is a part of aligning `headscale`'s behaviour with Tailscale's upstream behaviour. + **BREAKING**: -- ACLs have been rewritten and the behavior is different from before. It's now more aligned to tailscale's view of the feature. Namespaces are viewed as users and can communicate with each others. Tags should now work correctly and adding a host to Headscale should now reload the rules. The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features. +- ACLs have been rewritten to align with the bevaviour Tailscale Control Panel provides. **NOTE:** This is only active if you use ACLs + - Namespaces are now treated as Users + - All machines can communicate with all machines by default + - Tags should now work correctly and adding a host to Headscale should now reload the rules. + - The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features + **0.13.0 (2022-xx-xx):** From d00251c63e3eb8c93c0ea21acda1040af5971331 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 20 Feb 2022 21:24:02 +0100 Subject: [PATCH 030/204] fix(acls,machines): apply code review suggestions --- acls.go | 8 ++++---- acls_test.go | 2 +- machine.go | 37 ++++++++++++++++++++----------------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/acls.go b/acls.go index d5d3988..f9ed09d 100644 --- a/acls.go +++ b/acls.go @@ -204,7 +204,7 @@ func expandAlias( return ips, err } for _, n := range namespaces { - nodes := listMachinesInNamespace(machines, n) + nodes := filterMachinesByNamespace(machines, n) for _, node := range nodes { ips = append(ips, node.IPAddresses.ToStringSlice()...) } @@ -219,7 +219,7 @@ func expandAlias( return ips, err } for _, namespace := range owners { - machines := listMachinesInNamespace(machines, namespace) + machines := filterMachinesByNamespace(machines, namespace) for _, machine := range machines { if len(machine.HostInfo) == 0 { continue @@ -240,7 +240,7 @@ func expandAlias( } // if alias is a namespace - nodes := listMachinesInNamespace(machines, alias) + nodes := filterMachinesByNamespace(machines, alias) nodes, err := excludeCorrectlyTaggedNodes(aclPolicy, nodes, alias) if err != nil { return ips, err @@ -357,7 +357,7 @@ func expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { return &ports, nil } -func listMachinesInNamespace(machines []Machine, namespace string) []Machine { +func filterMachinesByNamespace(machines []Machine, namespace string) []Machine { out := []Machine{} for _, machine := range machines { if machine.Namespace.Name == namespace { diff --git a/acls_test.go b/acls_test.go index e68a01f..32dd572 100644 --- a/acls_test.go +++ b/acls_test.go @@ -687,7 +687,7 @@ func Test_listMachinesInNamespace(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - if got := listMachinesInNamespace(test.args.machines, test.args.namespace); !reflect.DeepEqual( + if got := filterMachinesByNamespace(test.args.machines, test.args.namespace); !reflect.DeepEqual( got, test.want, ) { diff --git a/machine.go b/machine.go index ba677f1..4c984d6 100644 --- a/machine.go +++ b/machine.go @@ -142,6 +142,16 @@ func containsAddresses(inputs []string, addrs MachineAddresses) bool { return false } +// matchSourceAndDestinationWithRule will check if source is authorized to communicate with destination through +// the given rule. +func matchSourceAndDestinationWithRule(rule tailcfg.FilterRule, source Machine, destination Machine) bool { + var dst []string + for _, d := range rule.DstPorts { + dst = append(dst, d.IP) + } + return (containsAddresses(rule.SrcIPs, source.IPAddresses) && containsAddresses(dst, destination.IPAddresses)) || containsString(dst, "*") +} + // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). @@ -149,14 +159,12 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { Str("machine", machine.Name). Msg("Finding peers filtered by ACLs") - machines := Machines{} - if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", - machine.MachineKey).Find(&machines).Error; err != nil { - log.Error().Err(err).Msg("Error accessing db") - + machines, err := h.ListAllMachines() + if err != nil { + log.Error().Err(err).Msg("Error retrieving list of machines") return Machines{}, err } - mMachines := make(map[uint64]Machine) + peers := make(map[uint64]Machine) // Aclfilter peers here. We are itering through machines in all namespaces and search through the computed aclRules // for match between rule SrcIPs and DstPorts. If the rule is a match we allow the machine to be viewable. @@ -175,21 +183,16 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { // In order to do this we would need to be able to identify that node A want to talk to node B but that Node B doesn't know // how to talk to node A and then add the peering resource. - for _, mchn := range machines { + for _, peer := range machines { for _, rule := range h.aclRules { - var dst []string - for _, d := range rule.DstPorts { - dst = append(dst, d.IP) - } - if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, mchn.IPAddresses) || containsString(dst, "*"))) || - (containsAddresses(rule.SrcIPs, mchn.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { - mMachines[mchn.ID] = mchn + if matchSourceAndDestinationWithRule(rule, *machine, peer) || matchSourceAndDestinationWithRule(rule, peer, *machine) { + peers[peer.ID] = peer } } } - authorizedMachines := make([]Machine, 0, len(mMachines)) - for _, m := range mMachines { + authorizedMachines := make([]Machine, 0, len(peers)) + for _, m := range peers { authorizedMachines = append(authorizedMachines, m) } sort.Slice( @@ -200,7 +203,7 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). Caller(). Str("machine", machine.Name). - Msgf("Found some machines: %s", machines.String()) + Msgf("Found some machines: %v", machines) return authorizedMachines, nil } From 5e167cc00ad5aa312c1d0c50b289a5479d88b867 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 20 Feb 2022 23:00:31 +0100 Subject: [PATCH 031/204] fix(tests): fix naming issues related to code review --- acls_test.go | 240 ++++++++++++++++++++++++++------------------------- 1 file changed, 123 insertions(+), 117 deletions(-) diff --git a/acls_test.go b/acls_test.go index 32dd572..cb33309 100644 --- a/acls_test.go +++ b/acls_test.go @@ -99,16 +99,16 @@ func (s *Suite) TestInvalidTagOwners(c *check.C) { // match properly the IP's of the related hosts. The owner is valid and the tag is also valid. // the tag is matched in the Users section. func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { - namespace, err := app.CreateNamespace("foo") + namespace, err := app.CreateNamespace("user1") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) - _, err = app.GetMachine("foo", "testmachine") + _, err = app.GetMachine("user1", "testmachine") c.Assert(err, check.NotNil) hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"testmachine\",\"RequestTags\":[\"tag:test\"]}", ) machine := Machine{ ID: 0, @@ -126,8 +126,8 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { app.db.Save(&machine) app.aclPolicy = &ACLPolicy{ - Groups: Groups{"group:test": []string{"foo", "foobar"}}, - TagOwners: TagOwners{"tag:test": []string{"bar", "group:test"}}, + Groups: Groups{"group:test": []string{"user1", "user2"}}, + TagOwners: TagOwners{"tag:test": []string{"user3", "group:test"}}, ACLs: []ACL{ {Action: "accept", Users: []string{"tag:test"}, Ports: []string{"*:*"}}, }, @@ -143,20 +143,20 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { // match properly the IP's of the related hosts. The owner is valid and the tag is also valid. // the tag is matched in the Ports section. func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { - namespace, err := app.CreateNamespace("foo") + namespace, err := app.CreateNamespace("user1") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) - _, err = app.GetMachine("foo", "testmachine") + _, err = app.GetMachine("user1", "testmachine") c.Assert(err, check.NotNil) hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"testmachine\",\"RequestTags\":[\"tag:test\"]}", ) machine := Machine{ ID: 1, - MachineKey: "foo", + MachineKey: "12345", NodeKey: "bar", DiscoKey: "faa", Name: "testmachine", @@ -170,8 +170,8 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { app.db.Save(&machine) app.aclPolicy = &ACLPolicy{ - Groups: Groups{"group:test": []string{"foo", "foobar"}}, - TagOwners: TagOwners{"tag:test": []string{"bar", "group:test"}}, + Groups: Groups{"group:test": []string{"user1", "user2"}}, + TagOwners: TagOwners{"tag:test": []string{"user3", "group:test"}}, ACLs: []ACL{ {Action: "accept", Users: []string{"*"}, Ports: []string{"tag:test:*"}}, }, @@ -187,20 +187,20 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { // tag on a host that isn't owned by a tag owners. So the namespace // of the host should be valid. func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { - namespace, err := app.CreateNamespace("foo") + namespace, err := app.CreateNamespace("user1") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) - _, err = app.GetMachine("foo", "testmachine") + _, err = app.GetMachine("user1", "testmachine") c.Assert(err, check.NotNil) hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"testmachine\",\"RequestTags\":[\"tag:foo\"]}", ) machine := Machine{ ID: 1, - MachineKey: "foo", + MachineKey: "12345", NodeKey: "bar", DiscoKey: "faa", Name: "testmachine", @@ -214,9 +214,9 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { app.db.Save(&machine) app.aclPolicy = &ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"foo"}}, + TagOwners: TagOwners{"tag:test": []string{"user1"}}, ACLs: []ACL{ - {Action: "accept", Users: []string{"foo"}, Ports: []string{"*:*"}}, + {Action: "accept", Users: []string{"user1"}, Ports: []string{"*:*"}}, }, } err = app.UpdateACLRules() @@ -230,20 +230,20 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { // an ACL rule is matching the tag to a namespace. It should not be valid since the // host should be tied to the tag now. func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { - namespace, err := app.CreateNamespace("foo") + namespace, err := app.CreateNamespace("user1") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) - _, err = app.GetMachine("foo", "webserver") + _, err = app.GetMachine("user1", "webserver") c.Assert(err, check.NotNil) hostInfo := []byte( "{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}", ) machine := Machine{ ID: 1, - MachineKey: "foo", + MachineKey: "12345", NodeKey: "bar", DiscoKey: "faa", Name: "webserver", @@ -255,12 +255,12 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) - _, err = app.GetMachine("foo", "user") + _, err = app.GetMachine("user1", "user") hostInfo = []byte("{\"OS\":\"debian\",\"Hostname\":\"user\"}") c.Assert(err, check.NotNil) machine = Machine{ ID: 2, - MachineKey: "foo2", + MachineKey: "56789", NodeKey: "bar2", DiscoKey: "faab", Name: "user", @@ -274,11 +274,11 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { app.db.Save(&machine) app.aclPolicy = &ACLPolicy{ - TagOwners: TagOwners{"tag:webapp": []string{"foo"}}, + TagOwners: TagOwners{"tag:webapp": []string{"user1"}}, ACLs: []ACL{ { Action: "accept", - Users: []string{"foo"}, + Users: []string{"user1"}, Ports: []string{"tag:webapp:80,443"}, }, }, @@ -339,7 +339,7 @@ func (s *Suite) TestPortNamespace(c *check.C) { ips, _ := app.getAvailableIPs() machine := Machine{ ID: 0, - MachineKey: "foo", + MachineKey: "12345", NodeKey: "bar", DiscoKey: "faa", Name: "testmachine", @@ -427,13 +427,13 @@ func Test_expandGroup(t *testing.T) { args: args{ aclPolicy: ACLPolicy{ Groups: Groups{ - "group:test": []string{"g1", "foo", "test"}, - "group:foo": []string{"foo", "test"}, + "group:test": []string{"user1", "user2", "user3"}, + "group:foo": []string{"user2", "user3"}, }, }, group: "group:test", }, - want: []string{"g1", "foo", "test"}, + want: []string{"user1", "user2", "user3"}, wantErr: false, }, { @@ -441,11 +441,11 @@ func Test_expandGroup(t *testing.T) { args: args{ aclPolicy: ACLPolicy{ Groups: Groups{ - "group:test": []string{"g1", "foo", "test"}, - "group:foo": []string{"foo", "test"}, + "group:test": []string{"user1", "user2", "user3"}, + "group:foo": []string{"user2", "user3"}, }, }, - group: "group:bar", + group: "group:undefined", }, want: []string{}, wantErr: true, @@ -478,45 +478,45 @@ func Test_expandTagOwners(t *testing.T) { wantErr bool }{ { - name: "simple tag", + name: "simple tag expansion", args: args{ aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"namespace1"}}, + TagOwners: TagOwners{"tag:test": []string{"user1"}}, }, tag: "tag:test", }, - want: []string{"namespace1"}, + want: []string{"user1"}, wantErr: false, }, { - name: "tag and group", + name: "expand with tag and group", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"n1", "bar"}}, + Groups: Groups{"group:foo": []string{"user1", "user2"}}, TagOwners: TagOwners{"tag:test": []string{"group:foo"}}, }, tag: "tag:test", }, - want: []string{"n1", "bar"}, + want: []string{"user1", "user2"}, wantErr: false, }, { - name: "namespace and group", + name: "expand with namespace and group", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"n1", "bar"}}, - TagOwners: TagOwners{"tag:test": []string{"group:foo", "home"}}, + Groups: Groups{"group:foo": []string{"user1", "user2"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo", "user3"}}, }, tag: "tag:test", }, - want: []string{"n1", "bar", "home"}, + want: []string{"user1", "user2", "user3"}, wantErr: false, }, { name: "invalid tag", args: args{ aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:foo": []string{"group:foo", "home"}}, + TagOwners: TagOwners{"tag:foo": []string{"group:foo", "user1"}}, }, tag: "tag:test", }, @@ -527,8 +527,8 @@ func Test_expandTagOwners(t *testing.T) { name: "invalid group", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:bar": []string{"n1", "foo"}}, - TagOwners: TagOwners{"tag:test": []string{"group:foo", "home"}}, + Groups: Groups{"group:bar": []string{"user1", "user2"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo", "user2"}}, }, tag: "tag:test", }, @@ -647,40 +647,40 @@ func Test_listMachinesInNamespace(t *testing.T) { name: "1 machine in namespace", args: args{ machines: []Machine{ - {Namespace: Namespace{Name: "test"}}, + {Namespace: Namespace{Name: "joe"}}, }, - namespace: "test", + namespace: "joe", }, want: []Machine{ - {Namespace: Namespace{Name: "test"}}, + {Namespace: Namespace{Name: "joe"}}, }, }, { name: "3 machines, 2 in namespace", args: args{ machines: []Machine{ - {ID: 1, Namespace: Namespace{Name: "test"}}, - {ID: 2, Namespace: Namespace{Name: "foo"}}, - {ID: 3, Namespace: Namespace{Name: "foo"}}, + {ID: 1, Namespace: Namespace{Name: "joe"}}, + {ID: 2, Namespace: Namespace{Name: "marc"}}, + {ID: 3, Namespace: Namespace{Name: "marc"}}, }, - namespace: "foo", + namespace: "marc", }, want: []Machine{ - {ID: 2, Namespace: Namespace{Name: "foo"}}, - {ID: 3, Namespace: Namespace{Name: "foo"}}, + {ID: 2, Namespace: Namespace{Name: "marc"}}, + {ID: 3, Namespace: Namespace{Name: "marc"}}, }, }, { name: "5 machines, 0 in namespace", args: args{ machines: []Machine{ - {ID: 1, Namespace: Namespace{Name: "test"}}, - {ID: 2, Namespace: Namespace{Name: "foo"}}, - {ID: 3, Namespace: Namespace{Name: "foo"}}, - {ID: 4, Namespace: Namespace{Name: "foo"}}, - {ID: 5, Namespace: Namespace{Name: "foo"}}, + {ID: 1, Namespace: Namespace{Name: "joe"}}, + {ID: 2, Namespace: Namespace{Name: "marc"}}, + {ID: 3, Namespace: Namespace{Name: "marc"}}, + {ID: 4, Namespace: Namespace{Name: "marc"}}, + {ID: 5, Namespace: Namespace{Name: "marc"}}, }, - namespace: "bar", + namespace: "mickael", }, want: []Machine{}, }, @@ -730,35 +730,35 @@ func Test_expandAlias(t *testing.T) { { name: "simple group", args: args{ - alias: "group:foo", + alias: "group:accountant", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "test"}, + Namespace: Namespace{Name: "mickael"}, }, }, aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"foo", "bar"}}, + Groups: Groups{"group:accountant": []string{"joe", "marc"}}, }, }, want: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, @@ -767,35 +767,35 @@ func Test_expandAlias(t *testing.T) { { name: "wrong group", args: args{ - alias: "group:test", + alias: "group:hr", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "test"}, + Namespace: Namespace{Name: "mickael"}, }, }, aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"foo", "bar"}}, + Groups: Groups{"group:accountant": []string{"joe", "marc"}}, }, }, want: []string{}, @@ -848,41 +848,41 @@ func Test_expandAlias(t *testing.T) { { name: "simple tag", args: args{ - alias: "tag:test", + alias: "tag:hr-webserver", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"foo"}}, + TagOwners: TagOwners{"tag:hr-webserver": []string{"joe"}}, }, }, want: []string{"100.64.0.1", "100.64.0.2"}, @@ -891,36 +891,36 @@ func Test_expandAlias(t *testing.T) { { name: "No tag defined", args: args{ - alias: "tag:foo", + alias: "tag:hr-webserver", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "test"}, + Namespace: Namespace{Name: "mickael"}, }, }, aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"foo", "bar"}}, - TagOwners: TagOwners{"tag:test": []string{"group:foo"}}, + Groups: Groups{"group:accountant": []string{"joe", "marc"}}, + TagOwners: TagOwners{"tag:accountant-webserver": []string{"group:accountant"}}, }, }, want: []string{}, @@ -929,41 +929,41 @@ func Test_expandAlias(t *testing.T) { { name: "list host in namespace without correctly tagged servers", args: args{ - alias: "foo", + alias: "joe", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"foo"}}, + TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, }, want: []string{"100.64.0.4"}, @@ -1005,40 +1005,40 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { name: "exclude nodes with valid tags", args: args{ aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"foo"}}, + TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, nodes: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, - namespace: "foo", + namespace: "joe", }, want: []Machine{ { IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, wantErr: false, @@ -1047,54 +1047,60 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { name: "all nodes have invalid tags, don't exclude them", args: args{ aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:foo": []string{"foo"}}, + TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, nodes: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"hr-web1\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"hr-web2\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, - namespace: "foo", + namespace: "joe", }, want: []Machine{ { - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, - Namespace: Namespace{Name: "foo"}, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"hr-web1\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, - Namespace: Namespace{Name: "foo"}, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"hr-web2\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, - Namespace: Namespace{Name: "foo"}, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "joe"}, }, }, wantErr: false, From b3d0fb7a939ceabd4c1f7743149fe41329e29e7b Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 20 Feb 2022 23:47:04 +0100 Subject: [PATCH 032/204] fix(machine): revert modifications Using h.ListAllMachines also listed the current machine in the result. It's unnecessary (I don't know if it's harmful). Breaking the check with the `matchSourceAndDestinationWithRule` broke the tests. We have a specificity with the '*' destination that isn't symetrical. I need to think of a better way to do this. It too hard to read. --- machine.go | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/machine.go b/machine.go index 4c984d6..46f20da 100644 --- a/machine.go +++ b/machine.go @@ -142,16 +142,6 @@ func containsAddresses(inputs []string, addrs MachineAddresses) bool { return false } -// matchSourceAndDestinationWithRule will check if source is authorized to communicate with destination through -// the given rule. -func matchSourceAndDestinationWithRule(rule tailcfg.FilterRule, source Machine, destination Machine) bool { - var dst []string - for _, d := range rule.DstPorts { - dst = append(dst, d.IP) - } - return (containsAddresses(rule.SrcIPs, source.IPAddresses) && containsAddresses(dst, destination.IPAddresses)) || containsString(dst, "*") -} - // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). @@ -159,9 +149,10 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { Str("machine", machine.Name). Msg("Finding peers filtered by ACLs") - machines, err := h.ListAllMachines() - if err != nil { - log.Error().Err(err).Msg("Error retrieving list of machines") + machines := Machines{} + if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", + machine.MachineKey).Find(&machines).Error; err != nil { + log.Error().Err(err).Msg("Error accessing db") return Machines{}, err } peers := make(map[uint64]Machine) @@ -185,7 +176,13 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { for _, peer := range machines { for _, rule := range h.aclRules { - if matchSourceAndDestinationWithRule(rule, *machine, peer) || matchSourceAndDestinationWithRule(rule, peer, *machine) { + var dst []string + for _, d := range rule.DstPorts { + dst = append(dst, d.IP) + } + if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, peer.IPAddresses) || containsString(dst, "*"))) || ( + // open return path + containsAddresses(rule.SrcIPs, peer.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { peers[peer.ID] = peer } } From 5242025ab3cc803c01932d7d903f747a8319913b Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 20 Feb 2022 23:50:08 +0100 Subject: [PATCH 033/204] fix(machines): renaming following review comments --- machine.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/machine.go b/machine.go index 46f20da..edebe03 100644 --- a/machine.go +++ b/machine.go @@ -188,13 +188,13 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { } } - authorizedMachines := make([]Machine, 0, len(peers)) + authorizedPeers := make([]Machine, 0, len(peers)) for _, m := range peers { - authorizedMachines = append(authorizedMachines, m) + authorizedPeers = append(authorizedPeers, m) } sort.Slice( - authorizedMachines, - func(i, j int) bool { return authorizedMachines[i].ID < authorizedMachines[j].ID }, + authorizedPeers, + func(i, j int) bool { return authorizedPeers[i].ID < authorizedPeers[j].ID }, ) log.Trace(). @@ -202,7 +202,7 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { Str("machine", machine.Name). Msgf("Found some machines: %v", machines) - return authorizedMachines, nil + return authorizedPeers, nil } func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { From 960412a335729869b063b7101ece86367f35c882 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 09:02:27 +0100 Subject: [PATCH 034/204] fix(machines): simplify complex if check This should fix the performance issue with computation of `dst` variable. It's also easier to read now. --- machine.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/machine.go b/machine.go index edebe03..4543407 100644 --- a/machine.go +++ b/machine.go @@ -132,8 +132,8 @@ func (h *Headscale) ListAllMachines() ([]Machine, error) { return machines, nil } -func containsAddresses(inputs []string, addrs MachineAddresses) bool { - for _, addr := range addrs.ToStringSlice() { +func containsAddresses(inputs []string, addrs []string) bool { + for _, addr := range addrs { if containsString(inputs, addr) { return true } @@ -142,6 +142,11 @@ func containsAddresses(inputs []string, addrs MachineAddresses) bool { return false } +// matchSourceAndDestinationWithRule +func matchSourceAndDestinationWithRule(ruleSources []string, ruleDestinations []string, source []string, destination []string) bool { + return containsAddresses(ruleSources, source) && containsAddresses(ruleDestinations, destination) +} + // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). @@ -180,9 +185,9 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { for _, d := range rule.DstPorts { dst = append(dst, d.IP) } - if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, peer.IPAddresses) || containsString(dst, "*"))) || ( - // open return path - containsAddresses(rule.SrcIPs, peer.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { + if matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), peer.IPAddresses.ToStringSlice()) || // match source and destination + matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), []string{"*"}) || // match source and all destination + matchSourceAndDestinationWithRule(rule.SrcIPs, dst, peer.IPAddresses.ToStringSlice(), machine.IPAddresses.ToStringSlice()) { // match return path peers[peer.ID] = peer } } From 9c6ce02554020ae114089eecc5e431c0d36dffe4 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 09:05:04 +0100 Subject: [PATCH 035/204] fix(machines): use ListAllMachines function added a simple filter to remove the current node --- machine.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/machine.go b/machine.go index 4543407..8a33e1d 100644 --- a/machine.go +++ b/machine.go @@ -154,10 +154,9 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { Str("machine", machine.Name). Msg("Finding peers filtered by ACLs") - machines := Machines{} - if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", - machine.MachineKey).Find(&machines).Error; err != nil { - log.Error().Err(err).Msg("Error accessing db") + machines, err := h.ListAllMachines() + if err != nil { + log.Error().Err(err).Msg("Error retrieving list of machines") return Machines{}, err } peers := make(map[uint64]Machine) @@ -180,6 +179,9 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { // how to talk to node A and then add the peering resource. for _, peer := range machines { + if peer.ID == machine.ID { + continue + } for _, rule := range h.aclRules { var dst []string for _, d := range rule.DstPorts { From f0068601364890852fde36a425299608ec82cca7 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 09:15:34 +0100 Subject: [PATCH 036/204] feat(machines): untie dependency with class for filter func The dependency to the `headscale` struct makes tests harder to do. This change allow to easily add some tests for this quite sensible function. --- machine.go | 19 ++++++++++--------- machine_test.go | 7 +++++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/machine.go b/machine.go index 8a33e1d..30c4ad9 100644 --- a/machine.go +++ b/machine.go @@ -148,19 +148,13 @@ func matchSourceAndDestinationWithRule(ruleSources []string, ruleDestinations [] } // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. -func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { +func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machine *Machine) (Machines, error) { log.Trace(). Caller(). Str("machine", machine.Name). Msg("Finding peers filtered by ACLs") - machines, err := h.ListAllMachines() - if err != nil { - log.Error().Err(err).Msg("Error retrieving list of machines") - return Machines{}, err - } peers := make(map[uint64]Machine) - // Aclfilter peers here. We are itering through machines in all namespaces and search through the computed aclRules // for match between rule SrcIPs and DstPorts. If the rule is a match we allow the machine to be viewable. @@ -182,7 +176,7 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { if peer.ID == machine.ID { continue } - for _, rule := range h.aclRules { + for _, rule := range rules { var dst []string for _, d := range rule.DstPorts { dst = append(dst, d.IP) @@ -301,10 +295,17 @@ func (h *Headscale) getSharedTo(machine *Machine) (Machines, error) { func (h *Headscale) getPeers(machine *Machine) (Machines, error) { var peers Machines var err error + // If ACLs rules are defined, filter visible host list with the ACLs // else use the classic namespace scope if h.aclPolicy != nil { - peers, err = h.getFilteredByACLPeers(machine) + var machines []Machine + machines, err = h.ListAllMachines() + if err != nil { + log.Error().Err(err).Msg("Error retrieving list of machines") + return Machines{}, err + } + peers, err = getFilteredByACLPeers(machines, h.aclRules, machine) if err != nil { log.Error(). Caller(). diff --git a/machine_test.go b/machine_test.go index f9e58be..90caf9d 100644 --- a/machine_test.go +++ b/machine_test.go @@ -219,10 +219,13 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { _, err = testMachine.GetHostInfo() c.Assert(err, check.IsNil) - peersOfTestMachine, err := app.getFilteredByACLPeers(testMachine) + machines, err := app.ListAllMachines() c.Assert(err, check.IsNil) - peersOfAdminMachine, err := app.getFilteredByACLPeers(adminMachine) + peersOfTestMachine, err := getFilteredByACLPeers(machines, app.aclRules, testMachine) + c.Assert(err, check.IsNil) + + peersOfAdminMachine, err := getFilteredByACLPeers(machines, app.aclRules, adminMachine) c.Assert(err, check.IsNil) c.Log(peersOfTestMachine) From 5ab62378aef28cfadf0739b891b0cd7b38d8c033 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 09:57:31 +0100 Subject: [PATCH 037/204] tests(machines): test all combinations of peer filtering --- machine_test.go | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/machine_test.go b/machine_test.go index 90caf9d..fb104f7 100644 --- a/machine_test.go +++ b/machine_test.go @@ -2,11 +2,14 @@ package headscale import ( "fmt" + "reflect" "strconv" + "testing" "time" "gopkg.in/check.v1" "inet.af/netaddr" + "tailscale.com/tailcfg" ) func (s *Suite) TestGetMachine(c *check.C) { @@ -295,3 +298,168 @@ func (s *Suite) TestSerdeAddressStrignSlice(c *check.C) { c.Assert(deserialized[i], check.Equals, input[i]) } } + +func Test_getFilteredByACLPeers(t *testing.T) { + type args struct { + machines []Machine + rules []tailcfg.FilterRule + machine *Machine + } + tests := []struct { + name string + args args + want Machines + wantErr bool + }{ + { + name: "all hosts can talk to each other", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + {SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + DstPorts: []tailcfg.NetPortRange{ + {IP: "*"}, + }, + }, + }, + machine: &Machine{ // current machine + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + }, + want: Machines{ + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + wantErr: false, + }, + { + name: "One host can talk to another, but not all hosts", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + {SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + DstPorts: []tailcfg.NetPortRange{ + {IP: "100.64.0.2"}, + }, + }, + }, + machine: &Machine{ // current machine + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + }, + want: Machines{ + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + }, + wantErr: false, + }, + { + name: "host cannot directly talk to destination, but return path is authorized", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + {SrcIPs: []string{"100.64.0.3"}, + DstPorts: []tailcfg.NetPortRange{ + {IP: "100.64.0.2"}, + }, + }, + }, + machine: &Machine{ // current machine + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + }, + want: Machines{ + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getFilteredByACLPeers(tt.args.machines, tt.args.rules, tt.args.machine) + if (err != nil) != tt.wantErr { + t.Errorf("getFilteredByACLPeers() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("getFilteredByACLPeers() = %v, want %v", got, tt.want) + } + }) + } +} + +var getFilteredByACLPeersTestRules = []tailcfg.FilterRule{ + { + SrcIPs: []string{"100.64.0.1"}, + DstPorts: []tailcfg.NetPortRange{{IP: "*"}}, + }, +} From 4bbe0051f6410b934b4585a4d690d442cbb21791 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 10:02:59 +0100 Subject: [PATCH 038/204] chore(machines): apply lint --- machine.go | 15 ++++----------- machine_test.go | 39 ++++++++++++--------------------------- 2 files changed, 16 insertions(+), 38 deletions(-) diff --git a/machine.go b/machine.go index 30c4ad9..0ec7b81 100644 --- a/machine.go +++ b/machine.go @@ -142,13 +142,13 @@ func containsAddresses(inputs []string, addrs []string) bool { return false } -// matchSourceAndDestinationWithRule +// matchSourceAndDestinationWithRule. func matchSourceAndDestinationWithRule(ruleSources []string, ruleDestinations []string, source []string, destination []string) bool { return containsAddresses(ruleSources, source) && containsAddresses(ruleDestinations, destination) } // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. -func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machine *Machine) (Machines, error) { +func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machine *Machine) Machines { log.Trace(). Caller(). Str("machine", machine.Name). @@ -203,7 +203,7 @@ func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machi Str("machine", machine.Name). Msgf("Found some machines: %v", machines) - return authorizedPeers, nil + return authorizedPeers } func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { @@ -303,17 +303,10 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) { machines, err = h.ListAllMachines() if err != nil { log.Error().Err(err).Msg("Error retrieving list of machines") - return Machines{}, err - } - peers, err = getFilteredByACLPeers(machines, h.aclRules, machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") return Machines{}, err } + peers = getFilteredByACLPeers(machines, h.aclRules, machine) } else { direct, err := h.getDirectPeers(machine) if err != nil { diff --git a/machine_test.go b/machine_test.go index fb104f7..3be3332 100644 --- a/machine_test.go +++ b/machine_test.go @@ -225,11 +225,8 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { machines, err := app.ListAllMachines() c.Assert(err, check.IsNil) - peersOfTestMachine, err := getFilteredByACLPeers(machines, app.aclRules, testMachine) - c.Assert(err, check.IsNil) - - peersOfAdminMachine, err := getFilteredByACLPeers(machines, app.aclRules, adminMachine) - c.Assert(err, check.IsNil) + peersOfTestMachine := getFilteredByACLPeers(machines, app.aclRules, testMachine) + peersOfAdminMachine := getFilteredByACLPeers(machines, app.aclRules, adminMachine) c.Log(peersOfTestMachine) c.Assert(len(peersOfTestMachine), check.Equals, 4) @@ -306,10 +303,9 @@ func Test_getFilteredByACLPeers(t *testing.T) { machine *Machine } tests := []struct { - name string - args args - want Machines - wantErr bool + name string + args args + want Machines }{ { name: "all hosts can talk to each other", @@ -332,7 +328,8 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered - {SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + { + SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, DstPorts: []tailcfg.NetPortRange{ {IP: "*"}, }, @@ -356,7 +353,6 @@ func Test_getFilteredByACLPeers(t *testing.T) { Namespace: Namespace{Name: "mickael"}, }, }, - wantErr: false, }, { name: "One host can talk to another, but not all hosts", @@ -379,7 +375,8 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered - {SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + { + SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, DstPorts: []tailcfg.NetPortRange{ {IP: "100.64.0.2"}, }, @@ -398,7 +395,6 @@ func Test_getFilteredByACLPeers(t *testing.T) { Namespace: Namespace{Name: "marc"}, }, }, - wantErr: false, }, { name: "host cannot directly talk to destination, but return path is authorized", @@ -421,7 +417,8 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered - {SrcIPs: []string{"100.64.0.3"}, + { + SrcIPs: []string{"100.64.0.3"}, DstPorts: []tailcfg.NetPortRange{ {IP: "100.64.0.2"}, }, @@ -440,26 +437,14 @@ func Test_getFilteredByACLPeers(t *testing.T) { Namespace: Namespace{Name: "mickael"}, }, }, - wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := getFilteredByACLPeers(tt.args.machines, tt.args.rules, tt.args.machine) - if (err != nil) != tt.wantErr { - t.Errorf("getFilteredByACLPeers() error = %v, wantErr %v", err, tt.wantErr) - return - } + got := getFilteredByACLPeers(tt.args.machines, tt.args.rules, tt.args.machine) if !reflect.DeepEqual(got, tt.want) { t.Errorf("getFilteredByACLPeers() = %v, want %v", got, tt.want) } }) } } - -var getFilteredByACLPeersTestRules = []tailcfg.FilterRule{ - { - SrcIPs: []string{"100.64.0.1"}, - DstPorts: []tailcfg.NetPortRange{{IP: "*"}}, - }, -} From 25550f886663c35c4a5c063f31ba93ef6beef89c Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 16:06:20 +0100 Subject: [PATCH 039/204] chore(format): run prettier on repo --- CHANGELOG.md | 8 ++--- acls_test.go | 6 ++-- machine.go | 23 ++++++++++++--- machine_test.go | 78 +++++++++++++++++++++++++++++++------------------ 4 files changed, 77 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cf99d9..6c04a17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,9 @@ **0.14.0 (2022-xx-xx):** **UPCOMING BREAKING**: -From the **next** version (`0.15.0`), all machines will be able to communicate regardless of -if they are in the same namespace. This means that the behaviour currently limited to ACLs -will become default. From version `0.15.0`, all limitation of communications must be done +From the **next** version (`0.15.0`), all machines will be able to communicate regardless of +if they are in the same namespace. This means that the behaviour currently limited to ACLs +will become default. From version `0.15.0`, all limitation of communications must be done with ACLs. This is a part of aligning `headscale`'s behaviour with Tailscale's upstream behaviour. @@ -17,7 +17,7 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - ACLs have been rewritten to align with the bevaviour Tailscale Control Panel provides. **NOTE:** This is only active if you use ACLs - Namespaces are now treated as Users - All machines can communicate with all machines by default - - Tags should now work correctly and adding a host to Headscale should now reload the rules. + - Tags should now work correctly and adding a host to Headscale should now reload the rules. - The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features **0.13.0 (2022-02-18):** diff --git a/acls_test.go b/acls_test.go index cb33309..44eb2e1 100644 --- a/acls_test.go +++ b/acls_test.go @@ -919,8 +919,10 @@ func Test_expandAlias(t *testing.T) { }, }, aclPolicy: ACLPolicy{ - Groups: Groups{"group:accountant": []string{"joe", "marc"}}, - TagOwners: TagOwners{"tag:accountant-webserver": []string{"group:accountant"}}, + Groups: Groups{"group:accountant": []string{"joe", "marc"}}, + TagOwners: TagOwners{ + "tag:accountant-webserver": []string{"group:accountant"}, + }, }, }, want: []string{}, diff --git a/machine.go b/machine.go index 0ec7b81..b1dd0d2 100644 --- a/machine.go +++ b/machine.go @@ -143,12 +143,22 @@ func containsAddresses(inputs []string, addrs []string) bool { } // matchSourceAndDestinationWithRule. -func matchSourceAndDestinationWithRule(ruleSources []string, ruleDestinations []string, source []string, destination []string) bool { - return containsAddresses(ruleSources, source) && containsAddresses(ruleDestinations, destination) +func matchSourceAndDestinationWithRule( + ruleSources []string, + ruleDestinations []string, + source []string, + destination []string, +) bool { + return containsAddresses(ruleSources, source) && + containsAddresses(ruleDestinations, destination) } // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. -func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machine *Machine) Machines { +func getFilteredByACLPeers( + machines []Machine, + rules []tailcfg.FilterRule, + machine *Machine, +) Machines { log.Trace(). Caller(). Str("machine", machine.Name). @@ -181,7 +191,12 @@ func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machi for _, d := range rule.DstPorts { dst = append(dst, d.IP) } - if matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), peer.IPAddresses.ToStringSlice()) || // match source and destination + if matchSourceAndDestinationWithRule( + rule.SrcIPs, + dst, + machine.IPAddresses.ToStringSlice(), + peer.IPAddresses.ToStringSlice(), + ) || // match source and destination matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), []string{"*"}) || // match source and all destination matchSourceAndDestinationWithRule(rule.SrcIPs, dst, peer.IPAddresses.ToStringSlice(), machine.IPAddresses.ToStringSlice()) { // match return path peers[peer.ID] = peer diff --git a/machine_test.go b/machine_test.go index 3be3332..b1cd341 100644 --- a/machine_test.go +++ b/machine_test.go @@ -312,19 +312,25 @@ func Test_getFilteredByACLPeers(t *testing.T) { args: args{ machines: []Machine{ // list of all machines in the database { - ID: 1, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, - Namespace: Namespace{Name: "joe"}, + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, }, { - ID: 2, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, - Namespace: Namespace{Name: "marc"}, + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, }, { - ID: 3, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, - Namespace: Namespace{Name: "mickael"}, + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered @@ -359,19 +365,25 @@ func Test_getFilteredByACLPeers(t *testing.T) { args: args{ machines: []Machine{ // list of all machines in the database { - ID: 1, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, - Namespace: Namespace{Name: "joe"}, + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, }, { - ID: 2, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, - Namespace: Namespace{Name: "marc"}, + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, }, { - ID: 3, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, - Namespace: Namespace{Name: "mickael"}, + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered @@ -401,19 +413,25 @@ func Test_getFilteredByACLPeers(t *testing.T) { args: args{ machines: []Machine{ // list of all machines in the database { - ID: 1, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, - Namespace: Namespace{Name: "joe"}, + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, }, { - ID: 2, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, - Namespace: Namespace{Name: "marc"}, + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, }, { - ID: 3, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, - Namespace: Namespace{Name: "mickael"}, + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered @@ -441,7 +459,11 @@ func Test_getFilteredByACLPeers(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := getFilteredByACLPeers(tt.args.machines, tt.args.rules, tt.args.machine) + got := getFilteredByACLPeers( + tt.args.machines, + tt.args.rules, + tt.args.machine, + ) if !reflect.DeepEqual(got, tt.want) { t.Errorf("getFilteredByACLPeers() = %v, want %v", got, tt.want) } From daa75da277085dbcffb45ea5a780520dab3231e6 Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Mon, 21 Feb 2022 10:09:23 -0500 Subject: [PATCH 040/204] Linting and updating tests --- app.go | 2 +- app_test.go | 10 ++++------ cmd/headscale/cli/utils.go | 17 +++++++++-------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app.go b/app.go index 8df56dd..26ec956 100644 --- a/app.go +++ b/app.go @@ -171,7 +171,7 @@ func LookupTLSClientAuthMode(mode string) (tls.ClientAuthType, bool) { // Client cert is _required and verified_. return tls.RequireAndVerifyClientCert, true default: - // Return the default when an unknown value is supplied. + // Return the default when an unknown value is supplied. return tls.RequireAnyClientCert, false } } diff --git a/app_test.go b/app_test.go index 3df5948..53c703a 100644 --- a/app_test.go +++ b/app_test.go @@ -69,9 +69,8 @@ func (s *Suite) ResetDB(c *check.C) { // Enusre an error is returned when an invalid auth mode // is supplied. func (s *Suite) TestInvalidClientAuthMode(c *check.C) { - app.cfg.TLSClientAuthMode = "invalid" - _, err := app.GetClientAuthMode() - c.Assert(err, check.NotNil) + _, isValid := LookupTLSClientAuthMode("invalid") + c.Assert(isValid, check.Equals, false) } // Ensure that all client auth modes return a nil error. @@ -79,8 +78,7 @@ func (s *Suite) TestAuthModes(c *check.C) { modes := []string{"disabled", "relaxed", "enforced"} for _, v := range modes { - app.cfg.TLSClientAuthMode = v - _, err := app.GetClientAuthMode() - c.Assert(err, check.IsNil) + _, isValid := LookupTLSClientAuthMode(v) + c.Assert(isValid, check.Equals, true) } } diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index dbcc8bb..9316302 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -34,7 +34,6 @@ const ( ) func LoadConfig(path string) error { - viper.SetConfigName("config") if path == "" { viper.AddConfigPath("/etc/headscale/") @@ -98,12 +97,12 @@ func LoadConfig(path string) error { _, authModeValid := headscale.LookupTLSClientAuthMode(viper.GetString("tls_client_auth_mode")) if !authModeValid { - errorText += fmt.Sprintf( - "Invalid tls_client_auth_mode supplied: %s. Accepted values: %s, %s, %s.", - viper.GetString("tls_client_auth_mode"), - headscale.DisabledClientAuth, - headscale.RelaxedClientAuth, - headscale.EnforcedClientAuth) + errorText += fmt.Sprintf( + "Invalid tls_client_auth_mode supplied: %s. Accepted values: %s, %s, %s.", + viper.GetString("tls_client_auth_mode"), + headscale.DisabledClientAuth, + headscale.RelaxedClientAuth, + headscale.EnforcedClientAuth) } if errorText != "" { @@ -295,7 +294,9 @@ func getHeadscaleConfig() headscale.Config { Msgf("'ip_prefixes' not configured, falling back to default: %v", prefixes) } - tlsClientAuthMode, _ := headscale.LookupTLSClientAuthMode(viper.GetString("tls_client_auth_mode")) + tlsClientAuthMode, _ := headscale.LookupTLSClientAuthMode( + viper.GetString("tls_client_auth_mode"), + ) return headscale.Config{ ServerURL: viper.GetString("server_url"), From 211fe4034a0b32cc1c86c60370a744642ad2e5d1 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 16:10:20 +0100 Subject: [PATCH 041/204] chore(linter): ignore tt var as it's generated code (vscode) --- .golangci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.golangci.yaml b/.golangci.yaml index 965f549..153cd7c 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -48,6 +48,7 @@ linters-settings: - ip - ok - c + - tt gocritic: disabled-checks: From b5a59d4e7acaef7e74b8015324cf77f7c59d150f Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Mon, 21 Feb 2022 10:20:11 -0500 Subject: [PATCH 042/204] updating changelog and docs --- CHANGELOG.md | 2 ++ docs/tls.md | 15 ++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70bda12..2aaf580 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ **TBD (TBD):** +- Add support for configurable mTLS [docs](docs/tls.md#configuring-mutual-tls-authentication-mtls) + **0.13.0 (2022-02-18):** **Features**: diff --git a/docs/tls.md b/docs/tls.md index d837144..7dc322c 100644 --- a/docs/tls.md +++ b/docs/tls.md @@ -32,16 +32,13 @@ tls_key_path: "" ### Configuring Mutual TLS Authentication (mTLS) -mTLS is a method by which an HTTPS server authenticates clients, e.g. Tailscale, -using TLS certificates. The capability can be configured by applying one of -the following values to the `tls_client_auth_mode` setting in the configuration -file. +mTLS is a method by which an HTTPS server authenticates clients, e.g. Tailscale, using TLS certificates. This can be configured by applying one of the following values to the `tls_client_auth_mode` setting in the configuration file. -| Value | Behavior | -| ---------- | ---------------------------------------------------------- | -| `disabled` | Disable mTLS (default). | -| `relaxed` | A client certificate is required, but it is not verified. | -| `enforced` | Requires clients to supply a certificate that is verified. | +| Value | Behavior | +| ------------------- | -----------------------------------------------------------| +| `disabled` | Disable mTLS. | +| `relaxed` (default) | A client certificate is required, but it is not verified. | +| `enforced` | Requires clients to supply a certificate that is verified. | ```yaml tls_client_auth_mode: "" From d5fd7a5c001111a99e496018ceb1c509f7806189 Mon Sep 17 00:00:00 2001 From: Nico Rey Date: Mon, 21 Feb 2022 12:50:15 -0300 Subject: [PATCH 043/204] metrics: add a new router and listener for Prometheus' metrics endpoint --- app.go | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/app.go b/app.go index ac350ec..4f910f0 100644 --- a/app.go +++ b/app.go @@ -68,6 +68,7 @@ const ( type Config struct { ServerURL string Addr string + MetricsAddr string GRPCAddr string GRPCAllowInsecure bool EphemeralNodeInactivityTimeout time.Duration @@ -406,11 +407,17 @@ func (h *Headscale) ensureUnixSocketIsAbsent() error { return os.Remove(h.cfg.UnixSocket) } -func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { - router := gin.Default() +func (h *Headscale) createPrometheusRouter() *gin.Engine { + promRouter := gin.Default() prometheus := ginprometheus.NewPrometheus("gin") - prometheus.Use(router) + prometheus.Use(promRouter) + + return promRouter +} + +func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { + router := gin.Default() router.GET( "/health", @@ -622,6 +629,27 @@ func (h *Headscale) Serve() error { log.Info(). Msgf("listening and serving HTTP on: %s", h.cfg.Addr) + promRouter := h.createPrometheusRouter() + + promHttpServer := &http.Server{ + Addr: h.cfg.MetricsAddr, + Handler: promRouter, + ReadTimeout: HTTPReadTimeout, + WriteTimeout: 0, + } + + var promHttpListener net.Listener + promHttpListener, err = net.Listen("tcp", h.cfg.MetricsAddr) + + if err != nil { + return fmt.Errorf("failed to bind to TCP address: %w", err) + } + + errorGroup.Go(func() error { return promHttpServer.Serve(promHttpListener) }) + + log.Info(). + Msgf("listening and serving metrics on: %s", h.cfg.MetricsAddr) + return errorGroup.Wait() } From 45d5ab30ffa7cd3fc0e675312c8844e60d03e7db Mon Sep 17 00:00:00 2001 From: Nico Rey Date: Mon, 21 Feb 2022 12:50:44 -0300 Subject: [PATCH 044/204] metrics/cfg: add a new entry for the Prometheus listen address --- cmd/headscale/cli/utils.go | 1 + config-example.yaml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 85dcae7..341a998 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -284,6 +284,7 @@ func getHeadscaleConfig() headscale.Config { return headscale.Config{ ServerURL: viper.GetString("server_url"), Addr: viper.GetString("listen_addr"), + MetricsAddr: viper.GetString("metrics_listen_addr"), GRPCAddr: viper.GetString("grpc_listen_addr"), GRPCAllowInsecure: viper.GetBool("grpc_allow_insecure"), diff --git a/config-example.yaml b/config-example.yaml index ba0c653..175f40b 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -16,6 +16,12 @@ server_url: http://127.0.0.1:8080 # listen_addr: 0.0.0.0:8080 +# Address to listen to /metrics, you may want +# to keep this endpoint private to your internal +# network +# +metrics_listen_addr: 127.0.0.1:8081 + # Address to listen for gRPC. # gRPC is used for controlling a headscale server # remotely with the CLI From fbc1843889619a44488ff69e2e7c9dc191f876b2 Mon Sep 17 00:00:00 2001 From: Nico Rey Date: Mon, 21 Feb 2022 12:51:05 -0300 Subject: [PATCH 045/204] metrics/tests: update tests --- cmd/headscale/headscale_test.go | 1 + integration_test/etc/config.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/cmd/headscale/headscale_test.go b/cmd/headscale/headscale_test.go index 5ab46e0..2edf2c1 100644 --- a/cmd/headscale/headscale_test.go +++ b/cmd/headscale/headscale_test.go @@ -55,6 +55,7 @@ func (*Suite) TestConfigLoading(c *check.C) { // Test that config file was interpreted correctly c.Assert(viper.GetString("server_url"), check.Equals, "http://127.0.0.1:8080") c.Assert(viper.GetString("listen_addr"), check.Equals, "0.0.0.0:8080") + c.Assert(viper.GetString("metrics_listen_addr"), check.Equals, "127.0.0.1:8081") c.Assert(viper.GetString("db_type"), check.Equals, "sqlite3") c.Assert(viper.GetString("db_path"), check.Equals, "/var/lib/headscale/db.sqlite") c.Assert(viper.GetString("tls_letsencrypt_hostname"), check.Equals, "") diff --git a/integration_test/etc/config.yaml b/integration_test/etc/config.yaml index 63af7eb..f1b04b6 100644 --- a/integration_test/etc/config.yaml +++ b/integration_test/etc/config.yaml @@ -14,6 +14,7 @@ dns_config: db_path: /tmp/integration_test_db.sqlite3 private_key_path: private.key listen_addr: 0.0.0.0:8080 +metrics_listen_addr: 127.0.0.1:8081 server_url: http://headscale:8080 derp: From 14e49885fbab368dfe1b782a45dd0fac9408f468 Mon Sep 17 00:00:00 2001 From: Nico Rey Date: Mon, 21 Feb 2022 12:51:25 -0300 Subject: [PATCH 046/204] metrics/kustomize: update Kustomize examples --- docs/examples/kustomize/base/configmap.yaml | 1 + docs/examples/kustomize/postgres/deployment.yaml | 5 +++++ docs/examples/kustomize/sqlite/statefulset.yaml | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/docs/examples/kustomize/base/configmap.yaml b/docs/examples/kustomize/base/configmap.yaml index 2e25e5f..5578958 100644 --- a/docs/examples/kustomize/base/configmap.yaml +++ b/docs/examples/kustomize/base/configmap.yaml @@ -5,4 +5,5 @@ metadata: data: server_url: $(PUBLIC_PROTO)://$(PUBLIC_HOSTNAME) listen_addr: "0.0.0.0:8080" + metrics_listen_addr: "127.0.0.1:8081" ephemeral_node_inactivity_timeout: "30m" diff --git a/docs/examples/kustomize/postgres/deployment.yaml b/docs/examples/kustomize/postgres/deployment.yaml index 75e6444..1dd88b4 100644 --- a/docs/examples/kustomize/postgres/deployment.yaml +++ b/docs/examples/kustomize/postgres/deployment.yaml @@ -25,6 +25,11 @@ spec: configMapKeyRef: name: headscale-config key: listen_addr + - name: METRICS_LISTEN_ADDR + valueFrom: + configMapKeyRef: + name: headscale-config + key: metrics_listen_addr - name: DERP_MAP_PATH value: /vol/config/derp.yaml - name: EPHEMERAL_NODE_INACTIVITY_TIMEOUT diff --git a/docs/examples/kustomize/sqlite/statefulset.yaml b/docs/examples/kustomize/sqlite/statefulset.yaml index 050bf76..2321d39 100644 --- a/docs/examples/kustomize/sqlite/statefulset.yaml +++ b/docs/examples/kustomize/sqlite/statefulset.yaml @@ -26,6 +26,11 @@ spec: configMapKeyRef: name: headscale-config key: listen_addr + - name: METRICS_LISTEN_ADDR + valueFrom: + configMapKeyRef: + name: headscale-config + key: metrics_listen_addr - name: DERP_MAP_PATH value: /vol/config/derp.yaml - name: EPHEMERAL_NODE_INACTIVITY_TIMEOUT From e3bcc88880eb2704dbcdb1eac79b79cfa48fe403 Mon Sep 17 00:00:00 2001 From: Nico Rey Date: Mon, 21 Feb 2022 15:22:36 -0300 Subject: [PATCH 047/204] Linter: make linter happy --- app.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app.go b/app.go index 4f910f0..5591180 100644 --- a/app.go +++ b/app.go @@ -631,21 +631,21 @@ func (h *Headscale) Serve() error { promRouter := h.createPrometheusRouter() - promHttpServer := &http.Server{ + promHTTPServer := &http.Server{ Addr: h.cfg.MetricsAddr, Handler: promRouter, ReadTimeout: HTTPReadTimeout, WriteTimeout: 0, } - var promHttpListener net.Listener - promHttpListener, err = net.Listen("tcp", h.cfg.MetricsAddr) + var promHTTPListener net.Listener + promHTTPListener, err = net.Listen("tcp", h.cfg.MetricsAddr) if err != nil { return fmt.Errorf("failed to bind to TCP address: %w", err) } - errorGroup.Go(func() error { return promHttpServer.Serve(promHttpListener) }) + errorGroup.Go(func() error { return promHTTPServer.Serve(promHTTPListener) }) log.Info(). Msgf("listening and serving metrics on: %s", h.cfg.MetricsAddr) From 50af44bc2fa7a578b3e141518ffcef2e32976325 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 20:06:31 +0100 Subject: [PATCH 048/204] fix: add error checking in acl and poll If aclPolicy is not defined, in updateAclPolicy, return an error. --- acls.go | 4 ++++ poll.go | 17 +++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/acls.go b/acls.go index f9ed09d..db2fc58 100644 --- a/acls.go +++ b/acls.go @@ -86,6 +86,10 @@ func (h *Headscale) UpdateACLRules() error { func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { rules := []tailcfg.FilterRule{} + if h.aclPolicy == nil { + return nil, errEmptyPolicy + } + machines, err := h.ListAllMachines() if err != nil { return nil, err diff --git a/poll.go b/poll.go index 96db43f..21aa3b3 100644 --- a/poll.go +++ b/poll.go @@ -95,15 +95,16 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { now := time.Now().UTC() // update ACLRules with peer informations (to update server tags if necessary) - err = h.UpdateACLRules() - if err != nil { - log.Error(). - Caller(). - Str("func", "handleAuthKey"). - Str("machine", machine.Name). - Err(err) + if h.aclPolicy != nil { + err = h.UpdateACLRules() + if err != nil { + log.Error(). + Caller(). + Str("func", "handleAuthKey"). + Str("machine", machine.Name). + Err(err) + } } - // From Tailscale client: // // ReadOnly is whether the client just wants to fetch the MapResponse, From baae266db015297ff304c1547fec6eed2fc6c45b Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 20:25:41 +0100 Subject: [PATCH 049/204] Update acls_test.go Co-authored-by: Kristoffer Dalby --- acls_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/acls_test.go b/acls_test.go index 44eb2e1..965c007 100644 --- a/acls_test.go +++ b/acls_test.go @@ -59,6 +59,7 @@ func (s *Suite) TestBasicRule(c *check.C) { c.Assert(rules, check.NotNil) } +# TODO(kradalby): Make tests values safe, independent and descriptive. func (s *Suite) TestInvalidAction(c *check.C) { app.aclPolicy = &ACLPolicy{ ACLs: []ACL{ From 650108c7c7fc7fdf84cd5cd2fbe6be043ef74dd9 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 21:45:15 +0100 Subject: [PATCH 050/204] chore(fmt): apply fmt --- machine.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/machine.go b/machine.go index b1dd0d2..ee48342 100644 --- a/machine.go +++ b/machine.go @@ -197,8 +197,18 @@ func getFilteredByACLPeers( machine.IPAddresses.ToStringSlice(), peer.IPAddresses.ToStringSlice(), ) || // match source and destination - matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), []string{"*"}) || // match source and all destination - matchSourceAndDestinationWithRule(rule.SrcIPs, dst, peer.IPAddresses.ToStringSlice(), machine.IPAddresses.ToStringSlice()) { // match return path + matchSourceAndDestinationWithRule( + rule.SrcIPs, + dst, + machine.IPAddresses.ToStringSlice(), + []string{"*"}, + ) || // match source and all destination + matchSourceAndDestinationWithRule( + rule.SrcIPs, + dst, + peer.IPAddresses.ToStringSlice(), + machine.IPAddresses.ToStringSlice(), + ) { // match return path peers[peer.ID] = peer } } From d971f0f0e62ec3ca3cf58f236db62fa9d09405a4 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 21:48:05 +0100 Subject: [PATCH 051/204] fix(acls_test): fix comment in go code --- acls_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acls_test.go b/acls_test.go index 965c007..5534257 100644 --- a/acls_test.go +++ b/acls_test.go @@ -59,7 +59,7 @@ func (s *Suite) TestBasicRule(c *check.C) { c.Assert(rules, check.NotNil) } -# TODO(kradalby): Make tests values safe, independent and descriptive. +// TODO(kradalby): Make tests values safe, independent and descriptive. func (s *Suite) TestInvalidAction(c *check.C) { app.aclPolicy = &ACLPolicy{ ACLs: []ACL{ From bbadeb567aa2c767e0ada229e4ce05b164316f42 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 21 Feb 2022 21:41:48 +0000 Subject: [PATCH 052/204] docs(README): update contributors --- README.md | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index e7ba664..071dd2b 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,13 @@ make build ohdearaugustin + + Adrien +
+ Adrien Raffin-Caboisse +
+
Alessandro @@ -157,6 +164,8 @@ make build Alessandro (Ale) Segala
unreality/ @@ -164,8 +173,6 @@ make build unreality
Eugen @@ -201,6 +208,8 @@ make build Michael G.
Paul @@ -208,8 +217,6 @@ make build Paul Tötterman
Casey @@ -245,6 +252,8 @@ make build thomas
Abraham @@ -252,15 +261,6 @@ make build Abraham Ingersoll
- - Adrien -
- Adrien Raffin-Caboisse -
-
Artem @@ -305,6 +305,13 @@ make build JJGadgets + + Jamie +
+ Jamie Greeff +
+
Jim @@ -333,6 +340,8 @@ make build Ryan Fowler
Shaanan @@ -340,8 +349,6 @@ make build Shaanan Cohney
Tanner/ @@ -377,6 +384,8 @@ make build Tjerk Woudsma
Zakhar @@ -384,8 +393,6 @@ make build Zakhar Bessarab
ZiYuan/ @@ -421,6 +428,8 @@ make build lion24
Wakeful-Cloud/ @@ -428,8 +437,6 @@ make build Wakeful-Cloud
zy/ From 9ceac5c0fc017e15670f4590aa6a8d1d5b281f77 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 22:44:08 +0000 Subject: [PATCH 053/204] Remove CLI and tests for Shared node --- cmd/headscale/cli/nodes.go | 157 ----------------------------- integration_cli_test.go | 195 +++++++++---------------------------- 2 files changed, 46 insertions(+), 306 deletions(-) diff --git a/cmd/headscale/cli/nodes.go b/cmd/headscale/cli/nodes.go index d6b86ee..a05339c 100644 --- a/cmd/headscale/cli/nodes.go +++ b/cmd/headscale/cli/nodes.go @@ -46,30 +46,6 @@ func init() { log.Fatalf(err.Error()) } nodeCmd.AddCommand(deleteNodeCmd) - - shareMachineCmd.Flags().StringP("namespace", "n", "", "Namespace") - err = shareMachineCmd.MarkFlagRequired("namespace") - if err != nil { - log.Fatalf(err.Error()) - } - shareMachineCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") - err = shareMachineCmd.MarkFlagRequired("identifier") - if err != nil { - log.Fatalf(err.Error()) - } - nodeCmd.AddCommand(shareMachineCmd) - - unshareMachineCmd.Flags().StringP("namespace", "n", "", "Namespace") - err = unshareMachineCmd.MarkFlagRequired("namespace") - if err != nil { - log.Fatalf(err.Error()) - } - unshareMachineCmd.Flags().Uint64P("identifier", "i", 0, "Node identifier (ID)") - err = unshareMachineCmd.MarkFlagRequired("identifier") - if err != nil { - log.Fatalf(err.Error()) - } - nodeCmd.AddCommand(unshareMachineCmd) } var nodeCmd = &cobra.Command{ @@ -317,139 +293,6 @@ var deleteNodeCmd = &cobra.Command{ }, } -func sharingWorker( - cmd *cobra.Command, -) (string, *v1.Machine, *v1.Namespace, error) { - output, _ := cmd.Flags().GetString("output") - namespaceStr, err := cmd.Flags().GetString("namespace") - if err != nil { - ErrorOutput(err, fmt.Sprintf("Error getting namespace: %s", err), output) - - return "", nil, nil, err - } - - ctx, client, conn, cancel := getHeadscaleCLIClient() - defer cancel() - defer conn.Close() - - identifier, err := cmd.Flags().GetUint64("identifier") - if err != nil { - ErrorOutput(err, fmt.Sprintf("Error converting ID to integer: %s", err), output) - - return "", nil, nil, err - } - - machineRequest := &v1.GetMachineRequest{ - MachineId: identifier, - } - - machineResponse, err := client.GetMachine(ctx, machineRequest) - if err != nil { - ErrorOutput( - err, - fmt.Sprintf("Error getting node node: %s", status.Convert(err).Message()), - output, - ) - - return "", nil, nil, err - } - - namespaceRequest := &v1.GetNamespaceRequest{ - Name: namespaceStr, - } - - namespaceResponse, err := client.GetNamespace(ctx, namespaceRequest) - if err != nil { - ErrorOutput( - err, - fmt.Sprintf("Error getting node node: %s", status.Convert(err).Message()), - output, - ) - - return "", nil, nil, err - } - - return output, machineResponse.GetMachine(), namespaceResponse.GetNamespace(), nil -} - -var shareMachineCmd = &cobra.Command{ - Use: "share", - Short: "Shares a node from the current namespace to the specified one", - Run: func(cmd *cobra.Command, args []string) { - output, machine, namespace, err := sharingWorker(cmd) - if err != nil { - ErrorOutput( - err, - fmt.Sprintf("Failed to fetch namespace or machine: %s", err), - output, - ) - - return - } - - ctx, client, conn, cancel := getHeadscaleCLIClient() - defer cancel() - defer conn.Close() - - request := &v1.ShareMachineRequest{ - MachineId: machine.Id, - Namespace: namespace.Name, - } - - response, err := client.ShareMachine(ctx, request) - if err != nil { - ErrorOutput( - err, - fmt.Sprintf("Error sharing node: %s", status.Convert(err).Message()), - output, - ) - - return - } - - SuccessOutput(response.Machine, "Node shared", output) - }, -} - -var unshareMachineCmd = &cobra.Command{ - Use: "unshare", - Short: "Unshares a node from the specified namespace", - Run: func(cmd *cobra.Command, args []string) { - output, machine, namespace, err := sharingWorker(cmd) - if err != nil { - ErrorOutput( - err, - fmt.Sprintf("Failed to fetch namespace or machine: %s", err), - output, - ) - - return - } - - ctx, client, conn, cancel := getHeadscaleCLIClient() - defer cancel() - defer conn.Close() - - request := &v1.UnshareMachineRequest{ - MachineId: machine.Id, - Namespace: namespace.Name, - } - - response, err := client.UnshareMachine(ctx, request) - if err != nil { - ErrorOutput( - err, - fmt.Sprintf("Error unsharing node: %s", status.Convert(err).Message()), - output, - ) - - return - } - - SuccessOutput(response.Machine, "Node unshared", output) - }, -} - func nodesToPtables( currentNamespace string, machines []*v1.Machine, diff --git a/integration_cli_test.go b/integration_cli_test.go index 818be91..aae80cb 100644 --- a/integration_cli_test.go +++ b/integration_cli_test.go @@ -529,7 +529,7 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { namespace, err := s.createNamespace("machine-namespace") assert.Nil(s.T(), err) - sharedNamespace, err := s.createNamespace("shared-namespace") + secondNamespace, err := s.createNamespace("other-namespace") assert.Nil(s.T(), err) // Randomly generated machine keys @@ -589,7 +589,7 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { assert.Len(s.T(), machines, len(machineKeys)) - // Test list all nodes after added shared + // Test list all nodes after added seconds listAllResult, err := ExecuteCommand( &s.headscale, []string{ @@ -627,14 +627,14 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { assert.True(s.T(), listAll[3].Registered) assert.True(s.T(), listAll[4].Registered) - sharedMachineKeys := []string{ + otherNamespaceMachineKeys := []string{ "b5b444774186d4217adcec407563a1223929465ee2c68a4da13af0d0185b4f8e", "dc721977ac7415aafa87f7d4574cbe07c6b171834a6d37375782bdc1fb6b3584", } - sharedMachines := make([]*v1.Machine, len(sharedMachineKeys)) + otherNamespaceMachines := make([]*v1.Machine, len(otherNamespaceMachineKeys)) assert.Nil(s.T(), err) - for index, machineKey := range sharedMachineKeys { + for index, machineKey := range otherNamespaceMachineKeys { _, err := ExecuteCommand( &s.headscale, []string{ @@ -642,9 +642,9 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { "debug", "create-node", "--name", - fmt.Sprintf("shared-machine-%d", index+1), + fmt.Sprintf("otherNamespace-machine-%d", index+1), "--namespace", - sharedNamespace.Name, + secondNamespace.Name, "--key", machineKey, "--output", @@ -660,7 +660,7 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { "headscale", "nodes", "--namespace", - sharedNamespace.Name, + secondNamespace.Name, "register", "--key", machineKey, @@ -675,13 +675,13 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { err = json.Unmarshal([]byte(machineResult), &machine) assert.Nil(s.T(), err) - sharedMachines[index] = &machine + otherNamespaceMachines[index] = &machine } - assert.Len(s.T(), sharedMachines, len(sharedMachineKeys)) + assert.Len(s.T(), otherNamespaceMachines, len(otherNamespaceMachineKeys)) - // Test list all nodes after added shared - listAllWithSharedResult, err := ExecuteCommand( + // Test list all nodes after added otherNamespace + listAllWithotherNamespaceResult, err := ExecuteCommand( &s.headscale, []string{ "headscale", @@ -694,31 +694,34 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { ) assert.Nil(s.T(), err) - var listAllWithShared []v1.Machine - err = json.Unmarshal([]byte(listAllWithSharedResult), &listAllWithShared) + var listAllWithotherNamespace []v1.Machine + err = json.Unmarshal( + []byte(listAllWithotherNamespaceResult), + &listAllWithotherNamespace, + ) assert.Nil(s.T(), err) - // All nodes, machines + shared - assert.Len(s.T(), listAllWithShared, 7) + // All nodes, machines + otherNamespace + assert.Len(s.T(), listAllWithotherNamespace, 7) - assert.Equal(s.T(), uint64(6), listAllWithShared[5].Id) - assert.Equal(s.T(), uint64(7), listAllWithShared[6].Id) + assert.Equal(s.T(), uint64(6), listAllWithotherNamespace[5].Id) + assert.Equal(s.T(), uint64(7), listAllWithotherNamespace[6].Id) - assert.Equal(s.T(), "shared-machine-1", listAllWithShared[5].Name) - assert.Equal(s.T(), "shared-machine-2", listAllWithShared[6].Name) + assert.Equal(s.T(), "otherNamespace-machine-1", listAllWithotherNamespace[5].Name) + assert.Equal(s.T(), "otherNamespace-machine-2", listAllWithotherNamespace[6].Name) - assert.True(s.T(), listAllWithShared[5].Registered) - assert.True(s.T(), listAllWithShared[6].Registered) + assert.True(s.T(), listAllWithotherNamespace[5].Registered) + assert.True(s.T(), listAllWithotherNamespace[6].Registered) - // Test list all nodes after added shared - listOnlySharedMachineNamespaceResult, err := ExecuteCommand( + // Test list all nodes after added otherNamespace + listOnlyotherNamespaceMachineNamespaceResult, err := ExecuteCommand( &s.headscale, []string{ "headscale", "nodes", "list", "--namespace", - sharedNamespace.Name, + secondNamespace.Name, "--output", "json", }, @@ -726,23 +729,31 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { ) assert.Nil(s.T(), err) - var listOnlySharedMachineNamespace []v1.Machine + var listOnlyotherNamespaceMachineNamespace []v1.Machine err = json.Unmarshal( - []byte(listOnlySharedMachineNamespaceResult), - &listOnlySharedMachineNamespace, + []byte(listOnlyotherNamespaceMachineNamespaceResult), + &listOnlyotherNamespaceMachineNamespace, ) assert.Nil(s.T(), err) - assert.Len(s.T(), listOnlySharedMachineNamespace, 2) + assert.Len(s.T(), listOnlyotherNamespaceMachineNamespace, 2) - assert.Equal(s.T(), uint64(6), listOnlySharedMachineNamespace[0].Id) - assert.Equal(s.T(), uint64(7), listOnlySharedMachineNamespace[1].Id) + assert.Equal(s.T(), uint64(6), listOnlyotherNamespaceMachineNamespace[0].Id) + assert.Equal(s.T(), uint64(7), listOnlyotherNamespaceMachineNamespace[1].Id) - assert.Equal(s.T(), "shared-machine-1", listOnlySharedMachineNamespace[0].Name) - assert.Equal(s.T(), "shared-machine-2", listOnlySharedMachineNamespace[1].Name) + assert.Equal( + s.T(), + "otherNamespace-machine-1", + listOnlyotherNamespaceMachineNamespace[0].Name, + ) + assert.Equal( + s.T(), + "otherNamespace-machine-2", + listOnlyotherNamespaceMachineNamespace[1].Name, + ) - assert.True(s.T(), listOnlySharedMachineNamespace[0].Registered) - assert.True(s.T(), listOnlySharedMachineNamespace[1].Registered) + assert.True(s.T(), listOnlyotherNamespaceMachineNamespace[0].Registered) + assert.True(s.T(), listOnlyotherNamespaceMachineNamespace[1].Registered) // Delete a machines _, err = ExecuteCommand( @@ -786,120 +797,6 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { assert.Nil(s.T(), err) assert.Len(s.T(), listOnlyMachineNamespaceAfterDelete, 4) - - // test: share node - - shareMachineResult, err := ExecuteCommand( - &s.headscale, - []string{ - "headscale", - "nodes", - "share", - "--namespace", - namespace.Name, - "--identifier", - "7", - "--output", - "json", - }, - []string{}, - ) - assert.Nil(s.T(), err) - - var shareMachine v1.Machine - err = json.Unmarshal([]byte(shareMachineResult), &shareMachine) - assert.Nil(s.T(), err) - - assert.Equal(s.T(), uint64(7), shareMachine.Id) - - assert.Equal(s.T(), "shared-machine-2", shareMachine.Name) - - assert.True(s.T(), shareMachine.Registered) - - // Test: list main namespace after machine has been shared - listOnlyMachineNamespaceAfterShareResult, err := ExecuteCommand( - &s.headscale, - []string{ - "headscale", - "nodes", - "list", - "--namespace", - namespace.Name, - "--output", - "json", - }, - []string{}, - ) - assert.Nil(s.T(), err) - - var listOnlyMachineNamespaceAfterShare []v1.Machine - err = json.Unmarshal( - []byte(listOnlyMachineNamespaceAfterShareResult), - &listOnlyMachineNamespaceAfterShare, - ) - assert.Nil(s.T(), err) - - assert.Len(s.T(), listOnlyMachineNamespaceAfterShare, 5) - - assert.Equal(s.T(), uint64(7), listOnlyMachineNamespaceAfterShare[4].Id) - - assert.Equal(s.T(), "shared-machine-2", listOnlyMachineNamespaceAfterShare[4].Name) - - assert.True(s.T(), listOnlyMachineNamespaceAfterShare[4].Registered) - - // test: unshare node - - unshareMachineResult, err := ExecuteCommand( - &s.headscale, - []string{ - "headscale", - "nodes", - "unshare", - "--namespace", - namespace.Name, - "--identifier", - "7", - "--output", - "json", - }, - []string{}, - ) - assert.Nil(s.T(), err) - - var unshareMachine v1.Machine - err = json.Unmarshal([]byte(unshareMachineResult), &unshareMachine) - assert.Nil(s.T(), err) - - assert.Equal(s.T(), uint64(7), unshareMachine.Id) - - assert.Equal(s.T(), "shared-machine-2", unshareMachine.Name) - - assert.True(s.T(), unshareMachine.Registered) - - // Test: list main namespace after machine has been shared - listOnlyMachineNamespaceAfterUnshareResult, err := ExecuteCommand( - &s.headscale, - []string{ - "headscale", - "nodes", - "list", - "--namespace", - namespace.Name, - "--output", - "json", - }, - []string{}, - ) - assert.Nil(s.T(), err) - - var listOnlyMachineNamespaceAfterUnshare []v1.Machine - err = json.Unmarshal( - []byte(listOnlyMachineNamespaceAfterUnshareResult), - &listOnlyMachineNamespaceAfterUnshare, - ) - assert.Nil(s.T(), err) - - assert.Len(s.T(), listOnlyMachineNamespaceAfterUnshare, 4) } func (s *IntegrationCLITestSuite) TestNodeExpireCommand() { From 6da2a19d1020cdc26fe57e9e80ba6778a235aa97 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 22:45:04 +0000 Subject: [PATCH 054/204] Remove grpc share/unshare functions --- grpcv1.go | 44 -------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/grpcv1.go b/grpcv1.go index 9762d22..75ce425 100644 --- a/grpcv1.go +++ b/grpcv1.go @@ -262,50 +262,6 @@ func (api headscaleV1APIServer) ListMachines( return &v1.ListMachinesResponse{Machines: response}, nil } -func (api headscaleV1APIServer) ShareMachine( - ctx context.Context, - request *v1.ShareMachineRequest, -) (*v1.ShareMachineResponse, error) { - destinationNamespace, err := api.h.GetNamespace(request.GetNamespace()) - if err != nil { - return nil, err - } - - machine, err := api.h.GetMachineByID(request.GetMachineId()) - if err != nil { - return nil, err - } - - err = api.h.AddSharedMachineToNamespace(machine, destinationNamespace) - if err != nil { - return nil, err - } - - return &v1.ShareMachineResponse{Machine: machine.toProto()}, nil -} - -func (api headscaleV1APIServer) UnshareMachine( - ctx context.Context, - request *v1.UnshareMachineRequest, -) (*v1.UnshareMachineResponse, error) { - destinationNamespace, err := api.h.GetNamespace(request.GetNamespace()) - if err != nil { - return nil, err - } - - machine, err := api.h.GetMachineByID(request.GetMachineId()) - if err != nil { - return nil, err - } - - err = api.h.RemoveSharedMachineFromNamespace(machine, destinationNamespace) - if err != nil { - return nil, err - } - - return &v1.UnshareMachineResponse{Machine: machine.toProto()}, nil -} - func (api headscaleV1APIServer) GetMachineRoute( ctx context.Context, request *v1.GetMachineRouteRequest, From 9d1752acbc7a7b66c84f26e87317da77239038a2 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 22:48:14 +0000 Subject: [PATCH 055/204] Remove protobuf share/unshare --- proto/headscale/v1/headscale.proto | 12 ------------ proto/headscale/v1/machine.proto | 18 ------------------ 2 files changed, 30 deletions(-) diff --git a/proto/headscale/v1/headscale.proto b/proto/headscale/v1/headscale.proto index 3cbbb8e..d6571b0 100644 --- a/proto/headscale/v1/headscale.proto +++ b/proto/headscale/v1/headscale.proto @@ -104,18 +104,6 @@ service HeadscaleService { get: "/api/v1/machine" }; } - - rpc ShareMachine(ShareMachineRequest) returns (ShareMachineResponse) { - option (google.api.http) = { - post: "/api/v1/machine/{machine_id}/share/{namespace}" - }; - } - - rpc UnshareMachine(UnshareMachineRequest) returns (UnshareMachineResponse) { - option (google.api.http) = { - post: "/api/v1/machine/{machine_id}/unshare/{namespace}" - }; - } // --- Machine end --- // --- Route start --- diff --git a/proto/headscale/v1/machine.proto b/proto/headscale/v1/machine.proto index 47664e1..7451db8 100644 --- a/proto/headscale/v1/machine.proto +++ b/proto/headscale/v1/machine.proto @@ -80,24 +80,6 @@ message ListMachinesResponse { repeated Machine machines = 1; } -message ShareMachineRequest { - uint64 machine_id = 1; - string namespace = 2; -} - -message ShareMachineResponse { - Machine machine = 1; -} - -message UnshareMachineRequest { - uint64 machine_id = 1; - string namespace = 2; -} - -message UnshareMachineResponse { - Machine machine = 1; -} - message DebugCreateMachineRequest { string namespace = 1; string key = 2; From 93997544897778672c54552644d6e972623f2345 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 22:48:27 +0000 Subject: [PATCH 056/204] Remove protobuf share/unshare generated go --- gen/go/headscale/v1/apikey.pb.go | 5 +- gen/go/headscale/v1/device.pb.go | 5 +- gen/go/headscale/v1/headscale.pb.go | 219 +++++----- gen/go/headscale/v1/headscale.pb.gw.go | 238 ----------- gen/go/headscale/v1/headscale_grpc.pb.go | 77 +--- gen/go/headscale/v1/machine.pb.go | 385 +++--------------- gen/go/headscale/v1/namespace.pb.go | 5 +- gen/go/headscale/v1/preauthkey.pb.go | 5 +- gen/go/headscale/v1/routes.pb.go | 5 +- .../headscale/v1/headscale.swagger.json | 110 +---- 10 files changed, 185 insertions(+), 869 deletions(-) diff --git a/gen/go/headscale/v1/apikey.pb.go b/gen/go/headscale/v1/apikey.pb.go index ace8b18..9e6fddb 100644 --- a/gen/go/headscale/v1/apikey.pb.go +++ b/gen/go/headscale/v1/apikey.pb.go @@ -7,12 +7,11 @@ package v1 import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) const ( diff --git a/gen/go/headscale/v1/device.pb.go b/gen/go/headscale/v1/device.pb.go index 5879251..2660701 100644 --- a/gen/go/headscale/v1/device.pb.go +++ b/gen/go/headscale/v1/device.pb.go @@ -7,12 +7,11 @@ package v1 import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) const ( diff --git a/gen/go/headscale/v1/headscale.pb.go b/gen/go/headscale/v1/headscale.pb.go index 7799082..5c70011 100644 --- a/gen/go/headscale/v1/headscale.pb.go +++ b/gen/go/headscale/v1/headscale.pb.go @@ -7,11 +7,10 @@ package v1 import ( - reflect "reflect" - _ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" ) const ( @@ -37,7 +36,7 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{ 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, - 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xcb, 0x15, 0x0a, 0x10, 0x48, 0x65, + 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xa3, 0x13, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x77, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, @@ -152,68 +151,50 @@ var file_headscale_v1_headscale_proto_rawDesc = []byte{ 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, - 0x12, 0x8d, 0x01, 0x0a, 0x0c, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, - 0x65, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x36, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x30, - 0x22, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, - 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x73, - 0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, - 0x12, 0x95, 0x01, 0x0a, 0x0e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, - 0x69, 0x6e, 0x65, 0x12, 0x23, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, - 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x32, 0x22, 0x30, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, - 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, - 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x75, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x2f, 0x7b, 0x6e, 0x61, - 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x12, 0x8b, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, - 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x68, - 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, - 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x25, 0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, - 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, - 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, - 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x22, 0x23, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, - 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, - 0x12, 0x70, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, - 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x22, - 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x3a, - 0x01, 0x2a, 0x12, 0x77, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, - 0x65, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x1a, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, - 0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0b, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, - 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, - 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, - 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, - 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, - 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, - 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x12, 0x8b, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x63, + 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, + 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x97, + 0x01, 0x0a, 0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, + 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x25, 0x22, 0x23, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x63, + 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x7b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, + 0x7d, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x70, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, + 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, + 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x65, + 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x22, 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, + 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x3a, 0x01, 0x2a, 0x12, 0x77, 0x0a, 0x0c, 0x45, 0x78, + 0x70, 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, 0x21, 0x2e, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, + 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, + 0x69, 0x72, 0x65, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x15, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x2f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, + 0x79, 0x73, 0x12, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, + 0x0e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x6b, 0x65, 0x79, 0x42, + 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, + 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, + 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var file_headscale_v1_headscale_proto_goTypes = []interface{}{ @@ -231,34 +212,30 @@ var file_headscale_v1_headscale_proto_goTypes = []interface{}{ (*DeleteMachineRequest)(nil), // 11: headscale.v1.DeleteMachineRequest (*ExpireMachineRequest)(nil), // 12: headscale.v1.ExpireMachineRequest (*ListMachinesRequest)(nil), // 13: headscale.v1.ListMachinesRequest - (*ShareMachineRequest)(nil), // 14: headscale.v1.ShareMachineRequest - (*UnshareMachineRequest)(nil), // 15: headscale.v1.UnshareMachineRequest - (*GetMachineRouteRequest)(nil), // 16: headscale.v1.GetMachineRouteRequest - (*EnableMachineRoutesRequest)(nil), // 17: headscale.v1.EnableMachineRoutesRequest - (*CreateApiKeyRequest)(nil), // 18: headscale.v1.CreateApiKeyRequest - (*ExpireApiKeyRequest)(nil), // 19: headscale.v1.ExpireApiKeyRequest - (*ListApiKeysRequest)(nil), // 20: headscale.v1.ListApiKeysRequest - (*GetNamespaceResponse)(nil), // 21: headscale.v1.GetNamespaceResponse - (*CreateNamespaceResponse)(nil), // 22: headscale.v1.CreateNamespaceResponse - (*RenameNamespaceResponse)(nil), // 23: headscale.v1.RenameNamespaceResponse - (*DeleteNamespaceResponse)(nil), // 24: headscale.v1.DeleteNamespaceResponse - (*ListNamespacesResponse)(nil), // 25: headscale.v1.ListNamespacesResponse - (*CreatePreAuthKeyResponse)(nil), // 26: headscale.v1.CreatePreAuthKeyResponse - (*ExpirePreAuthKeyResponse)(nil), // 27: headscale.v1.ExpirePreAuthKeyResponse - (*ListPreAuthKeysResponse)(nil), // 28: headscale.v1.ListPreAuthKeysResponse - (*DebugCreateMachineResponse)(nil), // 29: headscale.v1.DebugCreateMachineResponse - (*GetMachineResponse)(nil), // 30: headscale.v1.GetMachineResponse - (*RegisterMachineResponse)(nil), // 31: headscale.v1.RegisterMachineResponse - (*DeleteMachineResponse)(nil), // 32: headscale.v1.DeleteMachineResponse - (*ExpireMachineResponse)(nil), // 33: headscale.v1.ExpireMachineResponse - (*ListMachinesResponse)(nil), // 34: headscale.v1.ListMachinesResponse - (*ShareMachineResponse)(nil), // 35: headscale.v1.ShareMachineResponse - (*UnshareMachineResponse)(nil), // 36: headscale.v1.UnshareMachineResponse - (*GetMachineRouteResponse)(nil), // 37: headscale.v1.GetMachineRouteResponse - (*EnableMachineRoutesResponse)(nil), // 38: headscale.v1.EnableMachineRoutesResponse - (*CreateApiKeyResponse)(nil), // 39: headscale.v1.CreateApiKeyResponse - (*ExpireApiKeyResponse)(nil), // 40: headscale.v1.ExpireApiKeyResponse - (*ListApiKeysResponse)(nil), // 41: headscale.v1.ListApiKeysResponse + (*GetMachineRouteRequest)(nil), // 14: headscale.v1.GetMachineRouteRequest + (*EnableMachineRoutesRequest)(nil), // 15: headscale.v1.EnableMachineRoutesRequest + (*CreateApiKeyRequest)(nil), // 16: headscale.v1.CreateApiKeyRequest + (*ExpireApiKeyRequest)(nil), // 17: headscale.v1.ExpireApiKeyRequest + (*ListApiKeysRequest)(nil), // 18: headscale.v1.ListApiKeysRequest + (*GetNamespaceResponse)(nil), // 19: headscale.v1.GetNamespaceResponse + (*CreateNamespaceResponse)(nil), // 20: headscale.v1.CreateNamespaceResponse + (*RenameNamespaceResponse)(nil), // 21: headscale.v1.RenameNamespaceResponse + (*DeleteNamespaceResponse)(nil), // 22: headscale.v1.DeleteNamespaceResponse + (*ListNamespacesResponse)(nil), // 23: headscale.v1.ListNamespacesResponse + (*CreatePreAuthKeyResponse)(nil), // 24: headscale.v1.CreatePreAuthKeyResponse + (*ExpirePreAuthKeyResponse)(nil), // 25: headscale.v1.ExpirePreAuthKeyResponse + (*ListPreAuthKeysResponse)(nil), // 26: headscale.v1.ListPreAuthKeysResponse + (*DebugCreateMachineResponse)(nil), // 27: headscale.v1.DebugCreateMachineResponse + (*GetMachineResponse)(nil), // 28: headscale.v1.GetMachineResponse + (*RegisterMachineResponse)(nil), // 29: headscale.v1.RegisterMachineResponse + (*DeleteMachineResponse)(nil), // 30: headscale.v1.DeleteMachineResponse + (*ExpireMachineResponse)(nil), // 31: headscale.v1.ExpireMachineResponse + (*ListMachinesResponse)(nil), // 32: headscale.v1.ListMachinesResponse + (*GetMachineRouteResponse)(nil), // 33: headscale.v1.GetMachineRouteResponse + (*EnableMachineRoutesResponse)(nil), // 34: headscale.v1.EnableMachineRoutesResponse + (*CreateApiKeyResponse)(nil), // 35: headscale.v1.CreateApiKeyResponse + (*ExpireApiKeyResponse)(nil), // 36: headscale.v1.ExpireApiKeyResponse + (*ListApiKeysResponse)(nil), // 37: headscale.v1.ListApiKeysResponse } var file_headscale_v1_headscale_proto_depIdxs = []int32{ 0, // 0: headscale.v1.HeadscaleService.GetNamespace:input_type -> headscale.v1.GetNamespaceRequest @@ -275,36 +252,32 @@ var file_headscale_v1_headscale_proto_depIdxs = []int32{ 11, // 11: headscale.v1.HeadscaleService.DeleteMachine:input_type -> headscale.v1.DeleteMachineRequest 12, // 12: headscale.v1.HeadscaleService.ExpireMachine:input_type -> headscale.v1.ExpireMachineRequest 13, // 13: headscale.v1.HeadscaleService.ListMachines:input_type -> headscale.v1.ListMachinesRequest - 14, // 14: headscale.v1.HeadscaleService.ShareMachine:input_type -> headscale.v1.ShareMachineRequest - 15, // 15: headscale.v1.HeadscaleService.UnshareMachine:input_type -> headscale.v1.UnshareMachineRequest - 16, // 16: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest - 17, // 17: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest - 18, // 18: headscale.v1.HeadscaleService.CreateApiKey:input_type -> headscale.v1.CreateApiKeyRequest - 19, // 19: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest - 20, // 20: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest - 21, // 21: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse - 22, // 22: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse - 23, // 23: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse - 24, // 24: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse - 25, // 25: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse - 26, // 26: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse - 27, // 27: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse - 28, // 28: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse - 29, // 29: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse - 30, // 30: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse - 31, // 31: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse - 32, // 32: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse - 33, // 33: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse - 34, // 34: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse - 35, // 35: headscale.v1.HeadscaleService.ShareMachine:output_type -> headscale.v1.ShareMachineResponse - 36, // 36: headscale.v1.HeadscaleService.UnshareMachine:output_type -> headscale.v1.UnshareMachineResponse - 37, // 37: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse - 38, // 38: headscale.v1.HeadscaleService.EnableMachineRoutes:output_type -> headscale.v1.EnableMachineRoutesResponse - 39, // 39: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse - 40, // 40: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse - 41, // 41: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse - 21, // [21:42] is the sub-list for method output_type - 0, // [0:21] is the sub-list for method input_type + 14, // 14: headscale.v1.HeadscaleService.GetMachineRoute:input_type -> headscale.v1.GetMachineRouteRequest + 15, // 15: headscale.v1.HeadscaleService.EnableMachineRoutes:input_type -> headscale.v1.EnableMachineRoutesRequest + 16, // 16: headscale.v1.HeadscaleService.CreateApiKey:input_type -> headscale.v1.CreateApiKeyRequest + 17, // 17: headscale.v1.HeadscaleService.ExpireApiKey:input_type -> headscale.v1.ExpireApiKeyRequest + 18, // 18: headscale.v1.HeadscaleService.ListApiKeys:input_type -> headscale.v1.ListApiKeysRequest + 19, // 19: headscale.v1.HeadscaleService.GetNamespace:output_type -> headscale.v1.GetNamespaceResponse + 20, // 20: headscale.v1.HeadscaleService.CreateNamespace:output_type -> headscale.v1.CreateNamespaceResponse + 21, // 21: headscale.v1.HeadscaleService.RenameNamespace:output_type -> headscale.v1.RenameNamespaceResponse + 22, // 22: headscale.v1.HeadscaleService.DeleteNamespace:output_type -> headscale.v1.DeleteNamespaceResponse + 23, // 23: headscale.v1.HeadscaleService.ListNamespaces:output_type -> headscale.v1.ListNamespacesResponse + 24, // 24: headscale.v1.HeadscaleService.CreatePreAuthKey:output_type -> headscale.v1.CreatePreAuthKeyResponse + 25, // 25: headscale.v1.HeadscaleService.ExpirePreAuthKey:output_type -> headscale.v1.ExpirePreAuthKeyResponse + 26, // 26: headscale.v1.HeadscaleService.ListPreAuthKeys:output_type -> headscale.v1.ListPreAuthKeysResponse + 27, // 27: headscale.v1.HeadscaleService.DebugCreateMachine:output_type -> headscale.v1.DebugCreateMachineResponse + 28, // 28: headscale.v1.HeadscaleService.GetMachine:output_type -> headscale.v1.GetMachineResponse + 29, // 29: headscale.v1.HeadscaleService.RegisterMachine:output_type -> headscale.v1.RegisterMachineResponse + 30, // 30: headscale.v1.HeadscaleService.DeleteMachine:output_type -> headscale.v1.DeleteMachineResponse + 31, // 31: headscale.v1.HeadscaleService.ExpireMachine:output_type -> headscale.v1.ExpireMachineResponse + 32, // 32: headscale.v1.HeadscaleService.ListMachines:output_type -> headscale.v1.ListMachinesResponse + 33, // 33: headscale.v1.HeadscaleService.GetMachineRoute:output_type -> headscale.v1.GetMachineRouteResponse + 34, // 34: headscale.v1.HeadscaleService.EnableMachineRoutes:output_type -> headscale.v1.EnableMachineRoutesResponse + 35, // 35: headscale.v1.HeadscaleService.CreateApiKey:output_type -> headscale.v1.CreateApiKeyResponse + 36, // 36: headscale.v1.HeadscaleService.ExpireApiKey:output_type -> headscale.v1.ExpireApiKeyResponse + 37, // 37: headscale.v1.HeadscaleService.ListApiKeys:output_type -> headscale.v1.ListApiKeysResponse + 19, // [19:38] is the sub-list for method output_type + 0, // [0:19] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/gen/go/headscale/v1/headscale.pb.gw.go b/gen/go/headscale/v1/headscale.pb.gw.go index b245b89..0938e14 100644 --- a/gen/go/headscale/v1/headscale.pb.gw.go +++ b/gen/go/headscale/v1/headscale.pb.gw.go @@ -625,150 +625,6 @@ func local_request_HeadscaleService_ListMachines_0(ctx context.Context, marshale } -func request_HeadscaleService_ShareMachine_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ShareMachineRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["machine_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") - } - - protoReq.MachineId, err = runtime.Uint64(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) - } - - val, ok = pathParams["namespace"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "namespace") - } - - protoReq.Namespace, err = runtime.String(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "namespace", err) - } - - msg, err := client.ShareMachine(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_HeadscaleService_ShareMachine_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ShareMachineRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["machine_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") - } - - protoReq.MachineId, err = runtime.Uint64(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) - } - - val, ok = pathParams["namespace"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "namespace") - } - - protoReq.Namespace, err = runtime.String(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "namespace", err) - } - - msg, err := server.ShareMachine(ctx, &protoReq) - return msg, metadata, err - -} - -func request_HeadscaleService_UnshareMachine_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq UnshareMachineRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["machine_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") - } - - protoReq.MachineId, err = runtime.Uint64(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) - } - - val, ok = pathParams["namespace"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "namespace") - } - - protoReq.Namespace, err = runtime.String(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "namespace", err) - } - - msg, err := client.UnshareMachine(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_HeadscaleService_UnshareMachine_0(ctx context.Context, marshaler runtime.Marshaler, server HeadscaleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq UnshareMachineRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["machine_id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "machine_id") - } - - protoReq.MachineId, err = runtime.Uint64(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "machine_id", err) - } - - val, ok = pathParams["namespace"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "namespace") - } - - protoReq.Namespace, err = runtime.String(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "namespace", err) - } - - msg, err := server.UnshareMachine(ctx, &protoReq) - return msg, metadata, err - -} - func request_HeadscaleService_GetMachineRoute_0(ctx context.Context, marshaler runtime.Marshaler, client HeadscaleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetMachineRouteRequest var metadata runtime.ServerMetadata @@ -1305,52 +1161,6 @@ func RegisterHeadscaleServiceHandlerServer(ctx context.Context, mux *runtime.Ser }) - mux.Handle("POST", pattern_HeadscaleService_ShareMachine_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/ShareMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/share/{namespace}")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_HeadscaleService_ShareMachine_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_HeadscaleService_ShareMachine_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_HeadscaleService_UnshareMachine_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/headscale.v1.HeadscaleService/UnshareMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/unshare/{namespace}")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_HeadscaleService_UnshareMachine_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_HeadscaleService_UnshareMachine_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - mux.Handle("GET", pattern_HeadscaleService_GetMachineRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1787,46 +1597,6 @@ func RegisterHeadscaleServiceHandlerClient(ctx context.Context, mux *runtime.Ser }) - mux.Handle("POST", pattern_HeadscaleService_ShareMachine_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/ShareMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/share/{namespace}")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_HeadscaleService_ShareMachine_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_HeadscaleService_ShareMachine_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_HeadscaleService_UnshareMachine_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/headscale.v1.HeadscaleService/UnshareMachine", runtime.WithHTTPPathPattern("/api/v1/machine/{machine_id}/unshare/{namespace}")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_HeadscaleService_UnshareMachine_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_HeadscaleService_UnshareMachine_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - mux.Handle("GET", pattern_HeadscaleService_GetMachineRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -1959,10 +1729,6 @@ var ( pattern_HeadscaleService_ListMachines_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "machine"}, "")) - pattern_HeadscaleService_ShareMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "machine", "machine_id", "share", "namespace"}, "")) - - pattern_HeadscaleService_UnshareMachine_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "machine", "machine_id", "unshare", "namespace"}, "")) - pattern_HeadscaleService_GetMachineRoute_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "machine", "machine_id", "routes"}, "")) pattern_HeadscaleService_EnableMachineRoutes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "machine", "machine_id", "routes"}, "")) @@ -2003,10 +1769,6 @@ var ( forward_HeadscaleService_ListMachines_0 = runtime.ForwardResponseMessage - forward_HeadscaleService_ShareMachine_0 = runtime.ForwardResponseMessage - - forward_HeadscaleService_UnshareMachine_0 = runtime.ForwardResponseMessage - forward_HeadscaleService_GetMachineRoute_0 = runtime.ForwardResponseMessage forward_HeadscaleService_EnableMachineRoutes_0 = runtime.ForwardResponseMessage diff --git a/gen/go/headscale/v1/headscale_grpc.pb.go b/gen/go/headscale/v1/headscale_grpc.pb.go index c75a36c..e4edf3f 100644 --- a/gen/go/headscale/v1/headscale_grpc.pb.go +++ b/gen/go/headscale/v1/headscale_grpc.pb.go @@ -1,10 +1,13 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc (unknown) +// source: headscale/v1/headscale.proto package v1 import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -36,8 +39,6 @@ type HeadscaleServiceClient interface { DeleteMachine(ctx context.Context, in *DeleteMachineRequest, opts ...grpc.CallOption) (*DeleteMachineResponse, error) ExpireMachine(ctx context.Context, in *ExpireMachineRequest, opts ...grpc.CallOption) (*ExpireMachineResponse, error) ListMachines(ctx context.Context, in *ListMachinesRequest, opts ...grpc.CallOption) (*ListMachinesResponse, error) - ShareMachine(ctx context.Context, in *ShareMachineRequest, opts ...grpc.CallOption) (*ShareMachineResponse, error) - UnshareMachine(ctx context.Context, in *UnshareMachineRequest, opts ...grpc.CallOption) (*UnshareMachineResponse, error) // --- Route start --- GetMachineRoute(ctx context.Context, in *GetMachineRouteRequest, opts ...grpc.CallOption) (*GetMachineRouteResponse, error) EnableMachineRoutes(ctx context.Context, in *EnableMachineRoutesRequest, opts ...grpc.CallOption) (*EnableMachineRoutesResponse, error) @@ -181,24 +182,6 @@ func (c *headscaleServiceClient) ListMachines(ctx context.Context, in *ListMachi return out, nil } -func (c *headscaleServiceClient) ShareMachine(ctx context.Context, in *ShareMachineRequest, opts ...grpc.CallOption) (*ShareMachineResponse, error) { - out := new(ShareMachineResponse) - err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/ShareMachine", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *headscaleServiceClient) UnshareMachine(ctx context.Context, in *UnshareMachineRequest, opts ...grpc.CallOption) (*UnshareMachineResponse, error) { - out := new(UnshareMachineResponse) - err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/UnshareMachine", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *headscaleServiceClient) GetMachineRoute(ctx context.Context, in *GetMachineRouteRequest, opts ...grpc.CallOption) (*GetMachineRouteResponse, error) { out := new(GetMachineRouteResponse) err := c.cc.Invoke(ctx, "/headscale.v1.HeadscaleService/GetMachineRoute", in, out, opts...) @@ -265,8 +248,6 @@ type HeadscaleServiceServer interface { DeleteMachine(context.Context, *DeleteMachineRequest) (*DeleteMachineResponse, error) ExpireMachine(context.Context, *ExpireMachineRequest) (*ExpireMachineResponse, error) ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error) - ShareMachine(context.Context, *ShareMachineRequest) (*ShareMachineResponse, error) - UnshareMachine(context.Context, *UnshareMachineRequest) (*UnshareMachineResponse, error) // --- Route start --- GetMachineRoute(context.Context, *GetMachineRouteRequest) (*GetMachineRouteResponse, error) EnableMachineRoutes(context.Context, *EnableMachineRoutesRequest) (*EnableMachineRoutesResponse, error) @@ -323,12 +304,6 @@ func (UnimplementedHeadscaleServiceServer) ExpireMachine(context.Context, *Expir func (UnimplementedHeadscaleServiceServer) ListMachines(context.Context, *ListMachinesRequest) (*ListMachinesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListMachines not implemented") } -func (UnimplementedHeadscaleServiceServer) ShareMachine(context.Context, *ShareMachineRequest) (*ShareMachineResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ShareMachine not implemented") -} -func (UnimplementedHeadscaleServiceServer) UnshareMachine(context.Context, *UnshareMachineRequest) (*UnshareMachineResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UnshareMachine not implemented") -} func (UnimplementedHeadscaleServiceServer) GetMachineRoute(context.Context, *GetMachineRouteRequest) (*GetMachineRouteResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetMachineRoute not implemented") } @@ -609,42 +584,6 @@ func _HeadscaleService_ListMachines_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } -func _HeadscaleService_ShareMachine_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ShareMachineRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(HeadscaleServiceServer).ShareMachine(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/headscale.v1.HeadscaleService/ShareMachine", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(HeadscaleServiceServer).ShareMachine(ctx, req.(*ShareMachineRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _HeadscaleService_UnshareMachine_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UnshareMachineRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(HeadscaleServiceServer).UnshareMachine(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/headscale.v1.HeadscaleService/UnshareMachine", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(HeadscaleServiceServer).UnshareMachine(ctx, req.(*UnshareMachineRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _HeadscaleService_GetMachineRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetMachineRouteRequest) if err := dec(in); err != nil { @@ -798,14 +737,6 @@ var HeadscaleService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListMachines", Handler: _HeadscaleService_ListMachines_Handler, }, - { - MethodName: "ShareMachine", - Handler: _HeadscaleService_ShareMachine_Handler, - }, - { - MethodName: "UnshareMachine", - Handler: _HeadscaleService_UnshareMachine_Handler, - }, { MethodName: "GetMachineRoute", Handler: _HeadscaleService_GetMachineRoute_Handler, diff --git a/gen/go/headscale/v1/machine.pb.go b/gen/go/headscale/v1/machine.pb.go index 5f12c6e..9a5064f 100644 --- a/gen/go/headscale/v1/machine.pb.go +++ b/gen/go/headscale/v1/machine.pb.go @@ -7,12 +7,11 @@ package v1 import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) const ( @@ -694,210 +693,6 @@ func (x *ListMachinesResponse) GetMachines() []*Machine { return nil } -type ShareMachineRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"` - Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` -} - -func (x *ShareMachineRequest) Reset() { - *x = ShareMachineRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ShareMachineRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ShareMachineRequest) ProtoMessage() {} - -func (x *ShareMachineRequest) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ShareMachineRequest.ProtoReflect.Descriptor instead. -func (*ShareMachineRequest) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{11} -} - -func (x *ShareMachineRequest) GetMachineId() uint64 { - if x != nil { - return x.MachineId - } - return 0 -} - -func (x *ShareMachineRequest) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -type ShareMachineResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Machine *Machine `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"` -} - -func (x *ShareMachineResponse) Reset() { - *x = ShareMachineResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ShareMachineResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ShareMachineResponse) ProtoMessage() {} - -func (x *ShareMachineResponse) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ShareMachineResponse.ProtoReflect.Descriptor instead. -func (*ShareMachineResponse) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{12} -} - -func (x *ShareMachineResponse) GetMachine() *Machine { - if x != nil { - return x.Machine - } - return nil -} - -type UnshareMachineRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - MachineId uint64 `protobuf:"varint,1,opt,name=machine_id,json=machineId,proto3" json:"machine_id,omitempty"` - Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` -} - -func (x *UnshareMachineRequest) Reset() { - *x = UnshareMachineRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UnshareMachineRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UnshareMachineRequest) ProtoMessage() {} - -func (x *UnshareMachineRequest) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UnshareMachineRequest.ProtoReflect.Descriptor instead. -func (*UnshareMachineRequest) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{13} -} - -func (x *UnshareMachineRequest) GetMachineId() uint64 { - if x != nil { - return x.MachineId - } - return 0 -} - -func (x *UnshareMachineRequest) GetNamespace() string { - if x != nil { - return x.Namespace - } - return "" -} - -type UnshareMachineResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Machine *Machine `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"` -} - -func (x *UnshareMachineResponse) Reset() { - *x = UnshareMachineResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UnshareMachineResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UnshareMachineResponse) ProtoMessage() {} - -func (x *UnshareMachineResponse) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use UnshareMachineResponse.ProtoReflect.Descriptor instead. -func (*UnshareMachineResponse) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{14} -} - -func (x *UnshareMachineResponse) GetMachine() *Machine { - if x != nil { - return x.Machine - } - return nil -} - type DebugCreateMachineRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -912,7 +707,7 @@ type DebugCreateMachineRequest struct { func (x *DebugCreateMachineRequest) Reset() { *x = DebugCreateMachineRequest{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[15] + mi := &file_headscale_v1_machine_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -925,7 +720,7 @@ func (x *DebugCreateMachineRequest) String() string { func (*DebugCreateMachineRequest) ProtoMessage() {} func (x *DebugCreateMachineRequest) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[15] + mi := &file_headscale_v1_machine_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -938,7 +733,7 @@ func (x *DebugCreateMachineRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DebugCreateMachineRequest.ProtoReflect.Descriptor instead. func (*DebugCreateMachineRequest) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{15} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{11} } func (x *DebugCreateMachineRequest) GetNamespace() string { @@ -980,7 +775,7 @@ type DebugCreateMachineResponse struct { func (x *DebugCreateMachineResponse) Reset() { *x = DebugCreateMachineResponse{} if protoimpl.UnsafeEnabled { - mi := &file_headscale_v1_machine_proto_msgTypes[16] + mi := &file_headscale_v1_machine_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -993,7 +788,7 @@ func (x *DebugCreateMachineResponse) String() string { func (*DebugCreateMachineResponse) ProtoMessage() {} func (x *DebugCreateMachineResponse) ProtoReflect() protoreflect.Message { - mi := &file_headscale_v1_machine_proto_msgTypes[16] + mi := &file_headscale_v1_machine_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1006,7 +801,7 @@ func (x *DebugCreateMachineResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DebugCreateMachineResponse.ProtoReflect.Descriptor instead. func (*DebugCreateMachineResponse) Descriptor() ([]byte, []int) { - return file_headscale_v1_machine_proto_rawDescGZIP(), []int{16} + return file_headscale_v1_machine_proto_rawDescGZIP(), []int{12} } func (x *DebugCreateMachineResponse) GetMachine() *Machine { @@ -1105,51 +900,31 @@ var file_headscale_v1_machine_proto_rawDesc = []byte{ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, - 0x52, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x52, 0x0a, 0x13, 0x53, 0x68, - 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, - 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x47, - 0x0a, 0x14, 0x53, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, - 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, - 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x54, 0x0a, 0x15, 0x55, 0x6e, 0x73, 0x68, 0x61, - 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, - 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x49, 0x0a, - 0x16, 0x55, 0x6e, 0x73, 0x68, 0x61, 0x72, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, - 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x22, 0x77, 0x0a, 0x19, 0x44, 0x65, 0x62, 0x75, - 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x73, 0x22, 0x4d, 0x0a, 0x1a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, - 0x2a, 0x82, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, - 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, - 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x4b, 0x45, 0x59, - 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, - 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x43, 0x4c, 0x49, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x52, - 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4f, - 0x49, 0x44, 0x43, 0x10, 0x03, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, 0x65, 0x61, - 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x77, 0x0a, 0x19, 0x44, 0x65, + 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x73, 0x22, 0x4d, 0x0a, 0x1a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x63, 0x68, 0x69, + 0x6e, 0x65, 0x2a, 0x82, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, + 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, + 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x4b, + 0x45, 0x59, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, + 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x43, 0x4c, 0x49, 0x10, 0x02, 0x12, 0x18, 0x0a, + 0x14, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, + 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x03, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6a, 0x75, 0x61, 0x6e, 0x66, 0x6f, 0x6e, 0x74, 0x2f, 0x68, + 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, + 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1165,7 +940,7 @@ func file_headscale_v1_machine_proto_rawDescGZIP() []byte { } var file_headscale_v1_machine_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_headscale_v1_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_headscale_v1_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_headscale_v1_machine_proto_goTypes = []interface{}{ (RegisterMethod)(0), // 0: headscale.v1.RegisterMethod (*Machine)(nil), // 1: headscale.v1.Machine @@ -1179,36 +954,30 @@ var file_headscale_v1_machine_proto_goTypes = []interface{}{ (*ExpireMachineResponse)(nil), // 9: headscale.v1.ExpireMachineResponse (*ListMachinesRequest)(nil), // 10: headscale.v1.ListMachinesRequest (*ListMachinesResponse)(nil), // 11: headscale.v1.ListMachinesResponse - (*ShareMachineRequest)(nil), // 12: headscale.v1.ShareMachineRequest - (*ShareMachineResponse)(nil), // 13: headscale.v1.ShareMachineResponse - (*UnshareMachineRequest)(nil), // 14: headscale.v1.UnshareMachineRequest - (*UnshareMachineResponse)(nil), // 15: headscale.v1.UnshareMachineResponse - (*DebugCreateMachineRequest)(nil), // 16: headscale.v1.DebugCreateMachineRequest - (*DebugCreateMachineResponse)(nil), // 17: headscale.v1.DebugCreateMachineResponse - (*Namespace)(nil), // 18: headscale.v1.Namespace - (*timestamppb.Timestamp)(nil), // 19: google.protobuf.Timestamp - (*PreAuthKey)(nil), // 20: headscale.v1.PreAuthKey + (*DebugCreateMachineRequest)(nil), // 12: headscale.v1.DebugCreateMachineRequest + (*DebugCreateMachineResponse)(nil), // 13: headscale.v1.DebugCreateMachineResponse + (*Namespace)(nil), // 14: headscale.v1.Namespace + (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp + (*PreAuthKey)(nil), // 16: headscale.v1.PreAuthKey } var file_headscale_v1_machine_proto_depIdxs = []int32{ - 18, // 0: headscale.v1.Machine.namespace:type_name -> headscale.v1.Namespace + 14, // 0: headscale.v1.Machine.namespace:type_name -> headscale.v1.Namespace 0, // 1: headscale.v1.Machine.register_method:type_name -> headscale.v1.RegisterMethod - 19, // 2: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp - 19, // 3: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp - 19, // 4: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp - 20, // 5: headscale.v1.Machine.pre_auth_key:type_name -> headscale.v1.PreAuthKey - 19, // 6: headscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp + 15, // 2: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp + 15, // 3: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp + 15, // 4: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp + 16, // 5: headscale.v1.Machine.pre_auth_key:type_name -> headscale.v1.PreAuthKey + 15, // 6: headscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp 1, // 7: headscale.v1.RegisterMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 8: headscale.v1.GetMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 9: headscale.v1.ExpireMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 10: headscale.v1.ListMachinesResponse.machines:type_name -> headscale.v1.Machine - 1, // 11: headscale.v1.ShareMachineResponse.machine:type_name -> headscale.v1.Machine - 1, // 12: headscale.v1.UnshareMachineResponse.machine:type_name -> headscale.v1.Machine - 1, // 13: headscale.v1.DebugCreateMachineResponse.machine:type_name -> headscale.v1.Machine - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 1, // 11: headscale.v1.DebugCreateMachineResponse.machine:type_name -> headscale.v1.Machine + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_headscale_v1_machine_proto_init() } @@ -1352,54 +1121,6 @@ func file_headscale_v1_machine_proto_init() { } } file_headscale_v1_machine_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ShareMachineRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_headscale_v1_machine_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ShareMachineResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_headscale_v1_machine_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnshareMachineRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_headscale_v1_machine_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnshareMachineResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_headscale_v1_machine_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DebugCreateMachineRequest); i { case 0: return &v.state @@ -1411,7 +1132,7 @@ func file_headscale_v1_machine_proto_init() { return nil } } - file_headscale_v1_machine_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_headscale_v1_machine_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DebugCreateMachineResponse); i { case 0: return &v.state @@ -1430,7 +1151,7 @@ func file_headscale_v1_machine_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_headscale_v1_machine_proto_rawDesc, NumEnums: 1, - NumMessages: 17, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/gen/go/headscale/v1/namespace.pb.go b/gen/go/headscale/v1/namespace.pb.go index 0e0f827..f089365 100644 --- a/gen/go/headscale/v1/namespace.pb.go +++ b/gen/go/headscale/v1/namespace.pb.go @@ -7,12 +7,11 @@ package v1 import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) const ( diff --git a/gen/go/headscale/v1/preauthkey.pb.go b/gen/go/headscale/v1/preauthkey.pb.go index 056e0f3..645a0f0 100644 --- a/gen/go/headscale/v1/preauthkey.pb.go +++ b/gen/go/headscale/v1/preauthkey.pb.go @@ -7,12 +7,11 @@ package v1 import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) const ( diff --git a/gen/go/headscale/v1/routes.pb.go b/gen/go/headscale/v1/routes.pb.go index 12510f3..5ab4bbd 100644 --- a/gen/go/headscale/v1/routes.pb.go +++ b/gen/go/headscale/v1/routes.pb.go @@ -7,11 +7,10 @@ package v1 import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/gen/openapiv2/headscale/v1/headscale.swagger.json b/gen/openapiv2/headscale/v1/headscale.swagger.json index d91d0ba..db348f4 100644 --- a/gen/openapiv2/headscale/v1/headscale.swagger.json +++ b/gen/openapiv2/headscale/v1/headscale.swagger.json @@ -181,6 +181,20 @@ } } }, + "parameters": [ + { + "name": "namespace", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "key", + "in": "query", + "required": false, + "type": "string" + } + ], "tags": [ "HeadscaleService" ] @@ -324,37 +338,6 @@ } } }, - "parameters": [ - { - "name": "machineId", - "in": "path", - "required": true, - "type": "string", - "format": "uint64" - } - ], - "tags": [ - "HeadscaleService" - ] - } - }, - "/api/v1/machine/{machineId}/share/{namespace}": { - "post": { - "operationId": "HeadscaleService_ShareMachine", - "responses": { - "200": { - "description": "A successful response.", - "schema": { - "$ref": "#/definitions/v1ShareMachineResponse" - } - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "$ref": "#/definitions/rpcStatus" - } - } - }, "parameters": [ { "name": "machineId", @@ -364,47 +347,14 @@ "format": "uint64" }, { - "name": "namespace", - "in": "path", - "required": true, - "type": "string" - } - ], - "tags": [ - "HeadscaleService" - ] - } - }, - "/api/v1/machine/{machineId}/unshare/{namespace}": { - "post": { - "operationId": "HeadscaleService_UnshareMachine", - "responses": { - "200": { - "description": "A successful response.", - "schema": { - "$ref": "#/definitions/v1UnshareMachineResponse" - } - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "$ref": "#/definitions/rpcStatus" - } - } - }, - "parameters": [ - { - "name": "machineId", - "in": "path", - "required": true, - "type": "string", - "format": "uint64" - }, - { - "name": "namespace", - "in": "path", - "required": true, - "type": "string" + "name": "routes", + "in": "query", + "required": false, + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi" } ], "tags": [ @@ -1050,22 +1000,6 @@ } } } - }, - "v1ShareMachineResponse": { - "type": "object", - "properties": { - "machine": { - "$ref": "#/definitions/v1Machine" - } - } - }, - "v1UnshareMachineResponse": { - "type": "object", - "properties": { - "machine": { - "$ref": "#/definitions/v1Machine" - } - } } } } From 1e8f4dbdff593efa6c8f6003d8c7ad30ef8cb469 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 22:52:55 +0000 Subject: [PATCH 057/204] Drop shared node table --- db.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/db.go b/db.go index 1b53dc8..fea9e7f 100644 --- a/db.go +++ b/db.go @@ -53,10 +53,7 @@ func (h *Headscale) initDB() error { return err } - err = db.AutoMigrate(&SharedMachine{}) - if err != nil { - return err - } + _ = db.Migrator().DropTable("shared_machines") err = db.AutoMigrate(&APIKey{}) if err != nil { From 9411ec47c303ebab227d575bc8af662a82d7fd6f Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 22:53:30 +0000 Subject: [PATCH 058/204] Remove sharing class and tests --- sharing.go | 81 ------------ sharing_test.go | 341 ------------------------------------------------ 2 files changed, 422 deletions(-) delete mode 100644 sharing.go delete mode 100644 sharing_test.go diff --git a/sharing.go b/sharing.go deleted file mode 100644 index caac531..0000000 --- a/sharing.go +++ /dev/null @@ -1,81 +0,0 @@ -package headscale - -import "gorm.io/gorm" - -const ( - errSameNamespace = Error("Destination namespace same as origin") - errMachineAlreadyShared = Error("Node already shared to this namespace") - errMachineNotShared = Error("Machine not shared to this namespace") -) - -// SharedMachine is a join table to support sharing nodes between namespaces. -type SharedMachine struct { - gorm.Model - MachineID uint64 - Machine Machine - NamespaceID uint - Namespace Namespace -} - -// AddSharedMachineToNamespace adds a machine as a shared node to a namespace. -func (h *Headscale) AddSharedMachineToNamespace( - machine *Machine, - namespace *Namespace, -) error { - if machine.NamespaceID == namespace.ID { - return errSameNamespace - } - - sharedMachines := []SharedMachine{} - if err := h.db.Where("machine_id = ? AND namespace_id = ?", machine.ID, namespace.ID).Find(&sharedMachines).Error; err != nil { - return err - } - if len(sharedMachines) > 0 { - return errMachineAlreadyShared - } - - sharedMachine := SharedMachine{ - MachineID: machine.ID, - Machine: *machine, - NamespaceID: namespace.ID, - Namespace: *namespace, - } - h.db.Save(&sharedMachine) - - return nil -} - -// RemoveSharedMachineFromNamespace removes a shared machine from a namespace. -func (h *Headscale) RemoveSharedMachineFromNamespace( - machine *Machine, - namespace *Namespace, -) error { - if machine.NamespaceID == namespace.ID { - // Can't unshare from primary namespace - return errMachineNotShared - } - - sharedMachine := SharedMachine{} - result := h.db.Where("machine_id = ? AND namespace_id = ?", machine.ID, namespace.ID). - Unscoped(). - Delete(&sharedMachine) - if result.Error != nil { - return result.Error - } - - if result.RowsAffected == 0 { - return errMachineNotShared - } - - return nil -} - -// RemoveSharedMachineFromAllNamespaces removes a machine as a shared node from all namespaces. -func (h *Headscale) RemoveSharedMachineFromAllNamespaces(machine *Machine) error { - sharedMachine := SharedMachine{} - if result := h.db.Where("machine_id = ?", machine.ID).Unscoped().Delete(&sharedMachine); result.Error != nil { - return result.Error - } - - return nil -} diff --git a/sharing_test.go b/sharing_test.go deleted file mode 100644 index b7fef4e..0000000 --- a/sharing_test.go +++ /dev/null @@ -1,341 +0,0 @@ -package headscale - -import ( - "gopkg.in/check.v1" - "inet.af/netaddr" -) - -func CreateNodeNamespace( - c *check.C, - namespaceName, node, key, ip string, -) (*Namespace, *Machine) { - namespace, err := app.CreateNamespace(namespaceName) - c.Assert(err, check.IsNil) - - pak1, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) - c.Assert(err, check.IsNil) - - _, err = app.GetMachine(namespace.Name, node) - c.Assert(err, check.NotNil) - - machine := &Machine{ - ID: 0, - MachineKey: key, - NodeKey: key, - DiscoKey: key, - Name: node, - NamespaceID: namespace.ID, - Registered: true, - RegisterMethod: RegisterMethodAuthKey, - IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.1")}, - AuthKeyID: uint(pak1.ID), - } - app.db.Save(machine) - - _, err = app.GetMachine(namespace.Name, machine.Name) - c.Assert(err, check.IsNil) - - return namespace, machine -} - -func (s *Suite) TestBasicSharedNodesInNamespace(c *check.C) { - namespace1, machine1 := CreateNodeNamespace( - c, - "shared1", - "test_get_shared_nodes_1", - "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66", - "100.64.0.1", - ) - _, machine2 := CreateNodeNamespace( - c, - "shared2", - "test_get_shared_nodes_2", - "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863", - "100.64.0.2", - ) - - peersOfMachine1BeforeShared, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1BeforeShared), check.Equals, 0) - - err = app.AddSharedMachineToNamespace(machine2, namespace1) - c.Assert(err, check.IsNil) - - peersOfMachine1AfterShared, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1AfterShared), check.Equals, 1) - c.Assert(peersOfMachine1AfterShared[0].ID, check.Equals, machine2.ID) -} - -func (s *Suite) TestSameNamespace(c *check.C) { - namespace1, machine1 := CreateNodeNamespace( - c, - "shared1", - "test_get_shared_nodes_1", - "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66", - "100.64.0.1", - ) - - peersOfMachine1BeforeShare, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1BeforeShare), check.Equals, 0) - - err = app.AddSharedMachineToNamespace(machine1, namespace1) - c.Assert(err, check.Equals, errSameNamespace) -} - -func (s *Suite) TestUnshare(c *check.C) { - namespace1, machine1 := CreateNodeNamespace( - c, - "shared1", - "test_unshare_1", - "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66", - "100.64.0.1", - ) - _, machine2 := CreateNodeNamespace( - c, - "shared2", - "test_unshare_2", - "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863", - "100.64.0.2", - ) - - peersOfMachine1BeforeShare, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1BeforeShare), check.Equals, 0) - - err = app.AddSharedMachineToNamespace(machine2, namespace1) - c.Assert(err, check.IsNil) - - peersOfMachine1BeforeShare, err = app.getShared(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1BeforeShare), check.Equals, 1) - - err = app.RemoveSharedMachineFromNamespace(machine2, namespace1) - c.Assert(err, check.IsNil) - - peersOfMachine1BeforeShare, err = app.getShared(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1BeforeShare), check.Equals, 0) - - err = app.RemoveSharedMachineFromNamespace(machine2, namespace1) - c.Assert(err, check.Equals, errMachineNotShared) - - err = app.RemoveSharedMachineFromNamespace(machine1, namespace1) - c.Assert(err, check.Equals, errMachineNotShared) -} - -func (s *Suite) TestAlreadyShared(c *check.C) { - namespace1, machine1 := CreateNodeNamespace( - c, - "shared1", - "test_get_shared_nodes_1", - "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66", - "100.64.0.1", - ) - _, machine2 := CreateNodeNamespace( - c, - "shared2", - "test_get_shared_nodes_2", - "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863", - "100.64.0.2", - ) - - peersOfMachine1BeforeShare, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1BeforeShare), check.Equals, 0) - - err = app.AddSharedMachineToNamespace(machine2, namespace1) - c.Assert(err, check.IsNil) - err = app.AddSharedMachineToNamespace(machine2, namespace1) - c.Assert(err, check.Equals, errMachineAlreadyShared) -} - -func (s *Suite) TestDoNotIncludeRoutesOnShared(c *check.C) { - namespace1, machine1 := CreateNodeNamespace( - c, - "shared1", - "test_get_shared_nodes_1", - "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66", - "100.64.0.1", - ) - _, machine2 := CreateNodeNamespace( - c, - "shared2", - "test_get_shared_nodes_2", - "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863", - "100.64.0.2", - ) - - peersOfMachine1BeforeShare, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1BeforeShare), check.Equals, 0) - - err = app.AddSharedMachineToNamespace(machine2, namespace1) - c.Assert(err, check.IsNil) - - peersOfMachine1AfterShare, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1AfterShare), check.Equals, 1) - c.Assert(peersOfMachine1AfterShare[0].Name, check.Equals, "test_get_shared_nodes_2") -} - -func (s *Suite) TestComplexSharingAcrossNamespaces(c *check.C) { - namespace1, machine1 := CreateNodeNamespace( - c, - "shared1", - "test_get_shared_nodes_1", - "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66", - "100.64.0.1", - ) - _, machine2 := CreateNodeNamespace( - c, - "shared2", - "test_get_shared_nodes_2", - "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863", - "100.64.0.2", - ) - _, machine3 := CreateNodeNamespace( - c, - "shared3", - "test_get_shared_nodes_3", - "6e704bee83eb93db6fc2c417d7882964cd3f8cc87082cbb645982e34020c76c8", - "100.64.0.3", - ) - - pak4, err := app.CreatePreAuthKey(namespace1.Name, false, false, nil) - c.Assert(err, check.IsNil) - - machine4 := &Machine{ - ID: 4, - MachineKey: "4c3e07c3ecd40e9c945bb6797557c451850691c0409740578325e17009dd298f", - NodeKey: "4c3e07c3ecd40e9c945bb6797557c451850691c0409740578325e17009dd298f", - DiscoKey: "4c3e07c3ecd40e9c945bb6797557c451850691c0409740578325e17009dd298f", - Name: "test_get_shared_nodes_4", - NamespaceID: namespace1.ID, - Registered: true, - RegisterMethod: RegisterMethodAuthKey, - IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.4")}, - AuthKeyID: uint(pak4.ID), - } - app.db.Save(machine4) - - _, err = app.GetMachine(namespace1.Name, machine4.Name) - c.Assert(err, check.IsNil) - - peersOfMachine1BeforeShare, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1BeforeShare), check.Equals, 1) // node1 can see node4 - c.Assert(peersOfMachine1BeforeShare[0].Name, check.Equals, machine4.Name) - - err = app.AddSharedMachineToNamespace(machine2, namespace1) - c.Assert(err, check.IsNil) - - peersOfMachine1AfterShare, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert( - len(peersOfMachine1AfterShare), - check.Equals, - 2, - ) // node1 can see node2 (shared) and node4 (same namespace) - c.Assert(peersOfMachine1AfterShare[0].Name, check.Equals, machine2.Name) - c.Assert(peersOfMachine1AfterShare[1].Name, check.Equals, machine4.Name) - - sharedOfMachine1, err := app.getShared(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(sharedOfMachine1), check.Equals, 1) // node1 can see node2 as shared - c.Assert(sharedOfMachine1[0].Name, check.Equals, machine2.Name) - - peersOfMachine3, err := app.getPeers(machine3) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine3), check.Equals, 0) // node3 is alone - - peersOfMachine2, err := app.getPeers(machine2) - c.Assert(err, check.IsNil) - c.Assert( - len(peersOfMachine2), - check.Equals, - 2, - ) // node2 should see node1 (sharedTo) and node4 (sharedTo), as is shared in namespace1 - c.Assert(peersOfMachine2[0].Name, check.Equals, machine1.Name) - c.Assert(peersOfMachine2[1].Name, check.Equals, machine4.Name) -} - -func (s *Suite) TestDeleteSharedMachine(c *check.C) { - namespace1, machine1 := CreateNodeNamespace( - c, - "shared1", - "test_get_shared_nodes_1", - "686824e749f3b7f2a5927ee6c1e422aee5292592d9179a271ed7b3e659b44a66", - "100.64.0.1", - ) - _, machine2 := CreateNodeNamespace( - c, - "shared2", - "test_get_shared_nodes_2", - "dec46ef9dc45c7d2f03bfcd5a640d9e24e3cc68ce3d9da223867c9bc6d5e9863", - "100.64.0.2", - ) - _, machine3 := CreateNodeNamespace( - c, - "shared3", - "test_get_shared_nodes_3", - "6e704bee83eb93db6fc2c417d7882964cd3f8cc87082cbb645982e34020c76c8", - "100.64.0.3", - ) - - pak4n1, err := app.CreatePreAuthKey(namespace1.Name, false, false, nil) - c.Assert(err, check.IsNil) - machine4 := &Machine{ - ID: 4, - MachineKey: "4c3e07c3ecd40e9c945bb6797557c451850691c0409740578325e17009dd298f", - NodeKey: "4c3e07c3ecd40e9c945bb6797557c451850691c0409740578325e17009dd298f", - DiscoKey: "4c3e07c3ecd40e9c945bb6797557c451850691c0409740578325e17009dd298f", - Name: "test_get_shared_nodes_4", - NamespaceID: namespace1.ID, - Registered: true, - RegisterMethod: RegisterMethodAuthKey, - IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.4")}, - AuthKeyID: uint(pak4n1.ID), - } - app.db.Save(machine4) - - _, err = app.GetMachine(namespace1.Name, machine4.Name) - c.Assert(err, check.IsNil) - - peersOfMachine1BeforeShare, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1BeforeShare), check.Equals, 1) // nodes 1 and 4 - c.Assert(peersOfMachine1BeforeShare[0].Name, check.Equals, machine4.Name) - - err = app.AddSharedMachineToNamespace(machine2, namespace1) - c.Assert(err, check.IsNil) - - peersOfMachine1AfterShare, err := app.getPeers(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine1AfterShare), check.Equals, 2) // nodes 1, 2, 4 - c.Assert(peersOfMachine1AfterShare[0].Name, check.Equals, machine2.Name) - c.Assert(peersOfMachine1AfterShare[1].Name, check.Equals, machine4.Name) - - sharedOfMachine1, err := app.getShared(machine1) - c.Assert(err, check.IsNil) - c.Assert(len(sharedOfMachine1), check.Equals, 1) // nodes 1, 2, 4 - c.Assert(sharedOfMachine1[0].Name, check.Equals, machine2.Name) - - peersOfMachine3, err := app.getPeers(machine3) - c.Assert(err, check.IsNil) - c.Assert(len(peersOfMachine3), check.Equals, 0) // node 3 is alone - - sharedMachinesInNamespace1, err := app.ListSharedMachinesInNamespace( - namespace1.Name, - ) - c.Assert(err, check.IsNil) - c.Assert(len(sharedMachinesInNamespace1), check.Equals, 1) - - err = app.DeleteMachine(machine2) - c.Assert(err, check.IsNil) - - sharedMachinesInNamespace1, err = app.ListSharedMachinesInNamespace(namespace1.Name) - c.Assert(err, check.IsNil) - c.Assert(len(sharedMachinesInNamespace1), check.Equals, 0) -} From 24a8e198a1280596345dd412a0b249a16f86bbd4 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 23:01:35 +0000 Subject: [PATCH 059/204] Remove sharing references across the code --- grpcv1.go | 9 ----- machine.go | 107 ++------------------------------------------------ namespaces.go | 25 ------------ 3 files changed, 3 insertions(+), 138 deletions(-) diff --git a/grpcv1.go b/grpcv1.go index 75ce425..60e181d 100644 --- a/grpcv1.go +++ b/grpcv1.go @@ -232,15 +232,6 @@ func (api headscaleV1APIServer) ListMachines( return nil, err } - sharedMachines, err := api.h.ListSharedMachinesInNamespace( - request.GetNamespace(), - ) - if err != nil { - return nil, err - } - - machines = append(machines, sharedMachines...) - response := make([]*v1.Machine, len(machines)) for index, machine := range machines { response[index] = machine.toProto() diff --git a/machine.go b/machine.go index ee48342..6ada99b 100644 --- a/machine.go +++ b/machine.go @@ -3,7 +3,6 @@ package headscale import ( "database/sql/driver" "encoding/json" - "errors" "fmt" "sort" "strconv" @@ -255,68 +254,6 @@ func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { return machines, nil } -// getShared fetches machines that are shared to the `Namespace` of the machine we are getting peers for. -func (h *Headscale) getShared(machine *Machine) (Machines, error) { - log.Trace(). - Caller(). - Str("machine", machine.Name). - Msg("Finding shared peers") - - sharedMachines := []SharedMachine{} - if err := h.db.Preload("Namespace").Preload("Machine").Preload("Machine.Namespace").Where("namespace_id = ?", - machine.NamespaceID).Find(&sharedMachines).Error; err != nil { - return Machines{}, err - } - - peers := make(Machines, 0) - for _, sharedMachine := range sharedMachines { - peers = append(peers, sharedMachine.Machine) - } - - sort.Slice(peers, func(i, j int) bool { return peers[i].ID < peers[j].ID }) - - log.Trace(). - Caller(). - Str("machine", machine.Name). - Msgf("Found shared peers: %s", peers.String()) - - return peers, nil -} - -// getSharedTo fetches the machines of the namespaces this machine is shared in. -func (h *Headscale) getSharedTo(machine *Machine) (Machines, error) { - log.Trace(). - Caller(). - Str("machine", machine.Name). - Msg("Finding peers in namespaces this machine is shared with") - - sharedMachines := []SharedMachine{} - if err := h.db.Preload("Namespace").Preload("Machine").Preload("Machine.Namespace").Where("machine_id = ?", - machine.ID).Find(&sharedMachines).Error; err != nil { - return Machines{}, err - } - - peers := make(Machines, 0) - for _, sharedMachine := range sharedMachines { - namespaceMachines, err := h.ListMachinesInNamespace( - sharedMachine.Namespace.Name, - ) - if err != nil { - return Machines{}, err - } - peers = append(peers, namespaceMachines...) - } - - sort.Slice(peers, func(i, j int) bool { return peers[i].ID < peers[j].ID }) - - log.Trace(). - Caller(). - Str("machine", machine.Name). - Msgf("Found peers we are shared with: %s", peers.String()) - - return peers, nil -} - func (h *Headscale) getPeers(machine *Machine) (Machines, error) { var peers Machines var err error @@ -333,7 +270,7 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) { } peers = getFilteredByACLPeers(machines, h.aclRules, machine) } else { - direct, err := h.getDirectPeers(machine) + peers, err = h.getDirectPeers(machine) if err != nil { log.Error(). Caller(). @@ -342,28 +279,6 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) { return Machines{}, err } - - shared, err := h.getShared(machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") - - return Machines{}, err - } - - sharedTo, err := h.getSharedTo(machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") - - return Machines{}, err - } - peers = append(direct, shared...) - peers = append(peers, sharedTo...) } sort.Slice(peers, func(i, j int) bool { return peers[i].ID < peers[j].ID }) @@ -474,11 +389,6 @@ func (h *Headscale) RefreshMachine(machine *Machine, expiry time.Time) { // DeleteMachine softs deletes a Machine from the database. func (h *Headscale) DeleteMachine(machine *Machine) error { - err := h.RemoveSharedMachineFromAllNamespaces(machine) - if err != nil && errors.Is(err, errMachineNotShared) { - return err - } - machine.Registered = false h.db.Save(&machine) // we mark it as unregistered, just in case if err := h.db.Delete(&machine).Error; err != nil { @@ -498,11 +408,6 @@ func (h *Headscale) TouchMachine(machine *Machine) error { // HardDeleteMachine hard deletes a Machine from the database. func (h *Headscale) HardDeleteMachine(machine *Machine) error { - err := h.RemoveSharedMachineFromAllNamespaces(machine) - if err != nil && errors.Is(err, errMachineNotShared) { - return err - } - if err := h.db.Unscoped().Delete(&machine).Error; err != nil { return err } @@ -534,17 +439,9 @@ func (h *Headscale) isOutdated(machine *Machine) bool { return true } - sharedMachines, _ := h.getShared(machine) - namespaceSet := set.New(set.ThreadSafe) namespaceSet.Add(machine.Namespace.Name) - // Check if any of our shared namespaces has updates that we have - // not propagated. - for _, sharedMachine := range sharedMachines { - namespaceSet.Add(sharedMachine.Namespace.Name) - } - namespaces := make([]string, namespaceSet.Size()) for index, namespace := range namespaceSet.List() { if name, ok := namespace.(string); ok { @@ -659,6 +556,8 @@ func (machine Machine) toNode( []netaddr.IPPrefix{}, addrs...) // we append the node own IP, as it is required by the clients + // TODO(kradalby): Needs investigation, We probably dont need this condition + // now that we dont have shared nodes if includeRoutes { routesStr := []string{} if len(machine.EnabledRoutes) != 0 { diff --git a/namespaces.go b/namespaces.go index bdd440c..2eeee81 100644 --- a/namespaces.go +++ b/namespaces.go @@ -143,31 +143,6 @@ func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { return machines, nil } -// ListSharedMachinesInNamespace returns all the machines that are shared to the specified namespace. -func (h *Headscale) ListSharedMachinesInNamespace(name string) ([]Machine, error) { - namespace, err := h.GetNamespace(name) - if err != nil { - return nil, err - } - sharedMachines := []SharedMachine{} - if err := h.db.Preload("Namespace").Where(&SharedMachine{NamespaceID: namespace.ID}).Find(&sharedMachines).Error; err != nil { - return nil, err - } - - machines := []Machine{} - for _, sharedMachine := range sharedMachines { - machine, err := h.GetMachineByID( - sharedMachine.MachineID, - ) // otherwise not everything comes filled - if err != nil { - return nil, err - } - machines = append(machines, *machine) - } - - return machines, nil -} - // SetMachineNamespace assigns a Machine to a namespace. func (h *Headscale) SetMachineNamespace(machine *Machine, namespaceName string) error { namespace, err := h.GetNamespace(namespaceName) From 4ca8181dcbefdc89263d00d3de8ee86e2aab551b Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 23:04:10 +0000 Subject: [PATCH 060/204] Remove sharing from integration tests --- integration_test.go | 112 ++------------------------------------------ 1 file changed, 4 insertions(+), 108 deletions(-) diff --git a/integration_test.go b/integration_test.go index 43845b6..5024cd0 100644 --- a/integration_test.go +++ b/integration_test.go @@ -50,11 +50,11 @@ func TestIntegrationTestSuite(t *testing.T) { s := new(IntegrationTestSuite) s.namespaces = map[string]TestNamespace{ - "main": { - count: 20, + "thisspace": { + count: 15, tailscales: make(map[string]dockertest.Resource), }, - "shared": { + "otherspace": { count: 5, tailscales: make(map[string]dockertest.Resource), }, @@ -452,6 +452,7 @@ func getIPsfromIPNstate(status ipnstate.Status) []netaddr.IP { return ips } +// TODO: Adopt test for cross communication between namespaces func (s *IntegrationTestSuite) TestPingAllPeersByAddress() { for _, scales := range s.namespaces { ips, err := getIPs(scales.tailscales) @@ -497,111 +498,6 @@ func (s *IntegrationTestSuite) TestPingAllPeersByAddress() { } } -func (s *IntegrationTestSuite) TestSharedNodes() { - main := s.namespaces["main"] - shared := s.namespaces["shared"] - - result, err := ExecuteCommand( - &s.headscale, - []string{ - "headscale", - "nodes", - "list", - "--output", - "json", - "--namespace", - "shared", - }, - []string{}, - ) - assert.Nil(s.T(), err) - - var machineList []v1.Machine - err = json.Unmarshal([]byte(result), &machineList) - assert.Nil(s.T(), err) - - for _, machine := range machineList { - result, err := ExecuteCommand( - &s.headscale, - []string{ - "headscale", - "nodes", - "share", - "--identifier", fmt.Sprint(machine.Id), - "--namespace", "main", - }, - []string{}, - ) - assert.Nil(s.T(), err) - - fmt.Println("Shared node with result: ", result) - } - - result, err = ExecuteCommand( - &s.headscale, - []string{"headscale", "nodes", "list", "--namespace", "main"}, - []string{}, - ) - assert.Nil(s.T(), err) - fmt.Println("Nodelist after sharing", result) - - // Chck that the correct count of host is present in node list - lines := strings.Split(result, "\n") - assert.Equal(s.T(), len(main.tailscales)+len(shared.tailscales), len(lines)-2) - - for hostname := range main.tailscales { - assert.Contains(s.T(), result, hostname) - } - - for hostname := range shared.tailscales { - assert.Contains(s.T(), result, hostname) - } - - // TODO(juanfont): We have to find out why do we need to wait - time.Sleep(100 * time.Second) // Wait for the nodes to receive updates - - sharedIps, err := getIPs(shared.tailscales) - assert.Nil(s.T(), err) - - for hostname, tailscale := range main.tailscales { - for peername, peerIPs := range sharedIps { - for i, ip := range peerIPs { - // We currently cant ping ourselves, so skip that. - if peername == hostname { - continue - } - s.T(). - Run(fmt.Sprintf("%s-%s-%d", hostname, peername, i), func(t *testing.T) { - // We are only interested in "direct ping" which means what we - // might need a couple of more attempts before reaching the node. - command := []string{ - "tailscale", "ping", - "--timeout=15s", - "--c=20", - "--until-direct=true", - ip.String(), - } - - fmt.Printf( - "Pinging from %s to %s (%s)\n", - hostname, - peername, - ip, - ) - result, err := ExecuteCommand( - &tailscale, - command, - []string{}, - ) - assert.Nil(t, err) - fmt.Printf("Result for %s: %s\n", hostname, result) - assert.Contains(t, result, "pong") - }) - } - } - } -} - func (s *IntegrationTestSuite) TestTailDrop() { for _, scales := range s.namespaces { ips, err := getIPs(scales.tailscales) From f4c302f1fb4daff1c1435881695af10872ffb03e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 23:10:20 +0000 Subject: [PATCH 061/204] Uncomment tests that will failed in transition period --- dns_test.go | 32 ++++++++++-------------- namespaces_test.go | 62 ++++++++++++++++++++++------------------------ 2 files changed, 43 insertions(+), 51 deletions(-) diff --git a/dns_test.go b/dns_test.go index 80ee83b..b81bc7f 100644 --- a/dns_test.go +++ b/dns_test.go @@ -1,8 +1,6 @@ package headscale import ( - "fmt" - "gopkg.in/check.v1" "inet.af/netaddr" "tailscale.com/tailcfg" @@ -225,9 +223,6 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { } app.db.Save(machine2InShared1) - err = app.AddSharedMachineToNamespace(machineInShared2, namespaceShared1) - c.Assert(err, check.IsNil) - baseDomain := "foobar.headscale.net" dnsConfigOrig := tailcfg.DNSConfig{ Routes: make(map[string][]dnstype.Resolver), @@ -245,19 +240,21 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { peersOfMachineInShared1, ) c.Assert(dnsConfig, check.NotNil) - c.Assert(len(dnsConfig.Routes), check.Equals, 2) - domainRouteShared1 := fmt.Sprintf("%s.%s", namespaceShared1.Name, baseDomain) - _, ok := dnsConfig.Routes[domainRouteShared1] - c.Assert(ok, check.Equals, true) + // TODO: Remove comment out when we have all nodes available to every node + // c.Assert(len(dnsConfig.Routes), check.Equals, 2) - domainRouteShared2 := fmt.Sprintf("%s.%s", namespaceShared2.Name, baseDomain) - _, ok = dnsConfig.Routes[domainRouteShared2] - c.Assert(ok, check.Equals, true) - - domainRouteShared3 := fmt.Sprintf("%s.%s", namespaceShared3.Name, baseDomain) - _, ok = dnsConfig.Routes[domainRouteShared3] - c.Assert(ok, check.Equals, false) + // domainRouteShared1 := fmt.Sprintf("%s.%s", namespaceShared1.Name, baseDomain) + // _, ok := dnsConfig.Routes[domainRouteShared1] + // c.Assert(ok, check.Equals, true) + // + // domainRouteShared2 := fmt.Sprintf("%s.%s", namespaceShared2.Name, baseDomain) + // _, ok = dnsConfig.Routes[domainRouteShared2] + // c.Assert(ok, check.Equals, true) + // + // domainRouteShared3 := fmt.Sprintf("%s.%s", namespaceShared3.Name, baseDomain) + // _, ok = dnsConfig.Routes[domainRouteShared3] + // c.Assert(ok, check.Equals, false) } func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { @@ -374,9 +371,6 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { } app.db.Save(machine2InShared1) - err = app.AddSharedMachineToNamespace(machineInShared2, namespaceShared1) - c.Assert(err, check.IsNil) - baseDomain := "foobar.headscale.net" dnsConfigOrig := tailcfg.DNSConfig{ Routes: make(map[string][]dnstype.Resolver), diff --git a/namespaces_test.go b/namespaces_test.go index d07deb9..f7b345b 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -1,7 +1,6 @@ package headscale import ( - "github.com/rs/zerolog/log" "gopkg.in/check.v1" "gorm.io/gorm" "inet.af/netaddr" @@ -206,36 +205,35 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { } app.db.Save(machine2InShared1) - err = app.AddSharedMachineToNamespace(machineInShared2, namespaceShared1) - c.Assert(err, check.IsNil) - peersOfMachine1InShared1, err := app.getPeers(machineInShared1) - c.Assert(err, check.IsNil) + // TODO: Remove comment out when we have all nodes available to every node + // peersOfMachine1InShared1, err := app.getPeers(machineInShared1) + // c.Assert(err, check.IsNil) - userProfiles := getMapResponseUserProfiles( - *machineInShared1, - peersOfMachine1InShared1, - ) - - log.Trace().Msgf("userProfiles %#v", userProfiles) - c.Assert(len(userProfiles), check.Equals, 2) - - found := false - for _, userProfiles := range userProfiles { - if userProfiles.DisplayName == namespaceShared1.Name { - found = true - - break - } - } - c.Assert(found, check.Equals, true) - - found = false - for _, userProfile := range userProfiles { - if userProfile.DisplayName == namespaceShared2.Name { - found = true - - break - } - } - c.Assert(found, check.Equals, true) + // userProfiles := getMapResponseUserProfiles( + // *machineInShared1, + // peersOfMachine1InShared1, + // ) + // + // log.Trace().Msgf("userProfiles %#v", userProfiles) + // c.Assert(len(userProfiles), check.Equals, 2) + // + // found := false + // for _, userProfiles := range userProfiles { + // if userProfiles.DisplayName == namespaceShared1.Name { + // found = true + // + // break + // } + // } + // c.Assert(found, check.Equals, true) + // + // found = false + // for _, userProfile := range userProfiles { + // if userProfile.DisplayName == namespaceShared2.Name { + // found = true + // + // break + // } + // } + // c.Assert(found, check.Equals, true) } From 8dca40535fc3df976b3fdc847283e9c07e186028 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 21 Feb 2022 23:16:39 +0000 Subject: [PATCH 062/204] Test if we can join headscale in parallell to speed up --- integration_test.go | 113 +++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 49 deletions(-) diff --git a/integration_test.go b/integration_test.go index 43845b6..3075ac0 100644 --- a/integration_test.go +++ b/integration_test.go @@ -15,6 +15,7 @@ import ( "os" "path" "strings" + "sync" "testing" "time" @@ -44,6 +45,8 @@ type IntegrationTestSuite struct { headscale dockertest.Resource namespaces map[string]TestNamespace + + joinWaitGroup sync.WaitGroup } func TestIntegrationTestSuite(t *testing.T) { @@ -118,7 +121,7 @@ func (s *IntegrationTestSuite) saveLog( return err } - fmt.Printf("Saving logs for %s to %s\n", resource.Container.Name, basePath) + log.Printf("Saving logs for %s to %s\n", resource.Container.Name, basePath) err = ioutil.WriteFile( path.Join(basePath, resource.Container.Name+".stdout.log"), @@ -141,6 +144,34 @@ func (s *IntegrationTestSuite) saveLog( return nil } +func (s *IntegrationTestSuite) Join( + endpoint, key, hostname string, + tailscale dockertest.Resource, +) { + defer s.joinWaitGroup.Done() + + command := []string{ + "tailscale", + "up", + "-login-server", + endpoint, + "--authkey", + key, + "--hostname", + hostname, + } + + log.Println("Join command:", command) + log.Printf("Running join command for %s\n", hostname) + _, err := ExecuteCommand( + &tailscale, + command, + []string{}, + ) + assert.Nil(s.T(), err) + log.Printf("%s joined\n", hostname) +} + func (s *IntegrationTestSuite) tailscaleContainer( namespace, identifier, version string, ) (string, *dockertest.Resource) { @@ -178,7 +209,7 @@ func (s *IntegrationTestSuite) tailscaleContainer( if err != nil { log.Fatalf("Could not start resource: %s", err) } - fmt.Printf("Created %s container\n", hostname) + log.Printf("Created %s container\n", hostname) return hostname, pts } @@ -221,15 +252,15 @@ func (s *IntegrationTestSuite) SetupSuite() { Cmd: []string{"headscale", "serve"}, } - fmt.Println("Creating headscale container") + log.Println("Creating headscale container") if pheadscale, err := s.pool.BuildAndRunWithBuildOptions(headscaleBuildOptions, headscaleOptions, DockerRestartPolicy); err == nil { s.headscale = *pheadscale } else { log.Fatalf("Could not start resource: %s", err) } - fmt.Println("Created headscale container") + log.Println("Created headscale container") - fmt.Println("Creating tailscale containers") + log.Println("Creating tailscale containers") for namespace, scales := range s.namespaces { for i := 0; i < scales.count; i++ { version := tailscaleVersions[i%len(tailscaleVersions)] @@ -243,7 +274,7 @@ func (s *IntegrationTestSuite) SetupSuite() { } } - fmt.Println("Waiting for headscale to be ready") + log.Println("Waiting for headscale to be ready") hostEndpoint := fmt.Sprintf("localhost:%s", s.headscale.GetPort("8080/tcp")) if err := s.pool.Retry(func() error { @@ -266,19 +297,19 @@ func (s *IntegrationTestSuite) SetupSuite() { // https://github.com/stretchr/testify/issues/849 return // fmt.Errorf("Could not connect to headscale: %s", err) } - fmt.Println("headscale container is ready") + log.Println("headscale container is ready") for namespace, scales := range s.namespaces { - fmt.Printf("Creating headscale namespace: %s\n", namespace) + log.Printf("Creating headscale namespace: %s\n", namespace) result, err := ExecuteCommand( &s.headscale, []string{"headscale", "namespaces", "create", namespace}, []string{}, ) - fmt.Println("headscale create namespace result: ", result) + log.Println("headscale create namespace result: ", result) assert.Nil(s.T(), err) - fmt.Printf("Creating pre auth key for %s\n", namespace) + log.Printf("Creating pre auth key for %s\n", namespace) preAuthResult, err := ExecuteCommand( &s.headscale, []string{ @@ -304,33 +335,16 @@ func (s *IntegrationTestSuite) SetupSuite() { headscaleEndpoint := "http://headscale:8080" - fmt.Printf( + log.Printf( "Joining tailscale containers to headscale at %s\n", headscaleEndpoint, ) for hostname, tailscale := range scales.tailscales { - command := []string{ - "tailscale", - "up", - "-login-server", - headscaleEndpoint, - "--authkey", - preAuthKey.Key, - "--hostname", - hostname, - } - - fmt.Println("Join command:", command) - fmt.Printf("Running join command for %s\n", hostname) - result, err := ExecuteCommand( - &tailscale, - command, - []string{}, - ) - fmt.Println("tailscale result: ", result) - assert.Nil(s.T(), err) - fmt.Printf("%s joined\n", hostname) + s.joinWaitGroup.Add(1) + go s.Join(headscaleEndpoint, preAuthKey.Key, hostname, tailscale) } + + s.joinWaitGroup.Wait() } // The nodes need a bit of time to get their updated maps from headscale @@ -350,7 +364,7 @@ func (s *IntegrationTestSuite) HandleStats( func (s *IntegrationTestSuite) TestListNodes() { for namespace, scales := range s.namespaces { - fmt.Println("Listing nodes") + log.Println("Listing nodes") result, err := ExecuteCommand( &s.headscale, []string{"headscale", "--namespace", namespace, "nodes", "list"}, @@ -358,7 +372,7 @@ func (s *IntegrationTestSuite) TestListNodes() { ) assert.Nil(s.T(), err) - fmt.Printf("List nodes: \n%s\n", result) + log.Printf("List nodes: \n%s\n", result) // Chck that the correct count of host is present in node list lines := strings.Split(result, "\n") @@ -381,7 +395,7 @@ func (s *IntegrationTestSuite) TestGetIpAddresses() { s.T().Run(hostname, func(t *testing.T) { assert.NotNil(t, ip) - fmt.Printf("IP for %s: %s\n", hostname, ip) + log.Printf("IP for %s: %s\n", hostname, ip) // c.Assert(ip.Valid(), check.IsTrue) assert.True(t, ip.Is4() || ip.Is6()) @@ -410,7 +424,7 @@ func (s *IntegrationTestSuite) TestGetIpAddresses() { // s.T().Run(hostname, func(t *testing.T) { // command := []string{"tailscale", "status", "--json"} // -// fmt.Printf("Getting status for %s\n", hostname) +// log.Printf("Getting status for %s\n", hostname) // result, err := ExecuteCommand( // &tailscale, // command, @@ -476,7 +490,7 @@ func (s *IntegrationTestSuite) TestPingAllPeersByAddress() { ip.String(), } - fmt.Printf( + log.Printf( "Pinging from %s to %s (%s)\n", hostname, peername, @@ -488,7 +502,7 @@ func (s *IntegrationTestSuite) TestPingAllPeersByAddress() { []string{}, ) assert.Nil(t, err) - fmt.Printf("Result for %s: %s\n", hostname, result) + log.Printf("Result for %s: %s\n", hostname, result) assert.Contains(t, result, "pong") }) } @@ -534,7 +548,7 @@ func (s *IntegrationTestSuite) TestSharedNodes() { ) assert.Nil(s.T(), err) - fmt.Println("Shared node with result: ", result) + log.Println("Shared node with result: ", result) } result, err = ExecuteCommand( @@ -543,7 +557,7 @@ func (s *IntegrationTestSuite) TestSharedNodes() { []string{}, ) assert.Nil(s.T(), err) - fmt.Println("Nodelist after sharing", result) + log.Println("Nodelist after sharing", result) // Chck that the correct count of host is present in node list lines := strings.Split(result, "\n") @@ -582,7 +596,7 @@ func (s *IntegrationTestSuite) TestSharedNodes() { ip.String(), } - fmt.Printf( + log.Printf( "Pinging from %s to %s (%s)\n", hostname, peername, @@ -594,7 +608,7 @@ func (s *IntegrationTestSuite) TestSharedNodes() { []string{}, ) assert.Nil(t, err) - fmt.Printf("Result for %s: %s\n", hostname, result) + log.Printf("Result for %s: %s\n", hostname, result) assert.Contains(t, result, "pong") }) } @@ -616,6 +630,7 @@ func (s *IntegrationTestSuite) TestTailDrop() { } time.Sleep(sleepInverval) } + return } @@ -638,7 +653,7 @@ func (s *IntegrationTestSuite) TestTailDrop() { fmt.Sprintf("%s:", peername), } retry(10, 1*time.Second, func() error { - fmt.Printf( + log.Printf( "Sending file from %s to %s\n", hostname, peername, @@ -677,7 +692,7 @@ func (s *IntegrationTestSuite) TestTailDrop() { "ls", fmt.Sprintf("/tmp/file_from_%s", peername), } - fmt.Printf( + log.Printf( "Checking file in %s (%s) from %s (%s)\n", hostname, ips[hostname], @@ -690,7 +705,7 @@ func (s *IntegrationTestSuite) TestTailDrop() { []string{}, ) assert.Nil(t, err) - fmt.Printf("Result for %s: %s\n", peername, result) + log.Printf("Result for %s: %s\n", peername, result) assert.Equal( t, fmt.Sprintf("/tmp/file_from_%s\n", peername), @@ -720,7 +735,7 @@ func (s *IntegrationTestSuite) TestPingAllPeersByHostname() { fmt.Sprintf("%s.%s.headscale.net", peername, namespace), } - fmt.Printf( + log.Printf( "Pinging using hostname from %s to %s\n", hostname, peername, @@ -731,7 +746,7 @@ func (s *IntegrationTestSuite) TestPingAllPeersByHostname() { []string{}, ) assert.Nil(t, err) - fmt.Printf("Result for %s: %s\n", hostname, result) + log.Printf("Result for %s: %s\n", hostname, result) assert.Contains(t, result, "pong") }) } @@ -754,7 +769,7 @@ func (s *IntegrationTestSuite) TestMagicDNS() { fmt.Sprintf("%s.%s.headscale.net", peername, namespace), } - fmt.Printf( + log.Printf( "Resolving name %s from %s\n", peername, hostname, @@ -765,7 +780,7 @@ func (s *IntegrationTestSuite) TestMagicDNS() { []string{}, ) assert.Nil(t, err) - fmt.Printf("Result for %s: %s\n", hostname, result) + log.Printf("Result for %s: %s\n", hostname, result) for _, ip := range ips { assert.Contains(t, result, ip.String()) From fe2f75d13dd28bfc8ce1fc4be56cfed0447460ea Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 22 Feb 2022 07:40:56 +0000 Subject: [PATCH 063/204] Allow integration test to retry --- .github/workflows/test-integration.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index d9c52c7..b0e818d 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -29,4 +29,8 @@ jobs: - name: Run Integration tests if: steps.changed-files.outputs.any_changed == 'true' - run: go test -tags integration -timeout 30m + uses: nick-invision/retry@v2 + with: + max_attempts: 5 + retry_on: error + command: go test -tags integration -timeout 20m From f2f8d834e81bd1818e7f96a9446b356276927164 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 22 Feb 2022 11:26:21 +0100 Subject: [PATCH 064/204] fix(machine): remove comment After some more tests in tailscale I couldn't replicate the behavior described in there. When adding a rule, allowing A to talk to B the reverse connection was instantly added to B to allow communication to B. The previous assumption was probably wrong. --- machine.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/machine.go b/machine.go index ee48342..3c704ad 100644 --- a/machine.go +++ b/machine.go @@ -167,21 +167,6 @@ func getFilteredByACLPeers( peers := make(map[uint64]Machine) // Aclfilter peers here. We are itering through machines in all namespaces and search through the computed aclRules // for match between rule SrcIPs and DstPorts. If the rule is a match we allow the machine to be viewable. - - // FIXME: On official control plane if a rule allow user A to talk to user B but NO rule allows user B to talk to - // user A. The behaviour is the following - // - // On official tailscale control plane: - // on first `tailscale status`` on node A we can see node B. The `tailscale status` command on node B doesn't show node A - // We can successfully establish a communication from A to B. When it's done, if we run the `tailscale status` command - // on node B again we can now see node A. It's not possible to establish a communication from node B to node A. - // On this implementation of the feature - // on any `tailscale status` command on node A we can see node B. The `tailscale status` command on node B DOES show A. - // - // I couldn't find a way to not clutter the output of `tailscale status` with all nodes that we could be talking to. - // In order to do this we would need to be able to identify that node A want to talk to node B but that Node B doesn't know - // how to talk to node A and then add the peering resource. - for _, peer := range machines { if peer.ID == machine.ID { continue From f7eeb979fb01d09a8b0b0d014a69691945d20692 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 22 Feb 2022 13:46:59 +0000 Subject: [PATCH 065/204] Add timeout --- .github/workflows/test-integration.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index b0e818d..84651ab 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -31,6 +31,7 @@ jobs: if: steps.changed-files.outputs.any_changed == 'true' uses: nick-invision/retry@v2 with: + timeout_minutes: 100 max_attempts: 5 retry_on: error command: go test -tags integration -timeout 20m From 49623358604d02401581e7d9388883f4bbb39d93 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 22 Feb 2022 16:18:25 +0000 Subject: [PATCH 066/204] Remove dependency on CGO This commit changes the SQLite dependency to one that does not depend on CGO. It uses a C-to-Go translated sqlite library that is Pure go. --- .goreleaser.yml | 27 +-- CHANGELOG.md | 4 + Dockerfile | 2 +- Dockerfile.alpine | 2 +- Dockerfile.debug | 2 +- Makefile | 2 +- db.go | 2 +- go.mod | 21 ++- go.sum | 428 +++++++++++++++++----------------------------- 9 files changed, 192 insertions(+), 298 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index d1dec26..bd517d9 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -10,15 +10,12 @@ builds: - id: darwin-amd64 main: ./cmd/headscale/headscale.go mod_timestamp: "{{ .CommitTimestamp }}" + env: + - CGO_ENABLED=0 goos: - darwin goarch: - amd64 - env: - - PKG_CONFIG_SYSROOT_DIR=/sysroot/macos/amd64 - - PKG_CONFIG_PATH=/sysroot/macos/amd64/usr/local/lib/pkgconfig - - CC=o64-clang - - CXX=o64-clang++ flags: - -mod=readonly ldflags: @@ -27,46 +24,40 @@ builds: - id: linux-armhf main: ./cmd/headscale/headscale.go mod_timestamp: "{{ .CommitTimestamp }}" + env: + - CGO_ENABLED=0 goos: - linux goarch: - arm goarm: - "7" - env: - - CC=arm-linux-gnueabihf-gcc - - CXX=arm-linux-gnueabihf-g++ - - CGO_FLAGS=--sysroot=/sysroot/linux/armhf - - CGO_LDFLAGS=--sysroot=/sysroot/linux/armhf - - PKG_CONFIG_SYSROOT_DIR=/sysroot/linux/armhf - - PKG_CONFIG_PATH=/sysroot/linux/armhf/opt/vc/lib/pkgconfig:/sysroot/linux/armhf/usr/lib/arm-linux-gnueabihf/pkgconfig:/sysroot/linux/armhf/usr/lib/pkgconfig:/sysroot/linux/armhf/usr/local/lib/pkgconfig flags: - -mod=readonly ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} - id: linux-amd64 + mod_timestamp: "{{ .CommitTimestamp }}" env: - - CGO_ENABLED=1 + - CGO_ENABLED=0 goos: - linux goarch: - amd64 main: ./cmd/headscale/headscale.go - mod_timestamp: "{{ .CommitTimestamp }}" ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} - id: linux-arm64 + mod_timestamp: "{{ .CommitTimestamp }}" + env: + - CGO_ENABLED=0 goos: - linux goarch: - arm64 - env: - - CGO_ENABLED=1 - - CC=aarch64-linux-gnu-gcc main: ./cmd/headscale/headscale.go - mod_timestamp: "{{ .CommitTimestamp }}" ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c04a17..06a0ec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - Tags should now work correctly and adding a host to Headscale should now reload the rules. - The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features +**Changes**: + +- Remove dependency on CGO (switch from CGO SQLite to pure Go) [#346](https://github.com/juanfont/headscale/pull/346) + **0.13.0 (2022-02-18):** **Features**: diff --git a/Dockerfile b/Dockerfile index 6e57775..86f5bd4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ RUN go mod download COPY . . -RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale +RUN GGO_ENABLED=0 GOOS=linux go install -a ./cmd/headscale RUN strip /go/bin/headscale RUN test -e /go/bin/headscale diff --git a/Dockerfile.alpine b/Dockerfile.alpine index b07e190..af88434 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -9,7 +9,7 @@ RUN go mod download COPY . . -RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale +RUN GGO_ENABLED=0 GOOS=linux go install -a ./cmd/headscale RUN strip /go/bin/headscale RUN test -e /go/bin/headscale diff --git a/Dockerfile.debug b/Dockerfile.debug index 3d2675f..38385ce 100644 --- a/Dockerfile.debug +++ b/Dockerfile.debug @@ -8,7 +8,7 @@ RUN go mod download COPY . . -RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale +RUN GGO_ENABLED=0 GOOS=linux go install -a ./cmd/headscale RUN test -e /go/bin/headscale # Debug image diff --git a/Makefile b/Makefile index 69935bc..5214509 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ PROTO_SOURCES = $(call rwildcard,,*.proto) build: - go build -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go + GGO_ENABLED=0 go build -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go dev: lint test build diff --git a/db.go b/db.go index 1b53dc8..7aadd20 100644 --- a/db.go +++ b/db.go @@ -3,8 +3,8 @@ package headscale import ( "errors" + "github.com/glebarez/sqlite" "gorm.io/driver/postgres" - "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) diff --git a/go.mod b/go.mod index bbba464..8b721fa 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/efekarakus/termcolor v1.0.1 github.com/fatih/set v0.2.1 github.com/gin-gonic/gin v1.7.7 + github.com/glebarez/sqlite v1.3.5 github.com/gofrs/uuid v4.2.0+incompatible github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 @@ -19,14 +20,13 @@ require ( github.com/prometheus/client_golang v1.12.1 github.com/pterm/pterm v0.12.36 github.com/rs/zerolog v1.26.1 - github.com/soheilhy/cmux v0.1.5 github.com/spf13/cobra v1.3.0 github.com/spf13/viper v1.10.1 github.com/stretchr/testify v1.7.0 github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362 github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e github.com/zsais/go-gin-prometheus v0.1.0 - golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2 + golang.org/x/crypto v0.0.0-20220214200702-86341886e292 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336 @@ -36,9 +36,8 @@ require ( gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/yaml.v2 v2.4.0 gorm.io/datatypes v1.0.5 - gorm.io/driver/postgres v1.2.3 - gorm.io/driver/sqlite v1.2.6 - gorm.io/gorm v1.22.5 + gorm.io/driver/postgres v1.3.1 + gorm.io/gorm v1.23.1 inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 tailscale.com v1.20.4 ) @@ -58,8 +57,8 @@ require ( github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/ghodss/yaml v1.0.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/glebarez/go-sqlite v1.14.7 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.10.0 // indirect @@ -70,6 +69,7 @@ require ( github.com/google/go-github v17.0.0+incompatible // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gookit/color v1.5.0 // indirect github.com/hashicorp/go-version v1.4.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -112,6 +112,7 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/sirupsen/logrus v1.8.1 // indirect @@ -136,6 +137,12 @@ require ( gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - gorm.io/driver/mysql v1.2.3 // indirect + gorm.io/driver/mysql v1.3.2 // indirect + gorm.io/driver/sqlite v1.3.1 // indirect + gorm.io/driver/sqlserver v1.3.1 // indirect + modernc.org/libc v1.14.3 // indirect + modernc.org/mathutil v1.4.1 // indirect + modernc.org/memory v1.0.5 // indirect + modernc.org/sqlite v1.14.5 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 2814589..20eec3f 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -40,7 +39,6 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= @@ -56,6 +54,9 @@ contrib.go.opencensus.io/exporter/ocagent v0.7.0/go.mod h1:IshRmMJBhDfFj5Y67nVhM dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AlecAivazis/survey/v2 v2.3.2 h1:TqTB+aDDCLYhf9/bD2TwSO8u8jDSmMUd2SUVO4gCnU8= github.com/AlecAivazis/survey/v2 v2.3.2/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= @@ -63,9 +64,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= -github.com/MarvinJWendt/testza v0.2.1 h1:eitywm1lzygA2KCyn55jFVdOaXj5I9LeOsLNeifd2Kw= github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= @@ -74,7 +73,6 @@ github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzX github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= @@ -83,10 +81,6 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -94,20 +88,14 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -116,18 +104,11 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bufbuild/buf v0.37.0/go.mod h1:lQ1m2HkIaGOFba6w/aC3KYBHhKEOESP3gaAEpS3dAFM= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -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.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -141,7 +122,6 @@ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -155,13 +135,9 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= github.com/containerd/continuity v0.2.2 h1:QSqfxcn8c+12slxwu00AtzXrsami0MJb/MQs9lOLHLA= github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -171,11 +147,9 @@ github.com/coreos/go-oidc/v3 v3.1.0 h1:6avEvcdvTa1qYsOZ6I5PRkSYHzpTNWgKYmaJfaYbr github.com/coreos/go-oidc/v3 v3.1.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -190,38 +164,27 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8= -github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA= +github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.1-0.20200107013213-dc14462fd587+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.8+incompatible h1:/zO/6y9IOpcehE49yMRTV9ea0nBpb8OeqSskXLNfH1E= -github.com/docker/cli v20.10.8+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/cli v20.10.11+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v20.10.12+incompatible h1:lZlz0uzG+GH+c0plStMUdF/qk3ppmgnswpR5EbqzVGA= github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM= -github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U= github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/efekarakus/termcolor v1.0.1 h1:YAKFO3bnLrqZGTWyNLcYoSIAQFKVOmbqmDnwsU/znzg= github.com/efekarakus/termcolor v1.0.1/go.mod h1:AitrZNrE4nPO538fRsqf+p0WgLdAsGN5pUNrHEPsEMM= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -240,27 +203,24 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM= -github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= +github.com/glebarez/go-sqlite v1.14.7 h1:eXrKp59O5eWBfxv2Xfq5d7uex4+clKrOtWfMzzGSkoM= +github.com/glebarez/go-sqlite v1.14.7/go.mod h1:TKAw5tjyB/ocvVht7Xv4772qRAun5CG/xLCEbkDwNUc= +github.com/glebarez/sqlite v1.3.5 h1:R9op5nxb9Z10t4VXQSdAVyqRalLhWdLrlaT/iuvOGHI= +github.com/glebarez/sqlite v1.3.5/go.mod h1:ZffEtp/afVhV+jvIzQi8wlYEIkuGAYshr9OPKM/NmQc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -274,11 +234,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A= -github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -286,24 +243,20 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= -github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -336,7 +289,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -351,7 +303,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= @@ -381,49 +332,37 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.3.0/go.mod h1:d2gYTOTUQklu06xp0AJYYmRdTVU1VKrqhkYfYag2L08= github.com/grpc-ecosystem/grpc-gateway/v2 v2.4.0/go.mod h1:IOyTYjcIO0rkmnGBfJTL0NJ11exy/Tc2QEuv7hCXp24= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0 h1:rgxjzoDmDXw5q8HONgyHhBas4to0/XWRo/gPpJhsUNQ= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0/go.mod h1:qrJPVzv9YlhsrxJc3P/Q85nr0w1lIRikTl4JlhdDH5w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 h1:I8MsauTJQXZ8df8qJvEln0kYNc3bSapuaSsEsnFdEFU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3/go.mod h1:lZdb/YAJUSj9OqrCHs2ihjtoO3+xK3G53wTYXFWRGDo= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -443,8 +382,6 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4= github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -465,8 +402,6 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -474,10 +409,7 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/infobloxopen/atlas-app-toolkit v0.24.1-0.20210416193901-4c7518b07e08/go.mod h1:9BTHnpff654rY1J8KxSUOLJ+ZUDn2Vi3mmk26gQDo1M= -github.com/infobloxopen/protoc-gen-gorm v1.0.1 h1:IjvQ02gZSll+CjpWjxkLqrpxnvKAGfs5dXRJEpfZx2s= -github.com/infobloxopen/protoc-gen-gorm v1.0.1/go.mod h1:gTu86stnDQXwcNqLG9WNJfl3IPUIhxmGNqJ8z4826uo= github.com/infobloxopen/protoc-gen-gorm v1.1.0 h1:l6JKEkqMTFbtoGIfQmh/aOy7KfljgX4ql772LtG4kas= github.com/infobloxopen/protoc-gen-gorm v1.1.0/go.mod h1:ohzLmmFMWQztw2RBHunfjKSCjTPUW4JvbgU1Mdazwxg= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= @@ -488,15 +420,9 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU= -github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.11.0 h1:HiHArx4yFbwl91X3qqIHtUFoiIfLNJXCQRsnzkiwwaQ= github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= @@ -514,45 +440,30 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= -github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38= github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= -github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8= +github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w= github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -563,17 +474,13 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -590,10 +497,9 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -621,15 +527,11 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.3.1-0.20200116171513-9eb3fc897d6f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -644,30 +546,24 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= -github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= -github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ= github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -684,7 +580,6 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= @@ -699,73 +594,41 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k= -github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8= github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/ory/dockertest/v3 v3.7.0 h1:Bijzonc69Ont3OU0a3TWKJ1Rzlh3TsDXP1JrTAkSmsM= -github.com/ory/dockertest/v3 v3.7.0/go.mod h1:PvCCgnP7AfBZeVrzwiUTjZx/IUXlGLC1zQlUQrLIlUE= github.com/ory/dockertest/v3 v3.8.1 h1:vU/8d1We4qIad2YM0kOwRVtnyue7ExvacPiw1yDm17g= github.com/ory/dockertest/v3 v3.8.1/go.mod h1:wSRQ3wmkz+uSARYMk7kVJFDBGm8x5gSxIhI7NDc+BAQ= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/philip-bui/grpc-zerolog v1.0.1 h1:EMacvLRUd2O1K0eWod27ZP5CY1iTNkhBDLSN+Q4JEvA= github.com/philip-bui/grpc-zerolog v1.0.1/go.mod h1:qXbiq/2X4ZUMMshsqlWyTHOcw7ns+GZmlqZZN05ZHcQ= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= @@ -774,35 +637,27 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= @@ -813,13 +668,13 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= -github.com/pterm/pterm v0.12.30 h1:ZfXzqtOJVKZ2Uhd+L5o6jmbO44PH3Mee4mxq303nh1Y= github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= github.com/pterm/pterm v0.12.36 h1:Ui5zZj7xA8lXR0CxWXlKGCQMW1cZVUMOS8jEXs6ur/g= github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -827,30 +682,23 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 h1:Ha8xCaq6ln1a+R91Km45Oq6lPXj2Mla6CRJYcuV2h1w= -github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= -github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -865,45 +713,30 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= 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= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.1 h1:izYHOT71f9iZ7iq37Uqjael60/vYC6vMtzedudZ0zEk= github.com/spf13/afero v1.8.1/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.1-0.20201006035406-b97b5ead31f7/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk= -github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -919,25 +752,20 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tailscale/hujson v0.0.0-20211105212140-3a0adc019d83 h1:f7nwzdAHTUUOJjHZuDvLz9CEAlUM228amCRvwzlPvsA= -github.com/tailscale/hujson v0.0.0-20211105212140-3a0adc019d83/go.mod h1:iTDXJsA6A2wNNjurgic2rk+is6uzU4U2NLm4T+edr6M= github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362 h1:xx7EMpWIKUrMMg+QanclF7bj8QTH/XYdQb/eplkmkgw= github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362/go.mod h1:iTDXJsA6A2wNNjurgic2rk+is6uzU4U2NLm4T+edr6M= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e h1:IWllFTiDjjLIf2oeKxpIUmtiDV5sn71VgeQgg6vcE7k= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e/go.mod h1:d7u6HkTYKSv5m6MCKkOQlHwaShTMl3HjqSGW3XtVhXM= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/twitchtv/twirp v7.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= @@ -962,16 +790,9 @@ github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxt github.com/zsais/go-gin-prometheus v0.1.0 h1:bkLv1XCdzqVgQ36ScgRi09MA2UC1t3tAB6nsfErsGO4= github.com/zsais/go-gin-prometheus v0.1.0/go.mod h1:Slirjzuz8uM8Cw0jmPNqbneoqcUtY2GGjn2bEd4NRLY= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1010,27 +831,24 @@ golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaE golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8= -golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2 h1:XdAboW3BNMv9ocSCOk/u1MFioZGzCNkiJZ19v9Oe3Ig= golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1071,13 +889,11 @@ golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1111,7 +927,6 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1121,10 +936,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211205041911-012df41ee64c h1:7SfqwP5fxEtl/P02w5IhKc86ziJ+A25yFrkVgoy2FT8= -golang.org/x/net v0.0.0-20211205041911-012df41ee64c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1139,7 +953,6 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -1163,11 +976,9 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1181,18 +992,15 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1218,6 +1026,7 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1244,6 +1053,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1252,7 +1062,6 @@ golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= @@ -1274,12 +1083,10 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/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= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1334,6 +1141,7 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1353,7 +1161,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1376,7 +1183,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= @@ -1389,7 +1195,6 @@ google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUb google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1402,7 +1207,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1464,8 +1268,6 @@ google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247 h1:ZONpjmFT5e+I/0/xE3XXbG5OIvX2hRYzol04MhKBl2E= -google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= @@ -1474,15 +1276,11 @@ google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336 h1:RK2ysGpQApbI6U7xn+ROT2rrm08lE/t8AcGqG8XI1CY= google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1506,13 +1304,11 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 h1:TLkBREm4nIsEcexnCjgQd5GQWaHcqMzwQV0TX9pq8S0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY= @@ -1540,15 +1336,9 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1556,8 +1346,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1571,42 +1359,29 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/datatypes v1.0.2 h1:ChZ5VfWGB23qEr1kZosidvG9CF9HIczwoxLhBS7Ebs4= -gorm.io/datatypes v1.0.2/go.mod h1:1O1JVE4grFGcQTOGQbIBitiXUP6Sv84/KZU7eWeUv1k= gorm.io/datatypes v1.0.5 h1:3vHCfg4Bz8SDx83zE+ASskF+g/j0kWrcKrY9jFUyAl0= gorm.io/datatypes v1.0.5/go.mod h1:acG/OHGwod+1KrbwPL1t+aavb7jOBOETeyl5M8K5VQs= -gorm.io/driver/mysql v1.1.2 h1:OofcyE2lga734MxwcCW9uB4mWNXMr50uaGRVwQL2B0M= -gorm.io/driver/mysql v1.1.2/go.mod h1:4P/X9vSc3WTrhTLZ259cpFd6xKNYiSSdSZngkSBGIMM= gorm.io/driver/mysql v1.2.2/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo= gorm.io/driver/mysql v1.2.3 h1:cZqzlOfg5Kf1VIdLC1D9hT6Cy9BgxhExLj/2tIgUe7Y= gorm.io/driver/mysql v1.2.3/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo= -gorm.io/driver/postgres v1.1.0/go.mod h1:hXQIwafeRjJvUm+OMxcFWyswJ/vevcpPLlGocwAwuqw= -gorm.io/driver/postgres v1.1.1 h1:tWLmqYCyaoh89fi7DhM6QggujrOnmfo3H98AzgNAAu0= -gorm.io/driver/postgres v1.1.1/go.mod h1:tpe2xN7aCst1NUdYyWQyxPtnHC+Zfp6NEux9PXD1OU0= +gorm.io/driver/mysql v1.3.2 h1:QJryWiqQ91EvZ0jZL48NOpdlPdMjdip1hQ8bTgo4H7I= +gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= gorm.io/driver/postgres v1.2.3 h1:f4t0TmNMy9gh3TU2PX+EppoA6YsgFnyq8Ojtddb42To= gorm.io/driver/postgres v1.2.3/go.mod h1:pJV6RgYQPG47aM1f0QeOzFH9HxQc8JcmAgjRCgS0wjs= -gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw= -gorm.io/driver/sqlite v1.1.5 h1:JU8G59VyKu1x1RMQgjefQnkZjDe9wHc1kARDZPu5dZs= -gorm.io/driver/sqlite v1.1.5/go.mod h1:NpaYMcVKEh6vLJ47VP6T7Weieu4H1Drs3dGD/K6GrGc= -gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4= -gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY= -gorm.io/driver/sqlserver v1.0.9 h1:P7Dm/BKqsrOjyhRSnLXvG2g1W/eJUgxdrdBwgJw3tEg= -gorm.io/driver/sqlserver v1.0.9/go.mod h1:iBdxY2CepkTt9Q1r84RbZA1qCai300Qlp8kQf9qE9II= -gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gorm.io/gorm v1.21.9/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.12/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.14/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.15 h1:gAyaDoPw0lCyrSFWhBlahbUA1U4P5RViC1uIqoB+1Rk= -gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= +gorm.io/driver/postgres v1.3.1 h1:Pyv+gg1Gq1IgsLYytj/S2k7ebII3CzEdpqQkPOdH24g= +gorm.io/driver/postgres v1.3.1/go.mod h1:WwvWOuR9unCLpGWCL6Y3JOeBWvbKi6JLhayiVclSZZU= +gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= +gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= +gorm.io/driver/sqlserver v1.3.1 h1:F5t6ScMzOgy1zukRTIZgLZwKahgt3q1woAILVolKpOI= +gorm.io/driver/sqlserver v1.3.1/go.mod h1:w25Vrx2BG+CJNUu/xKbFhaKlGxT/nzRkhWCCoptX8tQ= gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk= -gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU= gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= +gorm.io/gorm v1.23.1 h1:aj5IlhDzEPsoIyOPtTRVI+SyaN1u6k613sbt4pwbxG0= +gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1616,14 +1391,131 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 h1:acCzuUSQ79tGsM/O50VRFySfMm19IoMKL+sZztZkCxw= inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6/go.mod h1:y3MGhcFMlh0KZPMuXXow8mpjxxAk3yoDNsp4cQz54i8= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60= +modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw= +modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI= +modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag= +modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw= +modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ= +modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c= +modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo= +modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg= +modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I= +modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs= +modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8= +modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE= +modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk= +modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w= +modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE= +modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8= +modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc= +modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU= +modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE= +modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk= +modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI= +modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE= +modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg= +modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74= +modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU= +modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU= +modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc= +modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM= +modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ= +modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84= +modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ= +modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY= +modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= +modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU= +modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko= +modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA= +modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4= +modernc.org/ccgo/v3 v3.14.0/go.mod h1:hBrkiBlUwvr5vV/ZH9YzXIp982jKE8Ek8tR1ytoAL6Q= +modernc.org/ccgo/v3 v3.15.1/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= +modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= +modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8= +modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= +modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg= +modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M= +modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU= +modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE= +modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso= +modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8= +modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8= +modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I= +modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk= +modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY= +modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE= +modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg= +modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM= +modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg= +modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo= +modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8= +modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ= +modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA= +modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM= +modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg= +modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE= +modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM= +modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU= +modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw= +modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M= +modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18= +modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8= +modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= +modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0= +modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI= +modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE= +modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY= +modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ= +modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c= +modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI= +modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ= +modernc.org/libc v1.13.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.13.2/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34= +modernc.org/libc v1.14.3 h1:ruQJ8VDhnWkUR/otUG/Ksw+sWHUw9cPAq6mjDaY/Y7c= +modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ= +modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= +modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14= +modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.14.5 h1:bYrrjwH9Y7QUGk1MbchZDhRfmpGuEAs/D45sVjNbfvs= +modernc.org/sqlite v1.14.5/go.mod h1:YyX5Rx0WbXokitdWl2GJIDy4BrPxBP0PwwhpXOHCDLE= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/tcl v1.10.0/go.mod h1:WzWapmP/7dHVhFoyPpEaNSVTL8xtewhouN/cqSJ5A2s= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.2.21/go.mod h1:uXrObx4pGqXWIMliC5MiKuwAyMrltzwpteOFUP1PWCc= +modernc.org/z v1.3.0/go.mod h1:+mvgLH814oDjtATDdT3rs84JnUIpkvAF5B8AVkNlE2g= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -tailscale.com v1.20.3 h1:C3g2AgmQaOi0YT5dAal9mslugPXMxwj0EXY7YfL2QrA= -tailscale.com v1.20.3/go.mod h1:kjVy3ji2OH5lZhPLIIRacoY3CN4Bo3Yyb2mtoM8nfJ4= tailscale.com v1.20.4 h1:7cl/Q2Sbo2Jb2dX7zA+Exbbl7DT5UGZ4iGhQ2xj23X0= tailscale.com v1.20.4/go.mod h1:kjVy3ji2OH5lZhPLIIRacoY3CN4Bo3Yyb2mtoM8nfJ4= From bfbcea35a03fc7cd80a46a8b5a0c9b1fee5a1e24 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 22 Feb 2022 16:18:25 +0000 Subject: [PATCH 067/204] Remove dependency on CGO This commit changes the SQLite dependency to one that does not depend on CGO. It uses a C-to-Go translated sqlite library that is Pure go. --- .goreleaser.yml | 27 +-- CHANGELOG.md | 4 + Dockerfile | 2 +- Dockerfile.alpine | 2 +- Dockerfile.debug | 2 +- Makefile | 2 +- db.go | 2 +- go.mod | 21 ++- go.sum | 428 +++++++++++++++++----------------------------- 9 files changed, 192 insertions(+), 298 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index d1dec26..bd517d9 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -10,15 +10,12 @@ builds: - id: darwin-amd64 main: ./cmd/headscale/headscale.go mod_timestamp: "{{ .CommitTimestamp }}" + env: + - CGO_ENABLED=0 goos: - darwin goarch: - amd64 - env: - - PKG_CONFIG_SYSROOT_DIR=/sysroot/macos/amd64 - - PKG_CONFIG_PATH=/sysroot/macos/amd64/usr/local/lib/pkgconfig - - CC=o64-clang - - CXX=o64-clang++ flags: - -mod=readonly ldflags: @@ -27,46 +24,40 @@ builds: - id: linux-armhf main: ./cmd/headscale/headscale.go mod_timestamp: "{{ .CommitTimestamp }}" + env: + - CGO_ENABLED=0 goos: - linux goarch: - arm goarm: - "7" - env: - - CC=arm-linux-gnueabihf-gcc - - CXX=arm-linux-gnueabihf-g++ - - CGO_FLAGS=--sysroot=/sysroot/linux/armhf - - CGO_LDFLAGS=--sysroot=/sysroot/linux/armhf - - PKG_CONFIG_SYSROOT_DIR=/sysroot/linux/armhf - - PKG_CONFIG_PATH=/sysroot/linux/armhf/opt/vc/lib/pkgconfig:/sysroot/linux/armhf/usr/lib/arm-linux-gnueabihf/pkgconfig:/sysroot/linux/armhf/usr/lib/pkgconfig:/sysroot/linux/armhf/usr/local/lib/pkgconfig flags: - -mod=readonly ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} - id: linux-amd64 + mod_timestamp: "{{ .CommitTimestamp }}" env: - - CGO_ENABLED=1 + - CGO_ENABLED=0 goos: - linux goarch: - amd64 main: ./cmd/headscale/headscale.go - mod_timestamp: "{{ .CommitTimestamp }}" ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} - id: linux-arm64 + mod_timestamp: "{{ .CommitTimestamp }}" + env: + - CGO_ENABLED=0 goos: - linux goarch: - arm64 - env: - - CGO_ENABLED=1 - - CC=aarch64-linux-gnu-gcc main: ./cmd/headscale/headscale.go - mod_timestamp: "{{ .CommitTimestamp }}" ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c04a17..06a0ec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - Tags should now work correctly and adding a host to Headscale should now reload the rules. - The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features +**Changes**: + +- Remove dependency on CGO (switch from CGO SQLite to pure Go) [#346](https://github.com/juanfont/headscale/pull/346) + **0.13.0 (2022-02-18):** **Features**: diff --git a/Dockerfile b/Dockerfile index 6e57775..86f5bd4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ RUN go mod download COPY . . -RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale +RUN GGO_ENABLED=0 GOOS=linux go install -a ./cmd/headscale RUN strip /go/bin/headscale RUN test -e /go/bin/headscale diff --git a/Dockerfile.alpine b/Dockerfile.alpine index b07e190..af88434 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -9,7 +9,7 @@ RUN go mod download COPY . . -RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale +RUN GGO_ENABLED=0 GOOS=linux go install -a ./cmd/headscale RUN strip /go/bin/headscale RUN test -e /go/bin/headscale diff --git a/Dockerfile.debug b/Dockerfile.debug index 3d2675f..38385ce 100644 --- a/Dockerfile.debug +++ b/Dockerfile.debug @@ -8,7 +8,7 @@ RUN go mod download COPY . . -RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale +RUN GGO_ENABLED=0 GOOS=linux go install -a ./cmd/headscale RUN test -e /go/bin/headscale # Debug image diff --git a/Makefile b/Makefile index 69935bc..5214509 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ PROTO_SOURCES = $(call rwildcard,,*.proto) build: - go build -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go + GGO_ENABLED=0 go build -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go dev: lint test build diff --git a/db.go b/db.go index 1b53dc8..7aadd20 100644 --- a/db.go +++ b/db.go @@ -3,8 +3,8 @@ package headscale import ( "errors" + "github.com/glebarez/sqlite" "gorm.io/driver/postgres" - "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) diff --git a/go.mod b/go.mod index bbba464..8b721fa 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/efekarakus/termcolor v1.0.1 github.com/fatih/set v0.2.1 github.com/gin-gonic/gin v1.7.7 + github.com/glebarez/sqlite v1.3.5 github.com/gofrs/uuid v4.2.0+incompatible github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 @@ -19,14 +20,13 @@ require ( github.com/prometheus/client_golang v1.12.1 github.com/pterm/pterm v0.12.36 github.com/rs/zerolog v1.26.1 - github.com/soheilhy/cmux v0.1.5 github.com/spf13/cobra v1.3.0 github.com/spf13/viper v1.10.1 github.com/stretchr/testify v1.7.0 github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362 github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e github.com/zsais/go-gin-prometheus v0.1.0 - golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2 + golang.org/x/crypto v0.0.0-20220214200702-86341886e292 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336 @@ -36,9 +36,8 @@ require ( gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/yaml.v2 v2.4.0 gorm.io/datatypes v1.0.5 - gorm.io/driver/postgres v1.2.3 - gorm.io/driver/sqlite v1.2.6 - gorm.io/gorm v1.22.5 + gorm.io/driver/postgres v1.3.1 + gorm.io/gorm v1.23.1 inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 tailscale.com v1.20.4 ) @@ -58,8 +57,8 @@ require ( github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/ghodss/yaml v1.0.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/glebarez/go-sqlite v1.14.7 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.10.0 // indirect @@ -70,6 +69,7 @@ require ( github.com/google/go-github v17.0.0+incompatible // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gookit/color v1.5.0 // indirect github.com/hashicorp/go-version v1.4.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -112,6 +112,7 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/sirupsen/logrus v1.8.1 // indirect @@ -136,6 +137,12 @@ require ( gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - gorm.io/driver/mysql v1.2.3 // indirect + gorm.io/driver/mysql v1.3.2 // indirect + gorm.io/driver/sqlite v1.3.1 // indirect + gorm.io/driver/sqlserver v1.3.1 // indirect + modernc.org/libc v1.14.3 // indirect + modernc.org/mathutil v1.4.1 // indirect + modernc.org/memory v1.0.5 // indirect + modernc.org/sqlite v1.14.5 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 2814589..20eec3f 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -40,7 +39,6 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= @@ -56,6 +54,9 @@ contrib.go.opencensus.io/exporter/ocagent v0.7.0/go.mod h1:IshRmMJBhDfFj5Y67nVhM dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AlecAivazis/survey/v2 v2.3.2 h1:TqTB+aDDCLYhf9/bD2TwSO8u8jDSmMUd2SUVO4gCnU8= github.com/AlecAivazis/survey/v2 v2.3.2/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= @@ -63,9 +64,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= -github.com/MarvinJWendt/testza v0.2.1 h1:eitywm1lzygA2KCyn55jFVdOaXj5I9LeOsLNeifd2Kw= github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= @@ -74,7 +73,6 @@ github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzX github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= @@ -83,10 +81,6 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -94,20 +88,14 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -116,18 +104,11 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bufbuild/buf v0.37.0/go.mod h1:lQ1m2HkIaGOFba6w/aC3KYBHhKEOESP3gaAEpS3dAFM= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -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.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -141,7 +122,6 @@ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -155,13 +135,9 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= github.com/containerd/continuity v0.2.2 h1:QSqfxcn8c+12slxwu00AtzXrsami0MJb/MQs9lOLHLA= github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -171,11 +147,9 @@ github.com/coreos/go-oidc/v3 v3.1.0 h1:6avEvcdvTa1qYsOZ6I5PRkSYHzpTNWgKYmaJfaYbr github.com/coreos/go-oidc/v3 v3.1.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -190,38 +164,27 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8= -github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA= +github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.1-0.20200107013213-dc14462fd587+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.8+incompatible h1:/zO/6y9IOpcehE49yMRTV9ea0nBpb8OeqSskXLNfH1E= -github.com/docker/cli v20.10.8+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/cli v20.10.11+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v20.10.12+incompatible h1:lZlz0uzG+GH+c0plStMUdF/qk3ppmgnswpR5EbqzVGA= github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM= -github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U= github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/efekarakus/termcolor v1.0.1 h1:YAKFO3bnLrqZGTWyNLcYoSIAQFKVOmbqmDnwsU/znzg= github.com/efekarakus/termcolor v1.0.1/go.mod h1:AitrZNrE4nPO538fRsqf+p0WgLdAsGN5pUNrHEPsEMM= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -240,27 +203,24 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM= -github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= +github.com/glebarez/go-sqlite v1.14.7 h1:eXrKp59O5eWBfxv2Xfq5d7uex4+clKrOtWfMzzGSkoM= +github.com/glebarez/go-sqlite v1.14.7/go.mod h1:TKAw5tjyB/ocvVht7Xv4772qRAun5CG/xLCEbkDwNUc= +github.com/glebarez/sqlite v1.3.5 h1:R9op5nxb9Z10t4VXQSdAVyqRalLhWdLrlaT/iuvOGHI= +github.com/glebarez/sqlite v1.3.5/go.mod h1:ZffEtp/afVhV+jvIzQi8wlYEIkuGAYshr9OPKM/NmQc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -274,11 +234,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A= -github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -286,24 +243,20 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= -github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -336,7 +289,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -351,7 +303,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= @@ -381,49 +332,37 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.3.0/go.mod h1:d2gYTOTUQklu06xp0AJYYmRdTVU1VKrqhkYfYag2L08= github.com/grpc-ecosystem/grpc-gateway/v2 v2.4.0/go.mod h1:IOyTYjcIO0rkmnGBfJTL0NJ11exy/Tc2QEuv7hCXp24= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0 h1:rgxjzoDmDXw5q8HONgyHhBas4to0/XWRo/gPpJhsUNQ= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0/go.mod h1:qrJPVzv9YlhsrxJc3P/Q85nr0w1lIRikTl4JlhdDH5w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 h1:I8MsauTJQXZ8df8qJvEln0kYNc3bSapuaSsEsnFdEFU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3/go.mod h1:lZdb/YAJUSj9OqrCHs2ihjtoO3+xK3G53wTYXFWRGDo= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -443,8 +382,6 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4= github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -465,8 +402,6 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -474,10 +409,7 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/infobloxopen/atlas-app-toolkit v0.24.1-0.20210416193901-4c7518b07e08/go.mod h1:9BTHnpff654rY1J8KxSUOLJ+ZUDn2Vi3mmk26gQDo1M= -github.com/infobloxopen/protoc-gen-gorm v1.0.1 h1:IjvQ02gZSll+CjpWjxkLqrpxnvKAGfs5dXRJEpfZx2s= -github.com/infobloxopen/protoc-gen-gorm v1.0.1/go.mod h1:gTu86stnDQXwcNqLG9WNJfl3IPUIhxmGNqJ8z4826uo= github.com/infobloxopen/protoc-gen-gorm v1.1.0 h1:l6JKEkqMTFbtoGIfQmh/aOy7KfljgX4ql772LtG4kas= github.com/infobloxopen/protoc-gen-gorm v1.1.0/go.mod h1:ohzLmmFMWQztw2RBHunfjKSCjTPUW4JvbgU1Mdazwxg= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= @@ -488,15 +420,9 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU= -github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.11.0 h1:HiHArx4yFbwl91X3qqIHtUFoiIfLNJXCQRsnzkiwwaQ= github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= @@ -514,45 +440,30 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= -github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38= github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= -github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8= +github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w= github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -563,17 +474,13 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -590,10 +497,9 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -621,15 +527,11 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.3.1-0.20200116171513-9eb3fc897d6f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -644,30 +546,24 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= -github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= -github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ= github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -684,7 +580,6 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= @@ -699,73 +594,41 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k= -github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8= github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/ory/dockertest/v3 v3.7.0 h1:Bijzonc69Ont3OU0a3TWKJ1Rzlh3TsDXP1JrTAkSmsM= -github.com/ory/dockertest/v3 v3.7.0/go.mod h1:PvCCgnP7AfBZeVrzwiUTjZx/IUXlGLC1zQlUQrLIlUE= github.com/ory/dockertest/v3 v3.8.1 h1:vU/8d1We4qIad2YM0kOwRVtnyue7ExvacPiw1yDm17g= github.com/ory/dockertest/v3 v3.8.1/go.mod h1:wSRQ3wmkz+uSARYMk7kVJFDBGm8x5gSxIhI7NDc+BAQ= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/philip-bui/grpc-zerolog v1.0.1 h1:EMacvLRUd2O1K0eWod27ZP5CY1iTNkhBDLSN+Q4JEvA= github.com/philip-bui/grpc-zerolog v1.0.1/go.mod h1:qXbiq/2X4ZUMMshsqlWyTHOcw7ns+GZmlqZZN05ZHcQ= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= @@ -774,35 +637,27 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= @@ -813,13 +668,13 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= -github.com/pterm/pterm v0.12.30 h1:ZfXzqtOJVKZ2Uhd+L5o6jmbO44PH3Mee4mxq303nh1Y= github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= github.com/pterm/pterm v0.12.36 h1:Ui5zZj7xA8lXR0CxWXlKGCQMW1cZVUMOS8jEXs6ur/g= github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -827,30 +682,23 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 h1:Ha8xCaq6ln1a+R91Km45Oq6lPXj2Mla6CRJYcuV2h1w= -github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= -github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -865,45 +713,30 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= 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= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.1 h1:izYHOT71f9iZ7iq37Uqjael60/vYC6vMtzedudZ0zEk= github.com/spf13/afero v1.8.1/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.1-0.20201006035406-b97b5ead31f7/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk= -github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -919,25 +752,20 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tailscale/hujson v0.0.0-20211105212140-3a0adc019d83 h1:f7nwzdAHTUUOJjHZuDvLz9CEAlUM228amCRvwzlPvsA= -github.com/tailscale/hujson v0.0.0-20211105212140-3a0adc019d83/go.mod h1:iTDXJsA6A2wNNjurgic2rk+is6uzU4U2NLm4T+edr6M= github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362 h1:xx7EMpWIKUrMMg+QanclF7bj8QTH/XYdQb/eplkmkgw= github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362/go.mod h1:iTDXJsA6A2wNNjurgic2rk+is6uzU4U2NLm4T+edr6M= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e h1:IWllFTiDjjLIf2oeKxpIUmtiDV5sn71VgeQgg6vcE7k= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e/go.mod h1:d7u6HkTYKSv5m6MCKkOQlHwaShTMl3HjqSGW3XtVhXM= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/twitchtv/twirp v7.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= @@ -962,16 +790,9 @@ github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxt github.com/zsais/go-gin-prometheus v0.1.0 h1:bkLv1XCdzqVgQ36ScgRi09MA2UC1t3tAB6nsfErsGO4= github.com/zsais/go-gin-prometheus v0.1.0/go.mod h1:Slirjzuz8uM8Cw0jmPNqbneoqcUtY2GGjn2bEd4NRLY= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1010,27 +831,24 @@ golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaE golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8= -golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2 h1:XdAboW3BNMv9ocSCOk/u1MFioZGzCNkiJZ19v9Oe3Ig= golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1071,13 +889,11 @@ golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1111,7 +927,6 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1121,10 +936,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211205041911-012df41ee64c h1:7SfqwP5fxEtl/P02w5IhKc86ziJ+A25yFrkVgoy2FT8= -golang.org/x/net v0.0.0-20211205041911-012df41ee64c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1139,7 +953,6 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -1163,11 +976,9 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1181,18 +992,15 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1218,6 +1026,7 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1244,6 +1053,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1252,7 +1062,6 @@ golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= @@ -1274,12 +1083,10 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/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= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1334,6 +1141,7 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1353,7 +1161,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1376,7 +1183,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= @@ -1389,7 +1195,6 @@ google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUb google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1402,7 +1207,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1464,8 +1268,6 @@ google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247 h1:ZONpjmFT5e+I/0/xE3XXbG5OIvX2hRYzol04MhKBl2E= -google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= @@ -1474,15 +1276,11 @@ google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336 h1:RK2ysGpQApbI6U7xn+ROT2rrm08lE/t8AcGqG8XI1CY= google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1506,13 +1304,11 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 h1:TLkBREm4nIsEcexnCjgQd5GQWaHcqMzwQV0TX9pq8S0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY= @@ -1540,15 +1336,9 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1556,8 +1346,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1571,42 +1359,29 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/datatypes v1.0.2 h1:ChZ5VfWGB23qEr1kZosidvG9CF9HIczwoxLhBS7Ebs4= -gorm.io/datatypes v1.0.2/go.mod h1:1O1JVE4grFGcQTOGQbIBitiXUP6Sv84/KZU7eWeUv1k= gorm.io/datatypes v1.0.5 h1:3vHCfg4Bz8SDx83zE+ASskF+g/j0kWrcKrY9jFUyAl0= gorm.io/datatypes v1.0.5/go.mod h1:acG/OHGwod+1KrbwPL1t+aavb7jOBOETeyl5M8K5VQs= -gorm.io/driver/mysql v1.1.2 h1:OofcyE2lga734MxwcCW9uB4mWNXMr50uaGRVwQL2B0M= -gorm.io/driver/mysql v1.1.2/go.mod h1:4P/X9vSc3WTrhTLZ259cpFd6xKNYiSSdSZngkSBGIMM= gorm.io/driver/mysql v1.2.2/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo= gorm.io/driver/mysql v1.2.3 h1:cZqzlOfg5Kf1VIdLC1D9hT6Cy9BgxhExLj/2tIgUe7Y= gorm.io/driver/mysql v1.2.3/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo= -gorm.io/driver/postgres v1.1.0/go.mod h1:hXQIwafeRjJvUm+OMxcFWyswJ/vevcpPLlGocwAwuqw= -gorm.io/driver/postgres v1.1.1 h1:tWLmqYCyaoh89fi7DhM6QggujrOnmfo3H98AzgNAAu0= -gorm.io/driver/postgres v1.1.1/go.mod h1:tpe2xN7aCst1NUdYyWQyxPtnHC+Zfp6NEux9PXD1OU0= +gorm.io/driver/mysql v1.3.2 h1:QJryWiqQ91EvZ0jZL48NOpdlPdMjdip1hQ8bTgo4H7I= +gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= gorm.io/driver/postgres v1.2.3 h1:f4t0TmNMy9gh3TU2PX+EppoA6YsgFnyq8Ojtddb42To= gorm.io/driver/postgres v1.2.3/go.mod h1:pJV6RgYQPG47aM1f0QeOzFH9HxQc8JcmAgjRCgS0wjs= -gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw= -gorm.io/driver/sqlite v1.1.5 h1:JU8G59VyKu1x1RMQgjefQnkZjDe9wHc1kARDZPu5dZs= -gorm.io/driver/sqlite v1.1.5/go.mod h1:NpaYMcVKEh6vLJ47VP6T7Weieu4H1Drs3dGD/K6GrGc= -gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4= -gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY= -gorm.io/driver/sqlserver v1.0.9 h1:P7Dm/BKqsrOjyhRSnLXvG2g1W/eJUgxdrdBwgJw3tEg= -gorm.io/driver/sqlserver v1.0.9/go.mod h1:iBdxY2CepkTt9Q1r84RbZA1qCai300Qlp8kQf9qE9II= -gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gorm.io/gorm v1.21.9/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.12/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.14/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.15 h1:gAyaDoPw0lCyrSFWhBlahbUA1U4P5RViC1uIqoB+1Rk= -gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= +gorm.io/driver/postgres v1.3.1 h1:Pyv+gg1Gq1IgsLYytj/S2k7ebII3CzEdpqQkPOdH24g= +gorm.io/driver/postgres v1.3.1/go.mod h1:WwvWOuR9unCLpGWCL6Y3JOeBWvbKi6JLhayiVclSZZU= +gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= +gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= +gorm.io/driver/sqlserver v1.3.1 h1:F5t6ScMzOgy1zukRTIZgLZwKahgt3q1woAILVolKpOI= +gorm.io/driver/sqlserver v1.3.1/go.mod h1:w25Vrx2BG+CJNUu/xKbFhaKlGxT/nzRkhWCCoptX8tQ= gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk= -gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU= gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= +gorm.io/gorm v1.23.1 h1:aj5IlhDzEPsoIyOPtTRVI+SyaN1u6k613sbt4pwbxG0= +gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1616,14 +1391,131 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 h1:acCzuUSQ79tGsM/O50VRFySfMm19IoMKL+sZztZkCxw= inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6/go.mod h1:y3MGhcFMlh0KZPMuXXow8mpjxxAk3yoDNsp4cQz54i8= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60= +modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw= +modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI= +modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag= +modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw= +modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ= +modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c= +modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo= +modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg= +modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I= +modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs= +modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8= +modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE= +modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk= +modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w= +modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE= +modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8= +modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc= +modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU= +modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE= +modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk= +modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI= +modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE= +modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg= +modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74= +modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU= +modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU= +modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc= +modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM= +modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ= +modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84= +modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ= +modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY= +modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= +modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU= +modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko= +modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA= +modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4= +modernc.org/ccgo/v3 v3.14.0/go.mod h1:hBrkiBlUwvr5vV/ZH9YzXIp982jKE8Ek8tR1ytoAL6Q= +modernc.org/ccgo/v3 v3.15.1/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= +modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= +modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8= +modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= +modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg= +modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M= +modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU= +modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE= +modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso= +modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8= +modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8= +modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I= +modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk= +modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY= +modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE= +modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg= +modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM= +modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg= +modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo= +modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8= +modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ= +modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA= +modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM= +modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg= +modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE= +modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM= +modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU= +modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw= +modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M= +modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18= +modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8= +modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= +modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0= +modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI= +modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE= +modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY= +modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ= +modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c= +modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI= +modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ= +modernc.org/libc v1.13.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.13.2/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34= +modernc.org/libc v1.14.3 h1:ruQJ8VDhnWkUR/otUG/Ksw+sWHUw9cPAq6mjDaY/Y7c= +modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ= +modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= +modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14= +modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.14.5 h1:bYrrjwH9Y7QUGk1MbchZDhRfmpGuEAs/D45sVjNbfvs= +modernc.org/sqlite v1.14.5/go.mod h1:YyX5Rx0WbXokitdWl2GJIDy4BrPxBP0PwwhpXOHCDLE= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/tcl v1.10.0/go.mod h1:WzWapmP/7dHVhFoyPpEaNSVTL8xtewhouN/cqSJ5A2s= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.2.21/go.mod h1:uXrObx4pGqXWIMliC5MiKuwAyMrltzwpteOFUP1PWCc= +modernc.org/z v1.3.0/go.mod h1:+mvgLH814oDjtATDdT3rs84JnUIpkvAF5B8AVkNlE2g= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -tailscale.com v1.20.3 h1:C3g2AgmQaOi0YT5dAal9mslugPXMxwj0EXY7YfL2QrA= -tailscale.com v1.20.3/go.mod h1:kjVy3ji2OH5lZhPLIIRacoY3CN4Bo3Yyb2mtoM8nfJ4= tailscale.com v1.20.4 h1:7cl/Q2Sbo2Jb2dX7zA+Exbbl7DT5UGZ4iGhQ2xj23X0= tailscale.com v1.20.4/go.mod h1:kjVy3ji2OH5lZhPLIIRacoY3CN4Bo3Yyb2mtoM8nfJ4= From 92ffac625ec7b32d2a82f89146497df67def1a47 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 22 Feb 2022 12:45:50 +0100 Subject: [PATCH 068/204] feat(namespace): add normalization function for namespace --- dns.go | 6 +- machine.go | 6 +- namespaces.go | 57 ++++++++++++++ namespaces_test.go | 61 +++++++++++++++ oidc_test.go | 180 --------------------------------------------- 5 files changed, 120 insertions(+), 190 deletions(-) delete mode 100644 oidc_test.go diff --git a/dns.go b/dns.go index 45e0fae..9a91cff 100644 --- a/dns.go +++ b/dns.go @@ -165,11 +165,7 @@ func getMapResponseDNSConfig( dnsConfig.Domains, fmt.Sprintf( "%s.%s", - strings.ReplaceAll( - machine.Namespace.Name, - "@", - ".", - ), // Replace @ with . for valid domain for machine + machine.Namespace.Name, baseDomain, ), ) diff --git a/machine.go b/machine.go index ee48342..25edd1d 100644 --- a/machine.go +++ b/machine.go @@ -724,11 +724,7 @@ func (machine Machine) toNode( hostname = fmt.Sprintf( "%s.%s.%s", machine.Name, - strings.ReplaceAll( - machine.Namespace.Name, - "@", - ".", - ), // Replace @ with . for valid domain for machine + machine.Namespace.Name, baseDomain, ) } else { diff --git a/namespaces.go b/namespaces.go index bdd440c..8160b03 100644 --- a/namespaces.go +++ b/namespaces.go @@ -2,7 +2,10 @@ package headscale import ( "errors" + "fmt" + "regexp" "strconv" + "strings" "time" v1 "github.com/juanfont/headscale/gen/go/headscale/v1" @@ -16,8 +19,11 @@ const ( errNamespaceExists = Error("Namespace already exists") errNamespaceNotFound = Error("Namespace not found") errNamespaceNotEmptyOfNodes = Error("Namespace not empty: node(s) found") + errInvalidNamespaceName = Error("Invalid namespace name") ) +var normalizeNamespaceRegex = regexp.MustCompile("[^a-z0-9-.]+") + // Namespace is the way Headscale implements the concept of users in Tailscale // // At the end of the day, users in Tailscale are some kind of 'bubbles' or namespaces @@ -30,7 +36,12 @@ type Namespace struct { // CreateNamespace creates a new Namespace. Returns error if could not be created // or another namespace already exists. func (h *Headscale) CreateNamespace(name string) (*Namespace, error) { + var err error namespace := Namespace{} + name, err = NormalizeNamespaceName(name) + if err != nil { + return nil, err + } if err := h.db.Where("name = ?", name).First(&namespace).Error; err == nil { return nil, errNamespaceExists } @@ -50,6 +61,10 @@ func (h *Headscale) CreateNamespace(name string) (*Namespace, error) { // DestroyNamespace destroys a Namespace. Returns error if the Namespace does // not exist or if there are machines associated with it. func (h *Headscale) DestroyNamespace(name string) error { + name, err := NormalizeNamespaceName(name) + if err != nil { + return err + } namespace, err := h.GetNamespace(name) if err != nil { return errNamespaceNotFound @@ -84,10 +99,15 @@ func (h *Headscale) DestroyNamespace(name string) error { // RenameNamespace renames a Namespace. Returns error if the Namespace does // not exist or if another Namespace exists with the new name. func (h *Headscale) RenameNamespace(oldName, newName string) error { + var err error oldNamespace, err := h.GetNamespace(oldName) if err != nil { return err } + newName, err = NormalizeNamespaceName(newName) + if err != nil { + return err + } _, err = h.GetNamespace(newName) if err == nil { return errNamespaceExists @@ -108,6 +128,10 @@ func (h *Headscale) RenameNamespace(oldName, newName string) error { // GetNamespace fetches a namespace by name. func (h *Headscale) GetNamespace(name string) (*Namespace, error) { namespace := Namespace{} + name, err := NormalizeNamespaceName(name) + if err != nil { + return nil, err + } if result := h.db.First(&namespace, "name = ?", name); errors.Is( result.Error, gorm.ErrRecordNotFound, @@ -130,6 +154,10 @@ func (h *Headscale) ListNamespaces() ([]Namespace, error) { // ListMachinesInNamespace gets all the nodes in a given namespace. func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { + name, err := NormalizeNamespaceName(name) + if err != nil { + return nil, err + } namespace, err := h.GetNamespace(name) if err != nil { return nil, err @@ -145,6 +173,10 @@ func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { // ListSharedMachinesInNamespace returns all the machines that are shared to the specified namespace. func (h *Headscale) ListSharedMachinesInNamespace(name string) ([]Machine, error) { + name, err := NormalizeNamespaceName(name) + if err != nil { + return nil, err + } namespace, err := h.GetNamespace(name) if err != nil { return nil, err @@ -170,6 +202,10 @@ func (h *Headscale) ListSharedMachinesInNamespace(name string) ([]Machine, error // SetMachineNamespace assigns a Machine to a namespace. func (h *Headscale) SetMachineNamespace(machine *Machine, namespaceName string) error { + namespaceName, err := NormalizeNamespaceName(namespaceName) + if err != nil { + return err + } namespace, err := h.GetNamespace(namespaceName) if err != nil { return err @@ -233,3 +269,24 @@ func (n *Namespace) toProto() *v1.Namespace { CreatedAt: timestamppb.New(n.CreatedAt), } } + +// NormalizeNamespaceName will replace forbidden chars in namespace +// it can also return an error if the namespace doesn't respect RFC 952 and 1123 +func NormalizeNamespaceName(name string) (string, error) { + name = strings.ToLower(name) + name = strings.ReplaceAll(name, "@", ".") + name = strings.ReplaceAll(name, "'", "") + name = normalizeNamespaceRegex.ReplaceAllString(name, "-") + + for _, elt := range strings.Split(name, ".") { + if len(elt) > 63 { + return "", fmt.Errorf( + "label %v is more than 63 chars: %w", + elt, + errInvalidNamespaceName, + ) + } + } + + return name, nil +} diff --git a/namespaces_test.go b/namespaces_test.go index d07deb9..cf2b323 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -1,6 +1,8 @@ package headscale import ( + "testing" + "github.com/rs/zerolog/log" "gopkg.in/check.v1" "gorm.io/gorm" @@ -239,3 +241,62 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { } c.Assert(found, check.Equals, true) } + +func TestNormalizeNamespaceName(t *testing.T) { + type args struct { + name string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "normalize simple name", + args: args{name: "normalize-simple.name"}, + want: "normalize-simple.name", + wantErr: false, + }, + { + name: "normalize an email", + args: args{name: "foo.bar@example.com"}, + want: "foo.bar.example.com", + wantErr: false, + }, + { + name: "normalize complex email", + args: args{name: "foo.bar+complex-email@example.com"}, + want: "foo.bar-complex-email.example.com", + wantErr: false, + }, + { + name: "namespace name with space", + args: args{name: "name space"}, + want: "name-space", + wantErr: false, + }, + { + name: "namespace with quote", + args: args{name: "Jamie's iPhone 5"}, + want: "jamies-iphone-5", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NormalizeNamespaceName(tt.args.name) + if (err != nil) != tt.wantErr { + t.Errorf( + "NormalizeNamespaceName() error = %v, wantErr %v", + err, + tt.wantErr, + ) + return + } + if got != tt.want { + t.Errorf("NormalizeNamespaceName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/oidc_test.go b/oidc_test.go deleted file mode 100644 index d50027a..0000000 --- a/oidc_test.go +++ /dev/null @@ -1,180 +0,0 @@ -package headscale - -import ( - "sync" - "testing" - - "github.com/coreos/go-oidc/v3/oidc" - "github.com/patrickmn/go-cache" - "golang.org/x/oauth2" - "gorm.io/gorm" - "tailscale.com/tailcfg" - "tailscale.com/types/key" -) - -func TestHeadscale_getNamespaceFromEmail(t *testing.T) { - type fields struct { - cfg Config - db *gorm.DB - dbString string - dbType string - dbDebug bool - privateKey *key.MachinePrivate - aclPolicy *ACLPolicy - aclRules []tailcfg.FilterRule - lastStateChange sync.Map - oidcProvider *oidc.Provider - oauth2Config *oauth2.Config - oidcStateCache *cache.Cache - } - type args struct { - email string - } - tests := []struct { - name string - fields fields - args args - want string - want1 bool - }{ - { - name: "match all", - fields: fields{ - cfg: Config{ - OIDC: OIDCConfig{ - MatchMap: map[string]string{ - ".*": "space", - }, - }, - }, - }, - args: args{ - email: "test@example.no", - }, - want: "space", - want1: true, - }, - { - name: "match user", - fields: fields{ - cfg: Config{ - OIDC: OIDCConfig{ - MatchMap: map[string]string{ - "specific@user\\.no": "user-namespace", - }, - }, - }, - }, - args: args{ - email: "specific@user.no", - }, - want: "user-namespace", - want1: true, - }, - { - name: "match domain", - fields: fields{ - cfg: Config{ - OIDC: OIDCConfig{ - MatchMap: map[string]string{ - ".*@example\\.no": "example", - }, - }, - }, - }, - args: args{ - email: "test@example.no", - }, - want: "example", - want1: true, - }, - { - name: "multi match domain", - fields: fields{ - cfg: Config{ - OIDC: OIDCConfig{ - MatchMap: map[string]string{ - ".*@example\\.no": "exammple", - ".*@gmail\\.com": "gmail", - }, - }, - }, - }, - args: args{ - email: "someuser@gmail.com", - }, - want: "gmail", - want1: true, - }, - { - name: "no match domain", - fields: fields{ - cfg: Config{ - OIDC: OIDCConfig{ - MatchMap: map[string]string{ - ".*@dontknow.no": "never", - }, - }, - }, - }, - args: args{ - email: "test@wedontknow.no", - }, - want: "", - want1: false, - }, - { - name: "multi no match domain", - fields: fields{ - cfg: Config{ - OIDC: OIDCConfig{ - MatchMap: map[string]string{ - ".*@dontknow.no": "never", - ".*@wedontknow.no": "other", - ".*\\.no": "stuffy", - }, - }, - }, - }, - args: args{ - email: "tasy@nonofthem.com", - }, - want: "", - want1: false, - }, - } - //nolint - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - app := &Headscale{ - cfg: test.fields.cfg, - db: test.fields.db, - dbString: test.fields.dbString, - dbType: test.fields.dbType, - dbDebug: test.fields.dbDebug, - privateKey: test.fields.privateKey, - aclPolicy: test.fields.aclPolicy, - aclRules: test.fields.aclRules, - lastStateChange: test.fields.lastStateChange, - oidcProvider: test.fields.oidcProvider, - oauth2Config: test.fields.oauth2Config, - oidcStateCache: test.fields.oidcStateCache, - } - got, got1 := app.getNamespaceFromEmail(test.args.email) - if got != test.want { - t.Errorf( - "Headscale.getNamespaceFromEmail() got = %v, want %v", - got, - test.want, - ) - } - if got1 != test.want1 { - t.Errorf( - "Headscale.getNamespaceFromEmail() got1 = %v, want %v", - got1, - test.want1, - ) - } - }) - } -} From 0191ea93ffd83e367530ca8c3b4be78dc6f05dbc Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 22 Feb 2022 12:46:45 +0100 Subject: [PATCH 069/204] feat(oidc): bind email to namespace --- oidc.go | 178 +++++++++++++++++++++++++------------------------------- 1 file changed, 79 insertions(+), 99 deletions(-) diff --git a/oidc.go b/oidc.go index a47863f..495832a 100644 --- a/oidc.go +++ b/oidc.go @@ -9,7 +9,6 @@ import ( "fmt" "html/template" "net/http" - "regexp" "strings" "time" @@ -282,109 +281,90 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { now := time.Now().UTC() - if namespaceName, ok := h.getNamespaceFromEmail(claims.Email); ok { - // register the machine if it's new - if !machine.Registered { - log.Debug().Msg("Registering new machine after successful callback") - - namespace, err := h.GetNamespace(namespaceName) - if errors.Is(err, gorm.ErrRecordNotFound) { - namespace, err = h.CreateNamespace(namespaceName) - - if err != nil { - log.Error(). - Err(err). - Caller(). - Msgf("could not create new namespace '%s'", namespaceName) - ctx.String( - http.StatusInternalServerError, - "could not create new namespace", - ) - - return - } - } else if err != nil { - log.Error(). - Caller(). - Err(err). - Str("namespace", namespaceName). - Msg("could not find or create namespace") - ctx.String( - http.StatusInternalServerError, - "could not find or create namespace", - ) - - return - } - - ips, err := h.getAvailableIPs() - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("could not get an IP from the pool") - ctx.String( - http.StatusInternalServerError, - "could not get an IP from the pool", - ) - - return - } - - machine.IPAddresses = ips - machine.NamespaceID = namespace.ID - machine.Registered = true - machine.RegisterMethod = RegisterMethodOIDC - machine.LastSuccessfulUpdate = &now - machine.Expiry = &requestedTime - h.db.Save(&machine) - } - - var content bytes.Buffer - if err := oidcCallbackTemplate.Execute(&content, oidcCallbackTemplateConfig{ - User: claims.Email, - Verb: "Authenticated", - }); err != nil { - log.Error(). - Str("func", "OIDCCallback"). - Str("type", "authenticate"). - Err(err). - Msg("Could not render OIDC callback template") - ctx.Data( - http.StatusInternalServerError, - "text/html; charset=utf-8", - []byte("Could not render OIDC callback template"), - ) - } - - ctx.Data(http.StatusOK, "text/html; charset=utf-8", content.Bytes()) - + namespaceName, err := NormalizeNamespaceName(claims.Email) + if err != nil { + log.Error().Err(err).Caller().Msgf("couldn't normalize email") + ctx.String( + http.StatusInternalServerError, + "couldn't normalize email", + ) return } + // register the machine if it's new + if !machine.Registered { + log.Debug().Msg("Registering new machine after successful callback") - log.Error(). - Caller(). - Str("email", claims.Email). - Str("username", claims.Username). - Str("machine", machine.Name). - Msg("Email could not be mapped to a namespace") - ctx.String( - http.StatusBadRequest, - "email from claim could not be mapped to a namespace", - ) -} + namespace, err := h.GetNamespace(namespaceName) + if errors.Is(err, gorm.ErrRecordNotFound) { + namespace, err = h.CreateNamespace(namespaceName) -// getNamespaceFromEmail passes the users email through a list of "matchers" -// and iterates through them until it matches and returns a namespace. -// If no match is found, an empty string will be returned. -// TODO(kradalby): golang Maps key order is not stable, so this list is _not_ deterministic. Find a way to make the list of keys stable, preferably in the order presented in a users configuration. -func (h *Headscale) getNamespaceFromEmail(email string) (string, bool) { - for match, namespace := range h.cfg.OIDC.MatchMap { - regex := regexp.MustCompile(match) - if regex.MatchString(email) { - return namespace, true + if err != nil { + log.Error(). + Err(err). + Caller(). + Msgf("could not create new namespace '%s'", namespaceName) + ctx.String( + http.StatusInternalServerError, + "could not create new namespace", + ) + + return + } + } else if err != nil { + log.Error(). + Caller(). + Err(err). + Str("namespace", namespaceName). + Msg("could not find or create namespace") + ctx.String( + http.StatusInternalServerError, + "could not find or create namespace", + ) + + return } + + ips, err := h.getAvailableIPs() + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("could not get an IP from the pool") + ctx.String( + http.StatusInternalServerError, + "could not get an IP from the pool", + ) + + return + } + + machine.IPAddresses = ips + machine.NamespaceID = namespace.ID + machine.Registered = true + machine.RegisterMethod = RegisterMethodOIDC + machine.LastSuccessfulUpdate = &now + machine.Expiry = &requestedTime + h.db.Save(&machine) } - return "", false + var content bytes.Buffer + if err := oidcCallbackTemplate.Execute(&content, oidcCallbackTemplateConfig{ + User: claims.Email, + Verb: "Authenticated", + }); err != nil { + log.Error(). + Str("func", "OIDCCallback"). + Str("type", "authenticate"). + Err(err). + Msg("Could not render OIDC callback template") + ctx.Data( + http.StatusInternalServerError, + "text/html; charset=utf-8", + []byte("Could not render OIDC callback template"), + ) + } + + ctx.Data(http.StatusOK, "text/html; charset=utf-8", content.Bytes()) + + return } From 67f5c32b49c68a873d095760315dd1e5ac9a8544 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 22 Feb 2022 19:04:52 +0000 Subject: [PATCH 070/204] Only allow one connection to sqlite --- db.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/db.go b/db.go index 7aadd20..90026ce 100644 --- a/db.go +++ b/db.go @@ -85,6 +85,9 @@ func (h *Headscale) openDB() (*gorm.DB, error) { DisableForeignKeyConstraintWhenMigrating: true, Logger: log, }) + + sqlDB, _ := db.DB() + sqlDB.SetMaxOpenConns(1) case Postgres: db, err = gorm.Open(postgres.Open(h.dbString), &gorm.Config{ DisableForeignKeyConstraintWhenMigrating: true, From 717250adb3fc8cf6a37550292caf70e5f17979a7 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 22 Feb 2022 20:58:08 +0100 Subject: [PATCH 071/204] feat: removing matchmap from headscale --- app.go | 1 - cmd/headscale/cli/utils.go | 15 --------------- config-example.yaml | 4 ---- 3 files changed, 20 deletions(-) diff --git a/app.go b/app.go index ac350ec..020f6fc 100644 --- a/app.go +++ b/app.go @@ -110,7 +110,6 @@ type OIDCConfig struct { Issuer string ClientID string ClientSecret string - MatchMap map[string]string } type DERPConfig struct { diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 85dcae7..f738ad3 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -10,7 +10,6 @@ import ( "net/url" "os" "path/filepath" - "regexp" "strconv" "strings" "time" @@ -356,8 +355,6 @@ func getHeadscaleApp() (*headscale.Headscale, error) { cfg := getHeadscaleConfig() - cfg.OIDC.MatchMap = loadOIDCMatchMap() - app, err := headscale.NewHeadscale(cfg) if err != nil { return nil, err @@ -514,18 +511,6 @@ func (tokenAuth) RequireTransportSecurity() bool { return true } -// loadOIDCMatchMap is a wrapper around viper to verifies that the keys in -// the match map is valid regex strings. -func loadOIDCMatchMap() map[string]string { - strMap := viper.GetStringMapString("oidc.domain_map") - - for oidcMatcher := range strMap { - _ = regexp.MustCompile(oidcMatcher) - } - - return strMap -} - func GetFileMode(key string) fs.FileMode { modeStr := viper.GetString(key) diff --git a/config-example.yaml b/config-example.yaml index ba0c653..17f556b 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -180,7 +180,3 @@ unix_socket_permission: "0770" # client_id: "your-oidc-client-id" # client_secret: "your-oidc-client-secret" # -# # Domain map is used to map incomming users (by their email) to -# # a namespace. The key can be a string, or regex. -# domain_map: -# ".*": default-namespace From afd4a3706ebe1d93f4ee9c4714df8de9bc7f4715 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 22 Feb 2022 21:05:39 +0100 Subject: [PATCH 072/204] chore: update formating --- namespaces.go | 9 +++++++-- namespaces_test.go | 1 + oidc.go | 3 +-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/namespaces.go b/namespaces.go index 8160b03..ec674b9 100644 --- a/namespaces.go +++ b/namespaces.go @@ -22,6 +22,11 @@ const ( errInvalidNamespaceName = Error("Invalid namespace name") ) +const ( + // value related to RFC 1123 and 952. + labelHostnameLength = 63 +) + var normalizeNamespaceRegex = regexp.MustCompile("[^a-z0-9-.]+") // Namespace is the way Headscale implements the concept of users in Tailscale @@ -271,7 +276,7 @@ func (n *Namespace) toProto() *v1.Namespace { } // NormalizeNamespaceName will replace forbidden chars in namespace -// it can also return an error if the namespace doesn't respect RFC 952 and 1123 +// it can also return an error if the namespace doesn't respect RFC 952 and 1123. func NormalizeNamespaceName(name string) (string, error) { name = strings.ToLower(name) name = strings.ReplaceAll(name, "@", ".") @@ -279,7 +284,7 @@ func NormalizeNamespaceName(name string) (string, error) { name = normalizeNamespaceRegex.ReplaceAllString(name, "-") for _, elt := range strings.Split(name, ".") { - if len(elt) > 63 { + if len(elt) > labelHostnameLength { return "", fmt.Errorf( "label %v is more than 63 chars: %w", elt, diff --git a/namespaces_test.go b/namespaces_test.go index cf2b323..d3519f9 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -292,6 +292,7 @@ func TestNormalizeNamespaceName(t *testing.T) { err, tt.wantErr, ) + return } if got != tt.want { diff --git a/oidc.go b/oidc.go index 495832a..78caa64 100644 --- a/oidc.go +++ b/oidc.go @@ -288,6 +288,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { http.StatusInternalServerError, "couldn't normalize email", ) + return } // register the machine if it's new @@ -365,6 +366,4 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { } ctx.Data(http.StatusOK, "text/html; charset=utf-8", content.Bytes()) - - return } From fe0b43eaaff43fd2692aa3c3da5c1ea7b92d2311 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 22 Feb 2022 21:20:59 +0100 Subject: [PATCH 073/204] chore: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c04a17..459d6c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - Add API Key support - Enable remote control of `headscale` via CLI [docs](docs/remote-cli.md) - Enable HTTP API (beta, subject to change) +- OIDC login will map user to an associated namespace. **Changes**: @@ -35,6 +36,7 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - Upgrade `tailscale` (1.20.4) and other dependencies to latest [#314](https://github.com/juanfont/headscale/pull/314) - fix swapped machine<->namespace labels in `/metrics` [#312](https://github.com/juanfont/headscale/pull/312) - remove key-value based update mechanism for namespace changes [#316](https://github.com/juanfont/headscale/pull/316) +- removal of the `oidc.domain_map` configuration parameter **0.12.4 (2022-01-29):** From 48c866b058374fbf79473509fae108f11428eff3 Mon Sep 17 00:00:00 2001 From: pernila Date: Tue, 22 Feb 2022 23:06:35 +0200 Subject: [PATCH 074/204] Added FreeBSD to the supported clients Added FreeBSD to the supported clients Now in ports: https://www.freshports.org/security/headscale/ --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e7ba664..76d7566 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ If you would like to sponsor features, bugs or prioritisation, reach out to one | ------- | ----------------------------------------------------------------------------------------------------------------- | | Linux | Yes | | OpenBSD | Yes | +| FreeBSD | Yes | | macOS | Yes (see `/apple` on your headscale for more information) | | Windows | Yes [docs](./docs/windows-client.md) | | Android | [You need to compile the client yourself](https://github.com/juanfont/headscale/issues/58#issuecomment-885255270) | From d4761da27cd5fcf609b89f076a32c84cae2b3070 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 22 Feb 2022 22:34:27 +0000 Subject: [PATCH 075/204] docs(README): update contributors --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 071dd2b..b21d604 100644 --- a/README.md +++ b/README.md @@ -430,6 +430,13 @@ make build
+ + pernila/ +
+ pernila +
+
Wakeful-Cloud/ From 45727dbb214f934b4a71bd694fa64570a6a4cf2e Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 23 Feb 2022 11:07:24 +0100 Subject: [PATCH 076/204] feat(namespace): add check function for namespace --- namespaces.go | 30 ++++++++++++++++++++++++-- namespaces_test.go | 52 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/namespaces.go b/namespaces.go index ec674b9..5062cc5 100644 --- a/namespaces.go +++ b/namespaces.go @@ -27,7 +27,7 @@ const ( labelHostnameLength = 63 ) -var normalizeNamespaceRegex = regexp.MustCompile("[^a-z0-9-.]+") +var invalidCharsInNamespaceRegex = regexp.MustCompile("[^a-z0-9-.]+") // Namespace is the way Headscale implements the concept of users in Tailscale // @@ -281,7 +281,7 @@ func NormalizeNamespaceName(name string) (string, error) { name = strings.ToLower(name) name = strings.ReplaceAll(name, "@", ".") name = strings.ReplaceAll(name, "'", "") - name = normalizeNamespaceRegex.ReplaceAllString(name, "-") + name = invalidCharsInNamespaceRegex.ReplaceAllString(name, "-") for _, elt := range strings.Split(name, ".") { if len(elt) > labelHostnameLength { @@ -295,3 +295,29 @@ func NormalizeNamespaceName(name string) (string, error) { return name, nil } + +func CheckNamespaceName(name string) error { + if len(name) > labelHostnameLength { + return fmt.Errorf( + "Namespace must not be over 63 chars. %v doesn't comply with this rule: %w", + name, + errInvalidNamespaceName, + ) + } + if strings.ToLower(name) != name { + return fmt.Errorf( + "Namespace name should be lowercase. %v doesn't comply with this rule: %w", + name, + errInvalidNamespaceName, + ) + } + if invalidCharsInNamespaceRegex.MatchString(name) { + return fmt.Errorf( + "Namespace name should only be composed of lowercase ASCII letters numbers, hyphen and dots. %v doesn't comply with theses rules: %w", + name, + errInvalidNamespaceName, + ) + } + + return nil +} diff --git a/namespaces_test.go b/namespaces_test.go index d3519f9..df4c5b0 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -74,13 +74,13 @@ func (s *Suite) TestRenameNamespace(c *check.C) { c.Assert(err, check.IsNil) c.Assert(len(namespaces), check.Equals, 1) - err = app.RenameNamespace("test", "test_renamed") + err = app.RenameNamespace("test", "test-renamed") c.Assert(err, check.IsNil) _, err = app.GetNamespace("test") c.Assert(err, check.Equals, errNamespaceNotFound) - _, err = app.GetNamespace("test_renamed") + _, err = app.GetNamespace("test-renamed") c.Assert(err, check.IsNil) err = app.RenameNamespace("test_does_not_exit", "test") @@ -90,7 +90,7 @@ func (s *Suite) TestRenameNamespace(c *check.C) { c.Assert(err, check.IsNil) c.Assert(namespaceTest2.Name, check.Equals, "test2") - err = app.RenameNamespace("test2", "test_renamed") + err = app.RenameNamespace("test2", "test-renamed") c.Assert(err, check.Equals, errNamespaceExists) } @@ -301,3 +301,49 @@ func TestNormalizeNamespaceName(t *testing.T) { }) } } + +func TestCheckNamespaceName(t *testing.T) { + type args struct { + name string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid: namespace", + args: args{name: "valid-namespace"}, + wantErr: false, + }, + { + name: "invalid: capitalized namespace", + args: args{name: "Invalid-CapItaLIzed-namespace"}, + wantErr: true, + }, + { + name: "invalid: email as namespace", + args: args{name: "foo.bar@example.com"}, + wantErr: true, + }, + { + name: "invalid: chars in namespace name", + args: args{name: "super-namespace+name"}, + wantErr: true, + }, + { + name: "invalid: too long name for namespace", + args: args{ + name: "super-long-namespace-name-that-should-be-a-little-more-than-63-chars", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CheckNamespaceName(tt.args.name); (err != nil) != tt.wantErr { + t.Errorf("CheckNamespaceName() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 995731a29c067890a7ddb7b1c3a2979f2e21272c Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 23 Feb 2022 11:13:37 +0100 Subject: [PATCH 077/204] fix(namespace): checknamespace name before actions I keep the check server side because it's better from a security point of view. --- namespaces.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/namespaces.go b/namespaces.go index 5062cc5..f276562 100644 --- a/namespaces.go +++ b/namespaces.go @@ -41,12 +41,11 @@ type Namespace struct { // CreateNamespace creates a new Namespace. Returns error if could not be created // or another namespace already exists. func (h *Headscale) CreateNamespace(name string) (*Namespace, error) { - var err error - namespace := Namespace{} - name, err = NormalizeNamespaceName(name) + err := CheckNamespaceName(name) if err != nil { return nil, err } + namespace := Namespace{} if err := h.db.Where("name = ?", name).First(&namespace).Error; err == nil { return nil, errNamespaceExists } @@ -66,7 +65,7 @@ func (h *Headscale) CreateNamespace(name string) (*Namespace, error) { // DestroyNamespace destroys a Namespace. Returns error if the Namespace does // not exist or if there are machines associated with it. func (h *Headscale) DestroyNamespace(name string) error { - name, err := NormalizeNamespaceName(name) + err := CheckNamespaceName(name) if err != nil { return err } @@ -109,7 +108,7 @@ func (h *Headscale) RenameNamespace(oldName, newName string) error { if err != nil { return err } - newName, err = NormalizeNamespaceName(newName) + err = CheckNamespaceName(newName) if err != nil { return err } @@ -132,11 +131,11 @@ func (h *Headscale) RenameNamespace(oldName, newName string) error { // GetNamespace fetches a namespace by name. func (h *Headscale) GetNamespace(name string) (*Namespace, error) { - namespace := Namespace{} - name, err := NormalizeNamespaceName(name) + err := CheckNamespaceName(name) if err != nil { return nil, err } + namespace := Namespace{} if result := h.db.First(&namespace, "name = ?", name); errors.Is( result.Error, gorm.ErrRecordNotFound, @@ -159,7 +158,7 @@ func (h *Headscale) ListNamespaces() ([]Namespace, error) { // ListMachinesInNamespace gets all the nodes in a given namespace. func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { - name, err := NormalizeNamespaceName(name) + err := CheckNamespaceName(name) if err != nil { return nil, err } @@ -178,7 +177,7 @@ func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { // ListSharedMachinesInNamespace returns all the machines that are shared to the specified namespace. func (h *Headscale) ListSharedMachinesInNamespace(name string) ([]Machine, error) { - name, err := NormalizeNamespaceName(name) + err := CheckNamespaceName(name) if err != nil { return nil, err } @@ -207,7 +206,7 @@ func (h *Headscale) ListSharedMachinesInNamespace(name string) ([]Machine, error // SetMachineNamespace assigns a Machine to a namespace. func (h *Headscale) SetMachineNamespace(machine *Machine, namespaceName string) error { - namespaceName, err := NormalizeNamespaceName(namespaceName) + err := CheckNamespaceName(namespaceName) if err != nil { return err } From fcdbe7c5109b83065c150338b143c13e611b4cc6 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 23 Feb 2022 11:38:20 +0100 Subject: [PATCH 078/204] fix(utils_test): fix namespace name --- utils_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils_test.go b/utils_test.go index feb44d5..f193160 100644 --- a/utils_test.go +++ b/utils_test.go @@ -20,7 +20,7 @@ func (s *Suite) TestGetUsedIps(c *check.C) { ips, err := app.getAvailableIPs() c.Assert(err, check.IsNil) - namespace, err := app.CreateNamespace("test_ip") + namespace, err := app.CreateNamespace("test-ip") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) @@ -142,7 +142,7 @@ func (s *Suite) TestGetAvailableIpMachineWithoutIP(c *check.C) { c.Assert(len(ips), check.Equals, 1) c.Assert(ips[0].String(), check.Equals, expected.String()) - namespace, err := app.CreateNamespace("test_ip") + namespace, err := app.CreateNamespace("test-ip") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) From cef0a2b0b3d6bae1a0a58d74a08363a82e9c1060 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 23 Feb 2022 11:40:48 +0100 Subject: [PATCH 079/204] fix(namespaces_test): fix missing namespace name --- namespaces_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/namespaces_test.go b/namespaces_test.go index df4c5b0..6b8df2b 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -83,7 +83,7 @@ func (s *Suite) TestRenameNamespace(c *check.C) { _, err = app.GetNamespace("test-renamed") c.Assert(err, check.IsNil) - err = app.RenameNamespace("test_does_not_exit", "test") + err = app.RenameNamespace("test-does-not-exit", "test") c.Assert(err, check.Equals, errNamespaceNotFound) namespaceTest2, err := app.CreateNamespace("test2") From 7e4709c13f79574620133d639498bff945c8423b Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 23 Feb 2022 13:35:57 +0100 Subject: [PATCH 080/204] fix(namespace): remove name validation for destroy and get --- namespaces.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/namespaces.go b/namespaces.go index f276562..cf1efe5 100644 --- a/namespaces.go +++ b/namespaces.go @@ -65,10 +65,6 @@ func (h *Headscale) CreateNamespace(name string) (*Namespace, error) { // DestroyNamespace destroys a Namespace. Returns error if the Namespace does // not exist or if there are machines associated with it. func (h *Headscale) DestroyNamespace(name string) error { - err := CheckNamespaceName(name) - if err != nil { - return err - } namespace, err := h.GetNamespace(name) if err != nil { return errNamespaceNotFound @@ -131,10 +127,6 @@ func (h *Headscale) RenameNamespace(oldName, newName string) error { // GetNamespace fetches a namespace by name. func (h *Headscale) GetNamespace(name string) (*Namespace, error) { - err := CheckNamespaceName(name) - if err != nil { - return nil, err - } namespace := Namespace{} if result := h.db.First(&namespace, "name = ?", name); errors.Is( result.Error, From 4f1f235a2e1ce251ba11d86bc96a6c1ca72f087b Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 23 Feb 2022 14:03:07 +0100 Subject: [PATCH 081/204] feat: add strip_email_domain to normalization of namespace --- app.go | 7 +++--- cmd/headscale/cli/utils.go | 9 ++++--- config-example.yaml | 6 +++++ namespaces.go | 9 +++++-- namespaces_test.go | 49 ++++++++++++++++++++++++++++---------- oidc.go | 2 +- 6 files changed, 61 insertions(+), 21 deletions(-) diff --git a/app.go b/app.go index 020f6fc..fa1f5a0 100644 --- a/app.go +++ b/app.go @@ -107,9 +107,10 @@ type Config struct { } type OIDCConfig struct { - Issuer string - ClientID string - ClientSecret string + Issuer string + ClientID string + ClientSecret string + StripEmaildomain bool } type DERPConfig struct { diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index f738ad3..d38bb26 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -63,6 +63,8 @@ func LoadConfig(path string) error { viper.SetDefault("cli.timeout", "5s") viper.SetDefault("cli.insecure", false) + viper.SetDefault("oidc.strip_email_domain", true) + if err := viper.ReadInConfig(); err != nil { return fmt.Errorf("fatal error reading config file: %w", err) } @@ -323,9 +325,10 @@ func getHeadscaleConfig() headscale.Config { UnixSocketPermission: GetFileMode("unix_socket_permission"), OIDC: headscale.OIDCConfig{ - Issuer: viper.GetString("oidc.issuer"), - ClientID: viper.GetString("oidc.client_id"), - ClientSecret: viper.GetString("oidc.client_secret"), + Issuer: viper.GetString("oidc.issuer"), + ClientID: viper.GetString("oidc.client_id"), + ClientSecret: viper.GetString("oidc.client_secret"), + StripEmaildomain: viper.GetBool("oidc.strip_email_domain"), }, CLI: headscale.CLIConfig{ diff --git a/config-example.yaml b/config-example.yaml index 17f556b..71fdfaa 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -180,3 +180,9 @@ unix_socket_permission: "0770" # client_id: "your-oidc-client-id" # client_secret: "your-oidc-client-secret" # +# If `strip_email_domain` is set to `true`, the domain part of the username email address will be removed. +# This will transform `first-name.last-name@example.com` to the namespace `first-name.last-name` +# If `strip_email_domain` is set to `false` the domain part will NOT be removed resulting to the following +# namespace: `first-name.last-name.example.com` +# +# strip_email_domain: true diff --git a/namespaces.go b/namespaces.go index cf1efe5..b02f7a7 100644 --- a/namespaces.go +++ b/namespaces.go @@ -268,10 +268,15 @@ func (n *Namespace) toProto() *v1.Namespace { // NormalizeNamespaceName will replace forbidden chars in namespace // it can also return an error if the namespace doesn't respect RFC 952 and 1123. -func NormalizeNamespaceName(name string) (string, error) { +func NormalizeNamespaceName(name string, stripEmailDomain bool) (string, error) { name = strings.ToLower(name) - name = strings.ReplaceAll(name, "@", ".") name = strings.ReplaceAll(name, "'", "") + if stripEmailDomain { + idx := strings.Index(name, "@") + name = name[:idx] + } else { + name = strings.ReplaceAll(name, "@", ".") + } name = invalidCharsInNamespaceRegex.ReplaceAllString(name, "-") for _, elt := range strings.Split(name, ".") { diff --git a/namespaces_test.go b/namespaces_test.go index 6b8df2b..6fb572c 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -244,7 +244,8 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { func TestNormalizeNamespaceName(t *testing.T) { type args struct { - name string + name string + stripEmailDomain bool } tests := []struct { name string @@ -253,39 +254,63 @@ func TestNormalizeNamespaceName(t *testing.T) { wantErr bool }{ { - name: "normalize simple name", - args: args{name: "normalize-simple.name"}, + name: "normalize simple name", + args: args{ + name: "normalize-simple.name", + stripEmailDomain: false, + }, want: "normalize-simple.name", wantErr: false, }, { - name: "normalize an email", - args: args{name: "foo.bar@example.com"}, + name: "normalize an email", + args: args{ + name: "foo.bar@example.com", + stripEmailDomain: false, + }, want: "foo.bar.example.com", wantErr: false, }, { - name: "normalize complex email", - args: args{name: "foo.bar+complex-email@example.com"}, + name: "normalize an email domain should be removed", + args: args{ + name: "foo.bar@example.com", + stripEmailDomain: true, + }, + want: "foo.bar", + wantErr: false, + }, + { + name: "normalize complex email", + args: args{ + name: "foo.bar+complex-email@example.com", + stripEmailDomain: false, + }, want: "foo.bar-complex-email.example.com", wantErr: false, }, { - name: "namespace name with space", - args: args{name: "name space"}, + name: "namespace name with space", + args: args{ + name: "name space", + stripEmailDomain: false, + }, want: "name-space", wantErr: false, }, { - name: "namespace with quote", - args: args{name: "Jamie's iPhone 5"}, + name: "namespace with quote", + args: args{ + name: "Jamie's iPhone 5", + stripEmailDomain: false, + }, want: "jamies-iphone-5", wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NormalizeNamespaceName(tt.args.name) + got, err := NormalizeNamespaceName(tt.args.name, tt.args.stripEmailDomain) if (err != nil) != tt.wantErr { t.Errorf( "NormalizeNamespaceName() error = %v, wantErr %v", diff --git a/oidc.go b/oidc.go index 78caa64..2036c4d 100644 --- a/oidc.go +++ b/oidc.go @@ -281,7 +281,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { now := time.Now().UTC() - namespaceName, err := NormalizeNamespaceName(claims.Email) + namespaceName, err := NormalizeNamespaceName(claims.Email, h.cfg.OIDC.StripEmaildomain) if err != nil { log.Error().Err(err).Caller().Msgf("couldn't normalize email") ctx.String( From 972bef1194c44091dfe694c1abbf77fc39b70c26 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 23 Feb 2022 14:21:46 +0100 Subject: [PATCH 082/204] feat: add length error if hostname too long --- machine.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/machine.go b/machine.go index 25edd1d..4536ef3 100644 --- a/machine.go +++ b/machine.go @@ -25,6 +25,11 @@ const ( errMachineAlreadyRegistered = Error("machine already registered") errMachineRouteIsNotAvailable = Error("route is not available on machine") errMachineAddressesInvalid = Error("failed to parse machine addresses") + errHostnameTooLong = Error("Hostname too long") +) + +const ( + maxHostnameLength = 255 ) // Machine is a Headscale client. @@ -727,6 +732,13 @@ func (machine Machine) toNode( machine.Namespace.Name, baseDomain, ) + if len(hostname) > maxHostnameLength { + return nil, fmt.Errorf( + "hostname %q is too long it cannot except 255 ASCII chars: %w", + hostname, + errHostnameTooLong, + ) + } } else { hostname = machine.Name } From 046116656b325922a5c39d07398b343f3bfbe33f Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 23 Feb 2022 14:22:21 +0100 Subject: [PATCH 083/204] chore: update formatting --- oidc.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/oidc.go b/oidc.go index 2036c4d..edea32a 100644 --- a/oidc.go +++ b/oidc.go @@ -281,7 +281,10 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { now := time.Now().UTC() - namespaceName, err := NormalizeNamespaceName(claims.Email, h.cfg.OIDC.StripEmaildomain) + namespaceName, err := NormalizeNamespaceName( + claims.Email, + h.cfg.OIDC.StripEmaildomain, + ) if err != nil { log.Error().Err(err).Caller().Msgf("couldn't normalize email") ctx.String( From ae6a20e4d93a7bd53404fd32cbd46e9728705669 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 23 Feb 2022 14:28:20 +0100 Subject: [PATCH 084/204] fix: add valid test identified by linter --- namespaces.go | 6 +++--- namespaces_test.go | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/namespaces.go b/namespaces.go index b02f7a7..e5c6448 100644 --- a/namespaces.go +++ b/namespaces.go @@ -271,9 +271,9 @@ func (n *Namespace) toProto() *v1.Namespace { func NormalizeNamespaceName(name string, stripEmailDomain bool) (string, error) { name = strings.ToLower(name) name = strings.ReplaceAll(name, "'", "") - if stripEmailDomain { - idx := strings.Index(name, "@") - name = name[:idx] + atIdx := strings.Index(name, "@") + if stripEmailDomain && atIdx > 0 { + name = name[:atIdx] } else { name = strings.ReplaceAll(name, "@", ".") } diff --git a/namespaces_test.go b/namespaces_test.go index 6fb572c..6cef5f5 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -280,6 +280,15 @@ func TestNormalizeNamespaceName(t *testing.T) { want: "foo.bar", wantErr: false, }, + { + name: "strip enabled no email passed as argument", + args: args{ + name: "not-email-and-strip-enabled", + stripEmailDomain: true, + }, + want: "not-email-and-strip-enabled", + wantErr: false, + }, { name: "normalize complex email", args: args{ From 686e45cf27b9d509530f590fefffb90941cbdcbc Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 23 Feb 2022 16:15:20 +0000 Subject: [PATCH 085/204] Set all anti-cgo options and add comment --- db.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/db.go b/db.go index 90026ce..feee747 100644 --- a/db.go +++ b/db.go @@ -2,6 +2,7 @@ package headscale import ( "errors" + "time" "github.com/glebarez/sqlite" "gorm.io/driver/postgres" @@ -81,13 +82,24 @@ func (h *Headscale) openDB() (*gorm.DB, error) { switch h.dbType { case Sqlite: - db, err = gorm.Open(sqlite.Open(h.dbString), &gorm.Config{ - DisableForeignKeyConstraintWhenMigrating: true, - Logger: log, - }) + db, err = gorm.Open( + sqlite.Open(h.dbString+"?_synchronous=1&_journal_mode=WAL"), + &gorm.Config{ + DisableForeignKeyConstraintWhenMigrating: true, + Logger: log, + }, + ) + db.Exec("PRAGMA foreign_keys=ON") + + // The pure Go SQLite library does not handle locking in + // the same way as the C based one and we cant use the gorm + // connection pool as of 2022/02/23. sqlDB, _ := db.DB() + sqlDB.SetMaxIdleConns(1) sqlDB.SetMaxOpenConns(1) + sqlDB.SetConnMaxIdleTime(time.Hour) + case Postgres: db, err = gorm.Open(postgres.Open(h.dbString), &gorm.Config{ DisableForeignKeyConstraintWhenMigrating: true, From 8c339076555c6872d2379500ebcaeabcdd1c8184 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 24 Feb 2022 11:10:40 +0000 Subject: [PATCH 086/204] Sort lint --- cmd/headscale/cli/utils.go | 4 +++- docs/tls.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 9316302..e3dce6b 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -94,7 +94,9 @@ func LoadConfig(path string) error { errorText += "Fatal config error: server_url must start with https:// or http://\n" } - _, authModeValid := headscale.LookupTLSClientAuthMode(viper.GetString("tls_client_auth_mode")) + _, authModeValid := headscale.LookupTLSClientAuthMode( + viper.GetString("tls_client_auth_mode"), + ) if !authModeValid { errorText += fmt.Sprintf( diff --git a/docs/tls.md b/docs/tls.md index 7dc322c..c319359 100644 --- a/docs/tls.md +++ b/docs/tls.md @@ -35,7 +35,7 @@ tls_key_path: "" mTLS is a method by which an HTTPS server authenticates clients, e.g. Tailscale, using TLS certificates. This can be configured by applying one of the following values to the `tls_client_auth_mode` setting in the configuration file. | Value | Behavior | -| ------------------- | -----------------------------------------------------------| +| ------------------- | ---------------------------------------------------------- | | `disabled` | Disable mTLS. | | `relaxed` (default) | A client certificate is required, but it is not verified. | | `enforced` | Requires clients to supply a certificate that is verified. | From fb85c78e8a32a12c8befb0f95bea138aeeee2cf2 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 24 Feb 2022 11:28:34 +0000 Subject: [PATCH 087/204] Fail integration tests fast --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5214509..266dadb 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ test: @go test -coverprofile=coverage.out ./... test_integration: - go test -tags integration -timeout 30m -count=1 ./... + go test -failfast -tags integration -timeout 30m -count=1 ./... test_integration_cli: go test -tags integration -v integration_cli_test.go integration_common_test.go From 9687e6768d1383e87843724e17909b87e3779e14 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 24 Feb 2022 11:29:53 +0000 Subject: [PATCH 088/204] Remove retry from integration tests --- .github/workflows/test-integration.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index 84651ab..b8fd85a 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -29,9 +29,4 @@ jobs: - name: Run Integration tests if: steps.changed-files.outputs.any_changed == 'true' - uses: nick-invision/retry@v2 - with: - timeout_minutes: 100 - max_attempts: 5 - retry_on: error - command: go test -tags integration -timeout 20m + run: make test_integration From f9ce32fe1a856ee423711c603566086413973586 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Thu, 24 Feb 2022 13:34:36 +0100 Subject: [PATCH 089/204] Update CHANGELOG.md Co-authored-by: Kristoffer Dalby --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a489421..b66477c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,10 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - Add API Key support - Enable remote control of `headscale` via CLI [docs](docs/remote-cli.md) - Enable HTTP API (beta, subject to change) -- OIDC login will map user to an associated namespace. +- OpenID Connect users will be mapped per namespaces + - Each user will get its own namespace, created if it does not exist + - `oidc.domain_map` option has been removed + - `strip_email_domain` option has been added (see [config-example.yaml](./config_example.yaml)) **Changes**: From 47e8442d915072366a080fc9c4fdd45b9c380be9 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Thu, 24 Feb 2022 13:34:48 +0100 Subject: [PATCH 090/204] Update CHANGELOG.md Co-authored-by: Kristoffer Dalby --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b66477c..39e0777 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,7 +47,6 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - Upgrade `tailscale` (1.20.4) and other dependencies to latest [#314](https://github.com/juanfont/headscale/pull/314) - fix swapped machine<->namespace labels in `/metrics` [#312](https://github.com/juanfont/headscale/pull/312) - remove key-value based update mechanism for namespace changes [#316](https://github.com/juanfont/headscale/pull/316) -- removal of the `oidc.domain_map` configuration parameter **0.12.4 (2022-01-29):** From eda0a9f88a694c62afc858202d144e0a62019cf7 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Thu, 24 Feb 2022 13:18:18 +0000 Subject: [PATCH 091/204] Lock allocation of IP address current logic is not safe as it will allow an IP that isnt persisted to the DB to be given out multiple times if machines joins in quick succession. This adds a lock around the "get ip" and machine registration and save to DB so we ensure thiis isnt happning. Currently this had to be done three places, which is silly, and outlined in #294. --- api.go | 5 +++++ app.go | 2 ++ machine.go | 3 +++ oidc.go | 4 ++++ utils.go | 44 +++++++++++++++++++++++--------------------- 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/api.go b/api.go index 073be5e..bb5495a 100644 --- a/api.go +++ b/api.go @@ -574,6 +574,9 @@ func (h *Headscale) handleAuthKey( Str("func", "handleAuthKey"). Str("machine", machine.Name). Msg("Authentication key was valid, proceeding to acquire IP addresses") + + h.ipAllocationMutex.Lock() + ips, err := h.getAvailableIPs() if err != nil { log.Error(). @@ -602,6 +605,8 @@ func (h *Headscale) handleAuthKey( machine.Registered = true machine.RegisterMethod = RegisterMethodAuthKey h.db.Save(&machine) + + h.ipAllocationMutex.Unlock() } pak.Used = true diff --git a/app.go b/app.go index 26ec956..68d933c 100644 --- a/app.go +++ b/app.go @@ -153,6 +153,8 @@ type Headscale struct { oidcStateCache *cache.Cache requestedExpiryCache *cache.Cache + + ipAllocationMutex sync.Mutex } // Look up the TLS constant relative to user-supplied TLS client diff --git a/machine.go b/machine.go index 3c704ad..7de99a6 100644 --- a/machine.go +++ b/machine.go @@ -856,6 +856,9 @@ func (h *Headscale) RegisterMachine( return nil, err } + h.ipAllocationMutex.Lock() + defer h.ipAllocationMutex.Unlock() + ips, err := h.getAvailableIPs() if err != nil { log.Error(). diff --git a/oidc.go b/oidc.go index a47863f..cd77d29 100644 --- a/oidc.go +++ b/oidc.go @@ -317,6 +317,8 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } + h.ipAllocationMutex.Lock() + ips, err := h.getAvailableIPs() if err != nil { log.Error(). @@ -338,6 +340,8 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { machine.LastSuccessfulUpdate = &now machine.Expiry = &requestedTime h.db.Save(&machine) + + h.ipAllocationMutex.Unlock() } var content bytes.Buffer diff --git a/utils.go b/utils.go index 3cee5e3..c1a39bb 100644 --- a/utils.go +++ b/utils.go @@ -12,6 +12,7 @@ import ( "encoding/json" "fmt" "net" + "sort" "strings" "github.com/rs/zerolog/log" @@ -157,9 +158,6 @@ func GetIPPrefixEndpoints(na netaddr.IPPrefix) (network, broadcast netaddr.IP) { return } -// TODO: Is this concurrency safe? -// What would happen if multiple hosts were to register at the same time? -// Would we attempt to assign the same addresses to multiple nodes? func (h *Headscale) getAvailableIP(ipPrefix netaddr.IPPrefix) (*netaddr.IP, error) { usedIps, err := h.getUsedIPs() if err != nil { @@ -179,7 +177,7 @@ func (h *Headscale) getAvailableIP(ipPrefix netaddr.IPPrefix) (*netaddr.IP, erro switch { case ip.Compare(ipPrefixBroadcastAddress) == 0: fallthrough - case containsIPs(usedIps, ip): + case usedIps.Contains(ip): fallthrough case ip.IsZero() || ip.IsLoopback(): ip = ip.Next() @@ -192,24 +190,38 @@ func (h *Headscale) getAvailableIP(ipPrefix netaddr.IPPrefix) (*netaddr.IP, erro } } -func (h *Headscale) getUsedIPs() ([]netaddr.IP, error) { +func (h *Headscale) getUsedIPs() (netaddr.IPSet, error) { // FIXME: This really deserves a better data model, // but this was quick to get running and it should be enough // to begin experimenting with a dual stack tailnet. var addressesSlices []string h.db.Model(&Machine{}).Pluck("ip_addresses", &addressesSlices) - ips := make([]netaddr.IP, 0, len(h.cfg.IPPrefixes)*len(addressesSlices)) + log.Trace(). + Strs("addresses", addressesSlices). + Msg("Got allocated ip addresses from databases") + + var ips netaddr.IPSetBuilder for _, slice := range addressesSlices { - var a MachineAddresses - err := a.Scan(slice) + var machineAddresses MachineAddresses + err := machineAddresses.Scan(slice) if err != nil { - return nil, fmt.Errorf("failed to read ip from database: %w", err) + return netaddr.IPSet{}, fmt.Errorf( + "failed to read ip from database: %w", + err, + ) + } + + for _, ip := range machineAddresses { + ips.Add(ip) } - ips = append(ips, a...) } - return ips, nil + log.Trace(). + Interface("addresses", ips). + Msg("Parsed ip addresses that has been allocated from databases") + + return netaddr.IPSet{}, nil } func containsString(ss []string, s string) bool { @@ -222,16 +234,6 @@ func containsString(ss []string, s string) bool { return false } -func containsIPs(ips []netaddr.IP, ip netaddr.IP) bool { - for _, v := range ips { - if v == ip { - return true - } - } - - return false -} - func tailNodesToString(nodes []*tailcfg.Node) string { temp := make([]string, len(nodes)) From ebe59a5a2781fa928f3625a40ef44069b10507e8 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 25 Feb 2022 08:28:22 +0000 Subject: [PATCH 092/204] Fix utils tests, use ipset datastructure --- utils.go | 15 +++++++++++---- utils_test.go | 32 +++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/utils.go b/utils.go index c1a39bb..004bf30 100644 --- a/utils.go +++ b/utils.go @@ -12,7 +12,6 @@ import ( "encoding/json" "fmt" "net" - "sort" "strings" "github.com/rs/zerolog/log" @@ -190,7 +189,7 @@ func (h *Headscale) getAvailableIP(ipPrefix netaddr.IPPrefix) (*netaddr.IP, erro } } -func (h *Headscale) getUsedIPs() (netaddr.IPSet, error) { +func (h *Headscale) getUsedIPs() (*netaddr.IPSet, error) { // FIXME: This really deserves a better data model, // but this was quick to get running and it should be enough // to begin experimenting with a dual stack tailnet. @@ -206,7 +205,7 @@ func (h *Headscale) getUsedIPs() (netaddr.IPSet, error) { var machineAddresses MachineAddresses err := machineAddresses.Scan(slice) if err != nil { - return netaddr.IPSet{}, fmt.Errorf( + return &netaddr.IPSet{}, fmt.Errorf( "failed to read ip from database: %w", err, ) @@ -221,7 +220,15 @@ func (h *Headscale) getUsedIPs() (netaddr.IPSet, error) { Interface("addresses", ips). Msg("Parsed ip addresses that has been allocated from databases") - return netaddr.IPSet{}, nil + ipSet, err := ips.IPSet() + if err != nil { + return &netaddr.IPSet{}, fmt.Errorf( + "failed to build IP Set: %w", + err, + ) + } + + return ipSet, nil } func containsString(ss []string, s string) bool { diff --git a/utils_test.go b/utils_test.go index feb44d5..896040c 100644 --- a/utils_test.go +++ b/utils_test.go @@ -48,9 +48,12 @@ func (s *Suite) TestGetUsedIps(c *check.C) { c.Assert(err, check.IsNil) expected := netaddr.MustParseIP("10.27.0.1") + expectedIPSetBuilder := netaddr.IPSetBuilder{} + expectedIPSetBuilder.Add(expected) + expectedIPSet, _ := expectedIPSetBuilder.IPSet() - c.Assert(len(usedIps), check.Equals, 1) - c.Assert(usedIps[0], check.Equals, expected) + c.Assert(usedIps.Equal(expectedIPSet), check.Equals, true) + c.Assert(usedIps.Contains(expected), check.Equals, true) machine1, err := app.GetMachineByID(0) c.Assert(err, check.IsNil) @@ -64,6 +67,8 @@ func (s *Suite) TestGetMultiIp(c *check.C) { c.Assert(err, check.IsNil) for index := 1; index <= 350; index++ { + app.ipAllocationMutex.Lock() + ips, err := app.getAvailableIPs() c.Assert(err, check.IsNil) @@ -86,17 +91,30 @@ func (s *Suite) TestGetMultiIp(c *check.C) { IPAddresses: ips, } app.db.Save(&machine) + + app.ipAllocationMutex.Unlock() } usedIps, err := app.getUsedIPs() - c.Assert(err, check.IsNil) - c.Assert(len(usedIps), check.Equals, 350) + expected0 := netaddr.MustParseIP("10.27.0.1") + expected9 := netaddr.MustParseIP("10.27.0.10") + expected300 := netaddr.MustParseIP("10.27.0.45") - c.Assert(usedIps[0], check.Equals, netaddr.MustParseIP("10.27.0.1")) - c.Assert(usedIps[9], check.Equals, netaddr.MustParseIP("10.27.0.10")) - c.Assert(usedIps[300], check.Equals, netaddr.MustParseIP("10.27.1.45")) + notExpectedIPSetBuilder := netaddr.IPSetBuilder{} + notExpectedIPSetBuilder.Add(expected0) + notExpectedIPSetBuilder.Add(expected9) + notExpectedIPSetBuilder.Add(expected300) + notExpectedIPSet, err := notExpectedIPSetBuilder.IPSet() + c.Assert(err, check.IsNil) + + // We actually expect it to be a lot larger + c.Assert(usedIps.Equal(notExpectedIPSet), check.Equals, false) + + c.Assert(usedIps.Contains(expected0), check.Equals, true) + c.Assert(usedIps.Contains(expected9), check.Equals, true) + c.Assert(usedIps.Contains(expected300), check.Equals, true) // Check that we can read back the IPs machine1, err := app.GetMachineByID(1) From 6d699d3c296b65eedf963aef3f3b2cb3dde0dad6 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 25 Feb 2022 08:44:16 +0000 Subject: [PATCH 093/204] Update changelog --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 531137f..fa357c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,13 @@ **TBD (TBD):** -**0.14.0 (2022-xx-xx):** +**0.15.0 (2022-xx-xx):** + +**Changes**: + +- Fix a bug were the same IP could be assigned to multiple hosts if joined in quick succession [#346](https://github.com/juanfont/headscale/pull/346) + +**0.14.0 (2022-02-25):** **UPCOMING BREAKING**: From the **next** version (`0.15.0`), all machines will be able to communicate regardless of From e03b3d558fa43ce5f226ac7dac2537131bc98c0e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 25 Feb 2022 10:26:34 +0100 Subject: [PATCH 094/204] Remove boundries between namespaces --- acls.go | 2 +- machine.go | 25 ++++++------------------- machine_test.go | 6 +++--- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/acls.go b/acls.go index db2fc58..ce14a89 100644 --- a/acls.go +++ b/acls.go @@ -90,7 +90,7 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { return nil, errEmptyPolicy } - machines, err := h.ListAllMachines() + machines, err := h.ListMachines() if err != nil { return nil, err } diff --git a/machine.go b/machine.go index 7656304..603441d 100644 --- a/machine.go +++ b/machine.go @@ -118,19 +118,6 @@ func (machine Machine) isExpired() bool { return time.Now().UTC().After(*machine.Expiry) } -func (h *Headscale) ListAllMachines() ([]Machine, error) { - machines := []Machine{} - if err := h.db.Preload("AuthKey"). - Preload("AuthKey.Namespace"). - Preload("Namespace"). - Where("registered"). - Find(&machines).Error; err != nil { - return nil, err - } - - return machines, nil -} - func containsAddresses(inputs []string, addrs []string) bool { for _, addr := range addrs { if containsString(inputs, addr) { @@ -215,15 +202,15 @@ func getFilteredByACLPeers( return authorizedPeers } -func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { +func (h *Headscale) ListPeers(machine *Machine) (Machines, error) { log.Trace(). Caller(). Str("machine", machine.Name). Msg("Finding direct peers") machines := Machines{} - if err := h.db.Preload("Namespace").Where("namespace_id = ? AND machine_key <> ? AND registered", - machine.NamespaceID, machine.MachineKey).Find(&machines).Error; err != nil { + if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Where("machine_key <> ? AND registered", + machine.MachineKey).Find(&machines).Error; err != nil { log.Error().Err(err).Msg("Error accessing db") return Machines{}, err @@ -234,7 +221,7 @@ func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { log.Trace(). Caller(). Str("machine", machine.Name). - Msgf("Found direct machines: %s", machines.String()) + Msgf("Found peers: %s", machines.String()) return machines, nil } @@ -247,7 +234,7 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) { // else use the classic namespace scope if h.aclPolicy != nil { var machines []Machine - machines, err = h.ListAllMachines() + machines, err = h.ListMachines() if err != nil { log.Error().Err(err).Msg("Error retrieving list of machines") @@ -255,7 +242,7 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) { } peers = getFilteredByACLPeers(machines, h.aclRules, machine) } else { - peers, err = h.getDirectPeers(machine) + peers, err = h.ListPeers(machine) if err != nil { log.Error(). Caller(). diff --git a/machine_test.go b/machine_test.go index b1cd341..e9c91f8 100644 --- a/machine_test.go +++ b/machine_test.go @@ -118,7 +118,7 @@ func (s *Suite) TestHardDeleteMachine(c *check.C) { c.Assert(err, check.NotNil) } -func (s *Suite) TestGetDirectPeers(c *check.C) { +func (s *Suite) TestListPeers(c *check.C) { namespace, err := app.CreateNamespace("test") c.Assert(err, check.IsNil) @@ -149,7 +149,7 @@ func (s *Suite) TestGetDirectPeers(c *check.C) { _, err = machine0ByID.GetHostInfo() c.Assert(err, check.IsNil) - peersOfMachine0, err := app.getDirectPeers(machine0ByID) + peersOfMachine0, err := app.ListPeers(machine0ByID) c.Assert(err, check.IsNil) c.Assert(len(peersOfMachine0), check.Equals, 9) @@ -222,7 +222,7 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { _, err = testMachine.GetHostInfo() c.Assert(err, check.IsNil) - machines, err := app.ListAllMachines() + machines, err := app.ListMachines() c.Assert(err, check.IsNil) peersOfTestMachine := getFilteredByACLPeers(machines, app.aclRules, testMachine) From d9e7f372800e3650f9d328fbf4d817a34cd0810d Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 25 Feb 2022 10:27:27 +0100 Subject: [PATCH 095/204] Uncomment previous test and update them for no boundries --- dns_test.go | 27 ++++++++++----------- namespaces_test.go | 58 ++++++++++++++++++++++------------------------ 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/dns_test.go b/dns_test.go index b81bc7f..23a34ca 100644 --- a/dns_test.go +++ b/dns_test.go @@ -1,6 +1,8 @@ package headscale import ( + "fmt" + "gopkg.in/check.v1" "inet.af/netaddr" "tailscale.com/tailcfg" @@ -241,20 +243,19 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { ) c.Assert(dnsConfig, check.NotNil) - // TODO: Remove comment out when we have all nodes available to every node - // c.Assert(len(dnsConfig.Routes), check.Equals, 2) + c.Assert(len(dnsConfig.Routes), check.Equals, 3) - // domainRouteShared1 := fmt.Sprintf("%s.%s", namespaceShared1.Name, baseDomain) - // _, ok := dnsConfig.Routes[domainRouteShared1] - // c.Assert(ok, check.Equals, true) - // - // domainRouteShared2 := fmt.Sprintf("%s.%s", namespaceShared2.Name, baseDomain) - // _, ok = dnsConfig.Routes[domainRouteShared2] - // c.Assert(ok, check.Equals, true) - // - // domainRouteShared3 := fmt.Sprintf("%s.%s", namespaceShared3.Name, baseDomain) - // _, ok = dnsConfig.Routes[domainRouteShared3] - // c.Assert(ok, check.Equals, false) + domainRouteShared1 := fmt.Sprintf("%s.%s", namespaceShared1.Name, baseDomain) + _, ok := dnsConfig.Routes[domainRouteShared1] + c.Assert(ok, check.Equals, true) + + domainRouteShared2 := fmt.Sprintf("%s.%s", namespaceShared2.Name, baseDomain) + _, ok = dnsConfig.Routes[domainRouteShared2] + c.Assert(ok, check.Equals, true) + + domainRouteShared3 := fmt.Sprintf("%s.%s", namespaceShared3.Name, baseDomain) + _, ok = dnsConfig.Routes[domainRouteShared3] + c.Assert(ok, check.Equals, true) } func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { diff --git a/namespaces_test.go b/namespaces_test.go index f7b345b..77c33ad 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -205,35 +205,33 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { } app.db.Save(machine2InShared1) - // TODO: Remove comment out when we have all nodes available to every node - // peersOfMachine1InShared1, err := app.getPeers(machineInShared1) - // c.Assert(err, check.IsNil) + peersOfMachine1InShared1, err := app.getPeers(machineInShared1) + c.Assert(err, check.IsNil) - // userProfiles := getMapResponseUserProfiles( - // *machineInShared1, - // peersOfMachine1InShared1, - // ) - // - // log.Trace().Msgf("userProfiles %#v", userProfiles) - // c.Assert(len(userProfiles), check.Equals, 2) - // - // found := false - // for _, userProfiles := range userProfiles { - // if userProfiles.DisplayName == namespaceShared1.Name { - // found = true - // - // break - // } - // } - // c.Assert(found, check.Equals, true) - // - // found = false - // for _, userProfile := range userProfiles { - // if userProfile.DisplayName == namespaceShared2.Name { - // found = true - // - // break - // } - // } - // c.Assert(found, check.Equals, true) + userProfiles := getMapResponseUserProfiles( + *machineInShared1, + peersOfMachine1InShared1, + ) + + c.Assert(len(userProfiles), check.Equals, 3) + + found := false + for _, userProfiles := range userProfiles { + if userProfiles.DisplayName == namespaceShared1.Name { + found = true + + break + } + } + c.Assert(found, check.Equals, true) + + found = false + for _, userProfile := range userProfiles { + if userProfile.DisplayName == namespaceShared2.Name { + found = true + + break + } + } + c.Assert(found, check.Equals, true) } From 2c7064462a2a2d129cfae8dd4ec4b9756300ea67 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 25 Feb 2022 10:30:58 +0100 Subject: [PATCH 096/204] Update changelog --- CHANGELOG.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 531137f..d48de9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,13 @@ # CHANGELOG -**TBD (TBD):** +**0.15.0 (2022-xx-xx):** -**0.14.0 (2022-xx-xx):** +**BREAKING**: + +- Boundaries between Namespaces has been removed and all nodes can communicate by default [#357](https://github.com/juanfont/headscale/pull/357) + - To limit access between nodes, use [ACLs](./docs/acls.md). + +**0.14.0 (2022-02-24):** **UPCOMING BREAKING**: From the **next** version (`0.15.0`), all machines will be able to communicate regardless of From 91b50550ee33e46cf1809ffc2e79d6d744e1267c Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 25 Feb 2022 10:34:35 +0100 Subject: [PATCH 097/204] Update readme and glossary to reflect features and goals --- README.md | 86 +++++++++++++++++++++++++++++++----------------- docs/glossary.md | 5 ++- 2 files changed, 59 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index d23a216..fb5d969 100644 --- a/README.md +++ b/README.md @@ -2,44 +2,67 @@ ![ci](https://github.com/juanfont/headscale/actions/workflows/test.yml/badge.svg) -An open source, self-hosted implementation of the Tailscale coordination server. +An open source, self-hosted implementation of the Tailscale control server. Join our [Discord](https://discord.gg/XcQxk2VHjx) server for a chat. -**Note:** Always select the same GitHub tag as the released version you use to ensure you have the correct example configuration and documentation. The `main` branch might contain unreleased changes. +**Note:** Always select the same GitHub tag as the released version you use +to ensure you have the correct example configuration and documentation. +The `main` branch might contain unreleased changes. -## Overview +## What is Tailscale -Tailscale is [a modern VPN](https://tailscale.com/) built on top of [Wireguard](https://www.wireguard.com/). It [works like an overlay network](https://tailscale.com/blog/how-tailscale-works/) between the computers of your networks - using [NAT traversal](https://tailscale.com/blog/how-nat-traversal-works/). +Tailscale is [a modern VPN](https://tailscale.com/) built on top of +[Wireguard](https://www.wireguard.com/). +It [works like an overlay network](https://tailscale.com/blog/how-tailscale-works/) +between the computers of your networks - using +[NAT traversal](https://tailscale.com/blog/how-nat-traversal-works/). -Everything in Tailscale is Open Source, except the GUI clients for proprietary OS (Windows and macOS/iOS), and the 'coordination/control server'. +Everything in Tailscale is Open Source, except the GUI clients for proprietary OS +(Windows and macOS/iOS), and the control server. -The control server works as an exchange point of Wireguard public keys for the nodes in the Tailscale network. It also assigns the IP addresses of the clients, creates the boundaries between each user, enables sharing machines between users, and exposes the advertised routes of your nodes. +The control server works as an exchange point of Wireguard public keys for the +nodes in the Tailscale network. It assigns the IP addresses of the clients, +creates the boundaries between each user, enables sharing machines between users, +and exposes the advertised routes of your nodes. -headscale implements this coordination server. +A [Tailscale network (tailnet)](https://tailscale.com/kb/1136/tailnet/) is private +network which Tailscale assigns to a user in terms of private users or an +organisations. + +## Design goal + +`headscale` aims to implement a self-hosted, open source alternative to the Tailscale +control server. `headscale` has a narrower scope and an instance of `headscale` +implements a _single_ Tailnet, which is typically what a single organisation, or +home/personal setup would use. + +`headscale` uses terms that maps to Tailscale's control server, consult the +[glossary](./docs/glossary.md) for explainations. ## Support -If you like `headscale` and find it useful, there is sponsorship and donation buttons available in the repo. +If you like `headscale` and find it useful, there is a sponsorship and donation +buttons available in the repo. -If you would like to sponsor features, bugs or prioritisation, reach out to one of the maintainers. +If you would like to sponsor features, bugs or prioritisation, reach out to +one of the maintainers. -## Status +## Features -- [x] Base functionality (nodes can communicate with each other) -- [x] Node registration through the web flow -- [x] Network changes are relayed to the nodes -- [x] Namespaces support (~tailnets in Tailscale.com naming) -- [x] Routing (advertise & accept, including exit nodes) -- [x] Node registration via pre-auth keys (including reusable keys, and ephemeral node support) -- [x] JSON-formatted output -- [x] ACLs -- [x] Taildrop (File Sharing) -- [x] Support for alternative IP ranges in the tailnets (default Tailscale's 100.64.0.0/10) -- [x] DNS (passing DNS servers to nodes) -- [x] Single-Sign-On (via Open ID Connect) -- [x] Share nodes between namespaces -- [x] MagicDNS (see `docs/`) +- Full "base" support of Tailscale's features +- Configurable DNS + - [Split DNS](https://tailscale.com/kb/1054/dns/#using-dns-settings-in-the-admin-console) +- Node registration + - Single-Sign-On (via Open ID Connect) + - Pre authenticated key +- Taildrop (File Sharing) +- [Access control lists](https://tailscale.com/kb/1018/acls/) +- [MagicDNS](https://tailscale.com/kb/1081/magicdns) +- Support for multiple IP ranges in the tailnet +- Dual stack (IPv4 and IPv6) +- Routing advertising (including exit nodes) +- Ephemeral nodes ## Client OS support @@ -53,10 +76,6 @@ If you would like to sponsor features, bugs or prioritisation, reach out to one | Android | [You need to compile the client yourself](https://github.com/juanfont/headscale/issues/58#issuecomment-885255270) | | iOS | Not yet | -## Roadmap - -Suggestions/PRs welcomed! - ## Running headscale Please have a look at the documentation under [`docs/`](docs/). @@ -68,11 +87,15 @@ Please have a look at the documentation under [`docs/`](docs/). ## Contributing -To contribute to Headscale you would need the lastest version of [Go](https://golang.org) and [Buf](https://buf.build)(Protobuf generator). +To contribute to headscale you would need the lastest version of [Go](https://golang.org) +and [Buf](https://buf.build)(Protobuf generator). + +PRs and suggestions are welcome. ### Code style -To ensure we have some consistency with a growing number of contributions, this project has adopted linting and style/formatting rules: +To ensure we have some consistency with a growing number of contributions, +this project has adopted linting and style/formatting rules: The **Go** code is linted with [`golangci-lint`](https://golangci-lint.run) and formatted with [`golines`](https://github.com/segmentio/golines) (width 88) and @@ -99,7 +122,8 @@ make install-protobuf-plugins ### Testing and building -Some parts of the project require the generation of Go code from Protobuf (if changes are made in `proto/`) and it must be (re-)generated with: +Some parts of the project require the generation of Go code from Protobuf +(if changes are made in `proto/`) and it must be (re-)generated with: ```shell make generate diff --git a/docs/glossary.md b/docs/glossary.md index aa3e2e3..c38060d 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -1,3 +1,6 @@ # Glossary -- Namespace: Collection of Tailscale nodes that can see each other. In Tailscale.com this is called Tailnet. +| Term | Description | +| --------- | --------------------------------------------------------------------------------------------------------------------- | +| Machine | A machine is a single entity connected to `headscale`, typically an installation of Tailscale. Also known as **Node** | +| Namespace | A namespace is a logical grouping of machines "owned" by the same entity, in Tailscale, this is typically a User | From a9122c3de37e91effc8951b117e87021ed282b4e Mon Sep 17 00:00:00 2001 From: Nico Rey Date: Fri, 25 Feb 2022 18:21:20 -0300 Subject: [PATCH 098/204] prometheus: replace default port by a port between the recommended prometheus range --- cmd/headscale/headscale_test.go | 2 +- config-example.yaml | 2 +- docs/examples/kustomize/base/configmap.yaml | 2 +- integration_test/etc/config.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/headscale/headscale_test.go b/cmd/headscale/headscale_test.go index 2edf2c1..551cf05 100644 --- a/cmd/headscale/headscale_test.go +++ b/cmd/headscale/headscale_test.go @@ -55,7 +55,7 @@ func (*Suite) TestConfigLoading(c *check.C) { // Test that config file was interpreted correctly c.Assert(viper.GetString("server_url"), check.Equals, "http://127.0.0.1:8080") c.Assert(viper.GetString("listen_addr"), check.Equals, "0.0.0.0:8080") - c.Assert(viper.GetString("metrics_listen_addr"), check.Equals, "127.0.0.1:8081") + c.Assert(viper.GetString("metrics_listen_addr"), check.Equals, "127.0.0.1:9915") c.Assert(viper.GetString("db_type"), check.Equals, "sqlite3") c.Assert(viper.GetString("db_path"), check.Equals, "/var/lib/headscale/db.sqlite") c.Assert(viper.GetString("tls_letsencrypt_hostname"), check.Equals, "") diff --git a/config-example.yaml b/config-example.yaml index fb8289f..2053e12 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -20,7 +20,7 @@ listen_addr: 0.0.0.0:8080 # to keep this endpoint private to your internal # network # -metrics_listen_addr: 127.0.0.1:8081 +metrics_listen_addr: 127.0.0.1:9915 # Address to listen for gRPC. # gRPC is used for controlling a headscale server diff --git a/docs/examples/kustomize/base/configmap.yaml b/docs/examples/kustomize/base/configmap.yaml index 5578958..b60c685 100644 --- a/docs/examples/kustomize/base/configmap.yaml +++ b/docs/examples/kustomize/base/configmap.yaml @@ -5,5 +5,5 @@ metadata: data: server_url: $(PUBLIC_PROTO)://$(PUBLIC_HOSTNAME) listen_addr: "0.0.0.0:8080" - metrics_listen_addr: "127.0.0.1:8081" + metrics_listen_addr: "127.0.0.1:9915" ephemeral_node_inactivity_timeout: "30m" diff --git a/integration_test/etc/config.yaml b/integration_test/etc/config.yaml index f1b04b6..223fab2 100644 --- a/integration_test/etc/config.yaml +++ b/integration_test/etc/config.yaml @@ -14,7 +14,7 @@ dns_config: db_path: /tmp/integration_test_db.sqlite3 private_key_path: private.key listen_addr: 0.0.0.0:8080 -metrics_listen_addr: 127.0.0.1:8081 +metrics_listen_addr: 127.0.0.1:9915 server_url: http://headscale:8080 derp: From 06e6c29a5b168731044ab40ca7dd19eb3417e263 Mon Sep 17 00:00:00 2001 From: Nico Rey Date: Fri, 25 Feb 2022 18:36:03 -0300 Subject: [PATCH 099/204] metrics: make metrics endpoint toggleable --- app.go | 39 ++++++++++--------- cmd/headscale/cli/utils.go | 1 + cmd/headscale/headscale_test.go | 1 + config-example.yaml | 3 ++ docs/examples/kustomize/base/configmap.yaml | 1 + .../kustomize/postgres/deployment.yaml | 5 +++ .../kustomize/sqlite/statefulset.yaml | 5 +++ integration_test/etc/config.yaml | 1 + 8 files changed, 38 insertions(+), 18 deletions(-) diff --git a/app.go b/app.go index cf49163..a67031e 100644 --- a/app.go +++ b/app.go @@ -72,6 +72,7 @@ const ( type Config struct { ServerURL string Addr string + MetricsEnabled bool MetricsAddr string GRPCAddr string GRPCAllowInsecure bool @@ -655,27 +656,29 @@ func (h *Headscale) Serve() error { log.Info(). Msgf("listening and serving HTTP on: %s", h.cfg.Addr) - promRouter := h.createPrometheusRouter() + if h.cfg.MetricsEnabled { + promRouter := h.createPrometheusRouter() - promHTTPServer := &http.Server{ - Addr: h.cfg.MetricsAddr, - Handler: promRouter, - ReadTimeout: HTTPReadTimeout, - WriteTimeout: 0, + promHTTPServer := &http.Server{ + Addr: h.cfg.MetricsAddr, + Handler: promRouter, + ReadTimeout: HTTPReadTimeout, + WriteTimeout: 0, + } + + var promHTTPListener net.Listener + promHTTPListener, err = net.Listen("tcp", h.cfg.MetricsAddr) + + if err != nil { + return fmt.Errorf("failed to bind to TCP address: %w", err) + } + + errorGroup.Go(func() error { return promHTTPServer.Serve(promHTTPListener) }) + + log.Info(). + Msgf("listening and serving metrics on: %s", h.cfg.MetricsAddr) } - var promHTTPListener net.Listener - promHTTPListener, err = net.Listen("tcp", h.cfg.MetricsAddr) - - if err != nil { - return fmt.Errorf("failed to bind to TCP address: %w", err) - } - - errorGroup.Go(func() error { return promHTTPServer.Serve(promHTTPListener) }) - - log.Info(). - Msgf("listening and serving metrics on: %s", h.cfg.MetricsAddr) - return errorGroup.Wait() } diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index fa4a0b7..f287cd4 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -303,6 +303,7 @@ func getHeadscaleConfig() headscale.Config { return headscale.Config{ ServerURL: viper.GetString("server_url"), Addr: viper.GetString("listen_addr"), + MetricsEnabled: viper.GetBool("metrics_enabled"), MetricsAddr: viper.GetString("metrics_listen_addr"), GRPCAddr: viper.GetString("grpc_listen_addr"), GRPCAllowInsecure: viper.GetBool("grpc_allow_insecure"), diff --git a/cmd/headscale/headscale_test.go b/cmd/headscale/headscale_test.go index 551cf05..d75e6e6 100644 --- a/cmd/headscale/headscale_test.go +++ b/cmd/headscale/headscale_test.go @@ -56,6 +56,7 @@ func (*Suite) TestConfigLoading(c *check.C) { c.Assert(viper.GetString("server_url"), check.Equals, "http://127.0.0.1:8080") c.Assert(viper.GetString("listen_addr"), check.Equals, "0.0.0.0:8080") c.Assert(viper.GetString("metrics_listen_addr"), check.Equals, "127.0.0.1:9915") + c.Assert(viper.GetString("metrics_enabled"), check.Equals, "true") c.Assert(viper.GetString("db_type"), check.Equals, "sqlite3") c.Assert(viper.GetString("db_path"), check.Equals, "/var/lib/headscale/db.sqlite") c.Assert(viper.GetString("tls_letsencrypt_hostname"), check.Equals, "") diff --git a/config-example.yaml b/config-example.yaml index 2053e12..8b028db 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -16,6 +16,9 @@ server_url: http://127.0.0.1:8080 # listen_addr: 0.0.0.0:8080 +# Enable Prometheus metrics endpoint +metrics_enabled: true + # Address to listen to /metrics, you may want # to keep this endpoint private to your internal # network diff --git a/docs/examples/kustomize/base/configmap.yaml b/docs/examples/kustomize/base/configmap.yaml index b60c685..a8287c6 100644 --- a/docs/examples/kustomize/base/configmap.yaml +++ b/docs/examples/kustomize/base/configmap.yaml @@ -5,5 +5,6 @@ metadata: data: server_url: $(PUBLIC_PROTO)://$(PUBLIC_HOSTNAME) listen_addr: "0.0.0.0:8080" + metrics_enabled: "true" metrics_listen_addr: "127.0.0.1:9915" ephemeral_node_inactivity_timeout: "30m" diff --git a/docs/examples/kustomize/postgres/deployment.yaml b/docs/examples/kustomize/postgres/deployment.yaml index 1dd88b4..3d380ac 100644 --- a/docs/examples/kustomize/postgres/deployment.yaml +++ b/docs/examples/kustomize/postgres/deployment.yaml @@ -30,6 +30,11 @@ spec: configMapKeyRef: name: headscale-config key: metrics_listen_addr + - name: METRICS_ENABLED + valueFrom: + configMapKeyRef: + name: headscale-config + key: metrics_enabled - name: DERP_MAP_PATH value: /vol/config/derp.yaml - name: EPHEMERAL_NODE_INACTIVITY_TIMEOUT diff --git a/docs/examples/kustomize/sqlite/statefulset.yaml b/docs/examples/kustomize/sqlite/statefulset.yaml index 2321d39..5b3b908 100644 --- a/docs/examples/kustomize/sqlite/statefulset.yaml +++ b/docs/examples/kustomize/sqlite/statefulset.yaml @@ -31,6 +31,11 @@ spec: configMapKeyRef: name: headscale-config key: metrics_listen_addr + - name: METRICS_ENABLED + valueFrom: + configMapKeyRef: + name: headscale-config + key: metrics_enabled - name: DERP_MAP_PATH value: /vol/config/derp.yaml - name: EPHEMERAL_NODE_INACTIVITY_TIMEOUT diff --git a/integration_test/etc/config.yaml b/integration_test/etc/config.yaml index 223fab2..128722f 100644 --- a/integration_test/etc/config.yaml +++ b/integration_test/etc/config.yaml @@ -14,6 +14,7 @@ dns_config: db_path: /tmp/integration_test_db.sqlite3 private_key_path: private.key listen_addr: 0.0.0.0:8080 +metrics_enabled: true metrics_listen_addr: 127.0.0.1:9915 server_url: http://headscale:8080 From 67d6c8f9465d52401666b27a5f96aff2bf17b5f9 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 09:04:27 +0100 Subject: [PATCH 100/204] Remove oversensitive tracing output --- utils.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/utils.go b/utils.go index 004bf30..af267eb 100644 --- a/utils.go +++ b/utils.go @@ -196,10 +196,6 @@ func (h *Headscale) getUsedIPs() (*netaddr.IPSet, error) { var addressesSlices []string h.db.Model(&Machine{}).Pluck("ip_addresses", &addressesSlices) - log.Trace(). - Strs("addresses", addressesSlices). - Msg("Got allocated ip addresses from databases") - var ips netaddr.IPSetBuilder for _, slice := range addressesSlices { var machineAddresses MachineAddresses @@ -216,10 +212,6 @@ func (h *Headscale) getUsedIPs() (*netaddr.IPSet, error) { } } - log.Trace(). - Interface("addresses", ips). - Msg("Parsed ip addresses that has been allocated from databases") - ipSet, err := ips.IPSet() if err != nil { return &netaddr.IPSet{}, fmt.Errorf( From 8a3a0b64037bea8c15700943d37a16f02375cf28 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 09:04:48 +0100 Subject: [PATCH 101/204] Add YAML support to ACLs --- acls.go | 40 +++++++++++++++++++++++++++++++--------- acls_types.go | 44 +++++++++++++++++++++++++++++++++----------- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/acls.go b/acls.go index ce14a89..1a597c2 100644 --- a/acls.go +++ b/acls.go @@ -5,11 +5,13 @@ import ( "fmt" "io" "os" + "path/filepath" "strconv" "strings" "github.com/rs/zerolog/log" "github.com/tailscale/hujson" + "gopkg.in/yaml.v3" "inet.af/netaddr" "tailscale.com/tailcfg" ) @@ -53,16 +55,36 @@ func (h *Headscale) LoadACLPolicy(path string) error { return err } - ast, err := hujson.Parse(policyBytes) - if err != nil { - return err - } - ast.Standardize() - policyBytes = ast.Pack() - err = json.Unmarshal(policyBytes, &policy) - if err != nil { - return err + switch filepath.Ext(path) { + case ".yml", ".yaml": + log.Debug(). + Str("path", path). + Bytes("file", policyBytes). + Msg("Loading ACLs from YAML") + + err := yaml.Unmarshal(policyBytes, &policy) + if err != nil { + return err + } + + log.Trace(). + Interface("policy", policy). + Msg("Loaded policy from YAML") + + default: + ast, err := hujson.Parse(policyBytes) + if err != nil { + return err + } + + ast.Standardize() + policyBytes = ast.Pack() + err = json.Unmarshal(policyBytes, &policy) + if err != nil { + return err + } } + if policy.IsZero() { return errEmptyPolicy } diff --git a/acls_types.go b/acls_types.go index 08e650f..fb86982 100644 --- a/acls_types.go +++ b/acls_types.go @@ -5,23 +5,24 @@ import ( "strings" "github.com/tailscale/hujson" + "gopkg.in/yaml.v3" "inet.af/netaddr" ) // ACLPolicy represents a Tailscale ACL Policy. type ACLPolicy struct { - Groups Groups `json:"Groups"` - Hosts Hosts `json:"Hosts"` - TagOwners TagOwners `json:"TagOwners"` - ACLs []ACL `json:"ACLs"` - Tests []ACLTest `json:"Tests"` + Groups Groups `json:"Groups" yaml:"Groups"` + Hosts Hosts `json:"Hosts" yaml:"Hosts"` + TagOwners TagOwners `json:"TagOwners" yaml:"TagOwners"` + ACLs []ACL `json:"ACLs" yaml:"ACLs"` + Tests []ACLTest `json:"Tests" yaml:"Tests"` } // ACL is a basic rule for the ACL Policy. type ACL struct { - Action string `json:"Action"` - Users []string `json:"Users"` - Ports []string `json:"Ports"` + Action string `json:"Action" yaml:"Action"` + Users []string `json:"Users" yaml:"Users"` + Ports []string `json:"Ports" yaml:"Ports"` } // Groups references a series of alias in the ACL rules. @@ -35,9 +36,9 @@ type TagOwners map[string][]string // ACLTest is not implemented, but should be use to check if a certain rule is allowed. type ACLTest struct { - User string `json:"User"` - Allow []string `json:"Allow"` - Deny []string `json:"Deny,omitempty"` + User string `json:"User" yaml:"User"` + Allow []string `json:"Allow" yaml:"Allow"` + Deny []string `json:"Deny,omitempty" yaml:"Deny,omitempty"` } // UnmarshalJSON allows to parse the Hosts directly into netaddr objects. @@ -69,6 +70,27 @@ func (hosts *Hosts) UnmarshalJSON(data []byte) error { return nil } +// UnmarshalYAML allows to parse the Hosts directly into netaddr objects. +func (hosts *Hosts) UnmarshalYAML(data []byte) error { + newHosts := Hosts{} + hostIPPrefixMap := make(map[string]string) + + err := yaml.Unmarshal(data, &hostIPPrefixMap) + if err != nil { + return err + } + for host, prefixStr := range hostIPPrefixMap { + prefix, err := netaddr.ParseIPPrefix(prefixStr) + if err != nil { + return err + } + newHosts[host] = prefix + } + *hosts = newHosts + + return nil +} + // IsZero is perhaps a bit naive here. func (policy ACLPolicy) IsZero() bool { if len(policy.Groups) == 0 && len(policy.Hosts) == 0 && len(policy.ACLs) == 0 { From c159eb7541e18f3ed1c926826d5075a7bf54b5cf Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 09:04:59 +0100 Subject: [PATCH 102/204] Add basic test of yaml parsing --- acls_test.go | 16 ++++++++++++++++ tests/acls/acl_policy_basic_wildcards.yaml | 10 ++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/acls/acl_policy_basic_wildcards.yaml diff --git a/acls_test.go b/acls_test.go index 5534257..9f0432a 100644 --- a/acls_test.go +++ b/acls_test.go @@ -328,6 +328,22 @@ func (s *Suite) TestPortWildcard(c *check.C) { c.Assert(rules[0].SrcIPs[0], check.Equals, "*") } +func (s *Suite) TestPortWildcardYAML(c *check.C) { + err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_wildcards.yaml") + c.Assert(err, check.IsNil) + + rules, err := app.generateACLRules() + c.Assert(err, check.IsNil) + c.Assert(rules, check.NotNil) + + c.Assert(rules, check.HasLen, 1) + c.Assert(rules[0].DstPorts, check.HasLen, 1) + c.Assert(rules[0].DstPorts[0].Ports.First, check.Equals, uint16(0)) + c.Assert(rules[0].DstPorts[0].Ports.Last, check.Equals, uint16(65535)) + c.Assert(rules[0].SrcIPs, check.HasLen, 1) + c.Assert(rules[0].SrcIPs[0], check.Equals, "*") +} + func (s *Suite) TestPortNamespace(c *check.C) { namespace, err := app.CreateNamespace("testnamespace") c.Assert(err, check.IsNil) diff --git a/tests/acls/acl_policy_basic_wildcards.yaml b/tests/acls/acl_policy_basic_wildcards.yaml new file mode 100644 index 0000000..8e7c817 --- /dev/null +++ b/tests/acls/acl_policy_basic_wildcards.yaml @@ -0,0 +1,10 @@ +--- +Hosts: + host-1: 100.100.100.100/32 + subnet-1: 100.100.101.100/24 +ACLs: + - Action: accept + Users: + - "*" + Ports: + - host-1:* From e0b9a317f4c30ad07e275b179b5037d61b8bdc02 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 09:05:08 +0100 Subject: [PATCH 103/204] Add note to config example --- config-example.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config-example.yaml b/config-example.yaml index bac3b0c..e14d1a1 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -132,7 +132,8 @@ tls_key_path: "" log_level: info # Path to a file containg ACL policies. -# Recommended path: /etc/headscale/acl.hujson +# ACLs can be defined as YAML or HUJSON. +# https://tailscale.com/kb/1018/acls/ acl_policy_path: "" ## DNS From d6f6939c54dc0144fa9cc5e6ddf97e45652780ae Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 09:08:29 +0100 Subject: [PATCH 104/204] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d44db56..b2b93ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ - Boundaries between Namespaces has been removed and all nodes can communicate by default [#357](https://github.com/juanfont/headscale/pull/357) - To limit access between nodes, use [ACLs](./docs/acls.md). +**Features**: + +- Add support for writing ACL files with YAML [#359](https://github.com/juanfont/headscale/pull/359) + **Changes**: - Fix a bug were the same IP could be assigned to multiple hosts if joined in quick succession [#346](https://github.com/juanfont/headscale/pull/346) From c58ce6f60cd0e85750228acc30f24a3dda93b619 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 18:40:10 +0100 Subject: [PATCH 105/204] Generalise the registration method to DRY stuff up --- cli_test.go | 2 ++ machine.go | 75 ++++++++++++++++++++++++++++------------------------- 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/cli_test.go b/cli_test.go index 71f2bea..2eedb5b 100644 --- a/cli_test.go +++ b/cli_test.go @@ -32,6 +32,8 @@ func (s *Suite) TestRegisterMachine(c *check.C) { machineAfterRegistering, err := app.RegisterMachine( machine.MachineKey, namespace.Name, + RegisterMethodCLI, + nil, nil, nil, nil, ) c.Assert(err, check.IsNil) c.Assert(machineAfterRegistering.Registered, check.Equals, true) diff --git a/machine.go b/machine.go index dac4459..3415b40 100644 --- a/machine.go +++ b/machine.go @@ -44,8 +44,10 @@ type Machine struct { Registered bool // temp RegisterMethod string - AuthKeyID uint - AuthKey *PreAuthKey + + // TODO(kradalby): This seems like irrelevant information? + AuthKeyID uint + AuthKey *PreAuthKey LastSeen *time.Time LastSuccessfulUpdate *time.Time @@ -686,6 +688,13 @@ func (machine *Machine) toProto() *v1.Machine { func (h *Headscale) RegisterMachine( machineKeyStr string, namespaceName string, + registrationMethod string, + + // Optionals + expiry *time.Time, + authKey *PreAuthKey, + nodePublicKey *string, + lastSeen *time.Time, ) (*Machine, error) { namespace, err := h.GetNamespace(namespaceName) if err != nil { @@ -709,27 +718,13 @@ func (h *Headscale) RegisterMachine( return nil, err } - // TODO(kradalby): Currently, if it fails to find a requested expiry, non will be set - // This means that if a user is to slow with register a machine, it will possibly not - // have the correct expiry. - requestedTime := time.Time{} - if requestedTimeIf, found := h.requestedExpiryCache.Get(machineKey.String()); found { - log.Trace(). - Caller(). - Str("machine", machine.Name). - Msg("Expiry time found in cache, assigning to node") - if reqTime, ok := requestedTimeIf.(time.Time); ok { - requestedTime = reqTime - } - } - if machine.isRegistered() { log.Trace(). Caller(). Str("machine", machine.Name). Msg("machine already registered, reauthenticating") - h.RefreshMachine(machine, requestedTime) + h.RefreshMachine(machine, *expiry) return machine, nil } @@ -739,17 +734,6 @@ func (h *Headscale) RegisterMachine( Str("machine", machine.Name). Msg("Attempting to register machine") - if machine.isRegistered() { - err := errMachineAlreadyRegistered - log.Error(). - Caller(). - Err(err). - Str("machine", machine.Name). - Msg("Attempting to register machine") - - return nil, err - } - h.ipAllocationMutex.Lock() defer h.ipAllocationMutex.Unlock() @@ -764,17 +748,36 @@ func (h *Headscale) RegisterMachine( return nil, err } - log.Trace(). - Caller(). - Str("machine", machine.Name). - Str("ip", strings.Join(ips.ToStringSlice(), ",")). - Msg("Found IP for host") - machine.IPAddresses = ips + + if expiry != nil { + machine.Expiry = expiry + } + + if authKey != nil { + machine.AuthKeyID = uint(authKey.ID) + } + + if nodePublicKey != nil { + machine.NodeKey = *nodePublicKey + } + + if lastSeen != nil { + machine.LastSeen = lastSeen + } + machine.NamespaceID = namespace.ID + + // TODO(kradalby): This field is uneccessary metadata, + // move it to tags instead of having a column. + machine.RegisterMethod = registrationMethod + + // TODO(kradalby): Registered is a very frustrating value + // to keep up to date, and it makes is have to care if a + // machine is registered, authenticated and expired. + // Let us simplify the model, a machine is _only_ saved if + // it is registered. machine.Registered = true - machine.RegisterMethod = RegisterMethodCLI - machine.Expiry = &requestedTime h.db.Save(&machine) log.Trace(). From acb945841c6878c1af6e66522f146265bd7feaa3 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 18:42:15 +0100 Subject: [PATCH 106/204] Generalise registration for pre auth keys --- api.go | 53 +++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/api.go b/api.go index bb5495a..810271c 100644 --- a/api.go +++ b/api.go @@ -22,7 +22,7 @@ import ( const ( reservedResponseHeaderSize = 4 - RegisterMethodAuthKey = "authKey" + RegisterMethodAuthKey = RegisterMethodAuthKey RegisterMethodOIDC = "oidc" RegisterMethodCLI = "cli" ErrRegisterMethodCLIDoesNotSupportExpire = Error( @@ -545,7 +545,7 @@ func (h *Headscale) handleAuthKey( Err(err). Msg("Cannot encode message") ctx.String(http.StatusInternalServerError, "") - machineRegistrations.WithLabelValues("new", "authkey", "error", machine.Namespace.Name). + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", machine.Namespace.Name). Inc() return @@ -556,7 +556,7 @@ func (h *Headscale) handleAuthKey( Str("func", "handleAuthKey"). Str("machine", machine.Name). Msg("Failed authentication via AuthKey") - machineRegistrations.WithLabelValues("new", "authkey", "error", machine.Namespace.Name). + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", machine.Namespace.Name). Inc() return @@ -575,38 +575,31 @@ func (h *Headscale) handleAuthKey( Str("machine", machine.Name). Msg("Authentication key was valid, proceeding to acquire IP addresses") - h.ipAllocationMutex.Lock() + nodeKey := NodePublicKeyStripPrefix(registerRequest.NodeKey) + now := time.Now().UTC() - ips, err := h.getAvailableIPs() + _, err = h.RegisterMachine( + machine.Name, + machine.Namespace.Name, + RegisterMethodAuthKey, + ®isterRequest.Expiry, + pak, + &nodeKey, + &now, + ) if err != nil { log.Error(). Caller(). - Str("func", "handleAuthKey"). - Str("machine", machine.Name). - Msg("Failed to find an available IP address") - machineRegistrations.WithLabelValues("new", "authkey", "error", machine.Namespace.Name). - Inc() + Err(err). + Msg("could not register machine") + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", machine.Namespace.Name).Inc() + ctx.String( + http.StatusInternalServerError, + "could not register machine", + ) return } - log.Info(). - Str("func", "handleAuthKey"). - Str("machine", machine.Name). - Str("ips", strings.Join(ips.ToStringSlice(), ",")). - Msgf("Assigning %s to %s", strings.Join(ips.ToStringSlice(), ","), machine.Name) - - machine.Expiry = ®isterRequest.Expiry - machine.AuthKeyID = uint(pak.ID) - machine.IPAddresses = ips - machine.NamespaceID = pak.NamespaceID - - machine.NodeKey = NodePublicKeyStripPrefix(registerRequest.NodeKey) - // we update it just in case - machine.Registered = true - machine.RegisterMethod = RegisterMethodAuthKey - h.db.Save(&machine) - - h.ipAllocationMutex.Unlock() } pak.Used = true @@ -622,13 +615,13 @@ func (h *Headscale) handleAuthKey( Str("machine", machine.Name). Err(err). Msg("Cannot encode message") - machineRegistrations.WithLabelValues("new", "authkey", "error", machine.Namespace.Name). + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", machine.Namespace.Name). Inc() ctx.String(http.StatusInternalServerError, "Extremely sad!") return } - machineRegistrations.WithLabelValues("new", "authkey", "success", machine.Namespace.Name). + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "success", machine.Namespace.Name). Inc() ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) log.Info(). From fd1e4a1dcd4b08868f70f221eee4f2524a69ffdf Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 18:42:24 +0100 Subject: [PATCH 107/204] Generalise registration for openid --- oidc.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/oidc.go b/oidc.go index edea32a..5207c64 100644 --- a/oidc.go +++ b/oidc.go @@ -328,27 +328,28 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - ips, err := h.getAvailableIPs() + _, err = h.RegisterMachine( + machineKeyStr, + namespace.Name, + RegisterMethodOIDC, + &requestedTime, + nil, + nil, + &now, + ) if err != nil { log.Error(). Caller(). Err(err). - Msg("could not get an IP from the pool") + Msg("could not register machine") ctx.String( http.StatusInternalServerError, - "could not get an IP from the pool", + "could not register machine", ) return } - machine.IPAddresses = ips - machine.NamespaceID = namespace.ID - machine.Registered = true - machine.RegisterMethod = RegisterMethodOIDC - machine.LastSuccessfulUpdate = &now - machine.Expiry = &requestedTime - h.db.Save(&machine) } var content bytes.Buffer From caffbd8956776e97e54bbeb6b18ea30a4c287b40 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 18:42:43 +0100 Subject: [PATCH 108/204] Update cli registration with new method --- grpcv1.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/grpcv1.go b/grpcv1.go index 60e181d..b1396bc 100644 --- a/grpcv1.go +++ b/grpcv1.go @@ -159,9 +159,27 @@ func (api headscaleV1APIServer) RegisterMachine( Str("namespace", request.GetNamespace()). Str("machine_key", request.GetKey()). Msg("Registering machine") + + // TODO(kradalby): Currently, if it fails to find a requested expiry, non will be set + // This means that if a user is to slow with register a machine, it will possibly not + // have the correct expiry. + requestedTime := time.Time{} + if requestedTimeIf, found := api.h.requestedExpiryCache.Get(request.GetKey()); found { + log.Trace(). + Caller(). + Str("machine", request.Key). + Msg("Expiry time found in cache, assigning to node") + if reqTime, ok := requestedTimeIf.(time.Time); ok { + requestedTime = reqTime + } + } + machine, err := api.h.RegisterMachine( request.GetKey(), request.GetNamespace(), + RegisterMethodCLI, + &requestedTime, + nil, nil, nil, ) if err != nil { return nil, err From ecc26432fd64c19d3b314536fcfee634d53e3517 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 18:48:12 +0100 Subject: [PATCH 109/204] Fix excessive replace --- api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.go b/api.go index 810271c..7d53532 100644 --- a/api.go +++ b/api.go @@ -22,7 +22,7 @@ import ( const ( reservedResponseHeaderSize = 4 - RegisterMethodAuthKey = RegisterMethodAuthKey + RegisterMethodAuthKey = "authkey" RegisterMethodOIDC = "oidc" RegisterMethodCLI = "cli" ErrRegisterMethodCLIDoesNotSupportExpire = Error( From 1caa6f5d6915b762cad4c9d5b28654ae0d2efe67 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 27 Feb 2022 18:48:25 +0100 Subject: [PATCH 110/204] Add todo for JSON datatype --- machine.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/machine.go b/machine.go index 3415b40..b805de6 100644 --- a/machine.go +++ b/machine.go @@ -53,6 +53,8 @@ type Machine struct { LastSuccessfulUpdate *time.Time Expiry *time.Time + // TODO(kradalby): Figure out a way to use tailcfg datatypes + // here and have gorm serialise them. HostInfo datatypes.JSON Endpoints datatypes.JSON EnabledRoutes datatypes.JSON From 469551bc5df6dd8483af1246560f2f358a2ed943 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 08:06:39 +0000 Subject: [PATCH 111/204] Register new machines needing callback in memory This commit stores temporary registration data in cache, instead of memory allowing us to only have actually registered machines in the database. --- api.go | 153 +++++++++++++++++++++++------------------------- app.go | 9 +++ cli_test.go | 1 + grpcv1.go | 3 +- machine.go | 52 +++++++++++++--- oidc.go | 7 +-- preauth_keys.go | 6 ++ 7 files changed, 136 insertions(+), 95 deletions(-) diff --git a/api.go b/api.go index 7d53532..60ca63f 100644 --- a/api.go +++ b/api.go @@ -125,25 +125,40 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { machine, err := h.GetMachineByMachineKey(machineKey) if errors.Is(err, gorm.ErrRecordNotFound) { log.Info().Str("machine", req.Hostinfo.Hostname).Msg("New machine") - newMachine := Machine{ - Expiry: &time.Time{}, - MachineKey: MachinePublicKeyStripPrefix(machineKey), - Name: req.Hostinfo.Hostname, - } - if err := h.db.Create(&newMachine).Error; err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Could not create row") - machineRegistrations.WithLabelValues("unknown", "web", "error", machine.Namespace.Name). - Inc() + + machineKeyStr := MachinePublicKeyStripPrefix(machineKey) + + // If the machine has AuthKey set, handle registration via PreAuthKeys + if req.Auth.AuthKey != "" { + h.handleAuthKey(ctx, machineKey, req) return } - machine = &newMachine + + // The machine did not have a key to authenticate, which means + // that we rely on a method that calls back some how (OpenID or CLI) + // We create the machine and then keep it around until a callback + // happens + newMachine := Machine{ + Expiry: &time.Time{}, + MachineKey: machineKeyStr, + Name: req.Hostinfo.Hostname, + NodeKey: NodePublicKeyStripPrefix(req.NodeKey), + LastSeen: &now, + } + + h.registrationCache.Set( + machineKeyStr, + newMachine, + requestedExpiryCacheExpiration, + ) + + h.handleMachineRegistrationNew(ctx, machineKey, req) + return } - if machine.Registered { + // The machine is already registered, so we need to pass through reauth or key update. + if machine != nil { // If the NodeKey stored in headscale is the same as the key presented in a registration // request, then we have a node that is either: // - Trying to log out (sending a expiry in the past) @@ -180,15 +195,6 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { return } - - // If the machine has AuthKey set, handle registration via PreAuthKeys - if req.Auth.AuthKey != "" { - h.handleAuthKey(ctx, machineKey, req, *machine) - - return - } - - h.handleMachineRegistrationNew(ctx, machineKey, req, *machine) } func (h *Headscale) getMapResponse( @@ -402,7 +408,7 @@ func (h *Headscale) handleMachineExpired( Msg("Machine registration has expired. Sending a authurl to register") if registerRequest.Auth.AuthKey != "" { - h.handleAuthKey(ctx, machineKey, registerRequest, machine) + h.handleAuthKey(ctx, machineKey, registerRequest) return } @@ -465,13 +471,12 @@ func (h *Headscale) handleMachineRegistrationNew( ctx *gin.Context, machineKey key.MachinePublic, registerRequest tailcfg.RegisterRequest, - machine Machine, ) { resp := tailcfg.RegisterResponse{} // The machine registration is new, redirect the client to the registration URL log.Debug(). - Str("machine", machine.Name). + Str("machine", registerRequest.Hostinfo.Hostname). Msg("The node is sending us a new NodeKey, sending auth url") if h.cfg.OIDC.Issuer != "" { resp.AuthURL = fmt.Sprintf( @@ -487,7 +492,7 @@ func (h *Headscale) handleMachineRegistrationNew( if !registerRequest.Expiry.IsZero() { log.Trace(). Caller(). - Str("machine", machine.Name). + Str("machine", registerRequest.Hostinfo.Hostname). Time("expiry", registerRequest.Expiry). Msg("Non-zero expiry time requested, adding to cache") h.requestedExpiryCache.Set( @@ -497,11 +502,6 @@ func (h *Headscale) handleMachineRegistrationNew( ) } - machine.NodeKey = NodePublicKeyStripPrefix(registerRequest.NodeKey) - - // save the NodeKey - h.db.Save(&machine) - respBody, err := encode(resp, &machineKey, h.privateKey) if err != nil { log.Error(). @@ -520,19 +520,21 @@ func (h *Headscale) handleAuthKey( ctx *gin.Context, machineKey key.MachinePublic, registerRequest tailcfg.RegisterRequest, - machine Machine, ) { + machineKeyStr := MachinePublicKeyStripPrefix(machineKey) + log.Debug(). Str("func", "handleAuthKey"). Str("machine", registerRequest.Hostinfo.Hostname). Msgf("Processing auth key for %s", registerRequest.Hostinfo.Hostname) resp := tailcfg.RegisterResponse{} + pak, err := h.checkKeyValidity(registerRequest.Auth.AuthKey) if err != nil { log.Error(). Caller(). Str("func", "handleAuthKey"). - Str("machine", machine.Name). + Str("machine", registerRequest.Hostinfo.Hostname). Err(err). Msg("Failed authentication via AuthKey") resp.MachineAuthorized = false @@ -541,69 +543,62 @@ func (h *Headscale) handleAuthKey( log.Error(). Caller(). Str("func", "handleAuthKey"). - Str("machine", machine.Name). + Str("machine", registerRequest.Hostinfo.Hostname). Err(err). Msg("Cannot encode message") ctx.String(http.StatusInternalServerError, "") - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", machine.Namespace.Name). + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.Namespace.Name). Inc() return } + ctx.Data(http.StatusUnauthorized, "application/json; charset=utf-8", respBody) log.Error(). Caller(). Str("func", "handleAuthKey"). - Str("machine", machine.Name). + Str("machine", registerRequest.Hostinfo.Hostname). Msg("Failed authentication via AuthKey") - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", machine.Namespace.Name). + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.Namespace.Name). Inc() return } - if machine.isRegistered() { - log.Trace(). + log.Debug(). + Str("func", "handleAuthKey"). + Str("machine", registerRequest.Hostinfo.Hostname). + Msg("Authentication key was valid, proceeding to acquire IP addresses") + + nodeKey := NodePublicKeyStripPrefix(registerRequest.NodeKey) + now := time.Now().UTC() + + machine, err := h.RegisterMachine( + registerRequest.Hostinfo.Hostname, + machineKeyStr, + pak.Namespace.Name, + RegisterMethodAuthKey, + ®isterRequest.Expiry, + pak, + &nodeKey, + &now, + ) + if err != nil { + log.Error(). Caller(). - Str("machine", machine.Name). - Msg("machine already registered, reauthenticating") - - h.RefreshMachine(&machine, registerRequest.Expiry) - } else { - log.Debug(). - Str("func", "handleAuthKey"). - Str("machine", machine.Name). - Msg("Authentication key was valid, proceeding to acquire IP addresses") - - nodeKey := NodePublicKeyStripPrefix(registerRequest.NodeKey) - now := time.Now().UTC() - - _, err = h.RegisterMachine( - machine.Name, - machine.Namespace.Name, - RegisterMethodAuthKey, - ®isterRequest.Expiry, - pak, - &nodeKey, - &now, + Err(err). + Msg("could not register machine") + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.Namespace.Name). + Inc() + ctx.String( + http.StatusInternalServerError, + "could not register machine", ) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("could not register machine") - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", machine.Namespace.Name).Inc() - ctx.String( - http.StatusInternalServerError, - "could not register machine", - ) - return - } + return } - pak.Used = true - h.db.Save(&pak) + h.UsePreAuthKey(pak) resp.MachineAuthorized = true resp.User = *pak.Namespace.toUser() @@ -612,21 +607,21 @@ func (h *Headscale) handleAuthKey( log.Error(). Caller(). Str("func", "handleAuthKey"). - Str("machine", machine.Name). + Str("machine", registerRequest.Hostinfo.Hostname). Err(err). Msg("Cannot encode message") - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", machine.Namespace.Name). + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "error", pak.Namespace.Name). Inc() ctx.String(http.StatusInternalServerError, "Extremely sad!") return } - machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "success", machine.Namespace.Name). + machineRegistrations.WithLabelValues("new", RegisterMethodAuthKey, "success", pak.Namespace.Name). Inc() ctx.Data(http.StatusOK, "application/json; charset=utf-8", respBody) log.Info(). Str("func", "handleAuthKey"). - Str("machine", machine.Name). + Str("machine", registerRequest.Hostinfo.Hostname). Str("ips", strings.Join(machine.IPAddresses.ToStringSlice(), ", ")). Msg("Successfully authenticated via AuthKey") } diff --git a/app.go b/app.go index eda670e..63ca10e 100644 --- a/app.go +++ b/app.go @@ -154,6 +154,8 @@ type Headscale struct { requestedExpiryCache *cache.Cache + registrationCache *cache.Cache + ipAllocationMutex sync.Mutex } @@ -207,6 +209,12 @@ func NewHeadscale(cfg Config) (*Headscale, error) { requestedExpiryCacheCleanupInterval, ) + registrationCache := cache.New( + // TODO(kradalby): Add unified cache expiry config options + requestedExpiryCacheExpiration, + requestedExpiryCacheCleanupInterval, + ) + app := Headscale{ cfg: cfg, dbType: cfg.DBtype, @@ -214,6 +222,7 @@ func NewHeadscale(cfg Config) (*Headscale, error) { privateKey: privKey, aclRules: tailcfg.FilterAllowAll, // default allowall requestedExpiryCache: requestedExpiryCache, + registrationCache: registrationCache, } err = app.initDB() diff --git a/cli_test.go b/cli_test.go index 2eedb5b..fab8201 100644 --- a/cli_test.go +++ b/cli_test.go @@ -30,6 +30,7 @@ func (s *Suite) TestRegisterMachine(c *check.C) { c.Assert(err, check.IsNil) machineAfterRegistering, err := app.RegisterMachine( + "testmachine", machine.MachineKey, namespace.Name, RegisterMethodCLI, diff --git a/grpcv1.go b/grpcv1.go index b1396bc..3a2e19c 100644 --- a/grpcv1.go +++ b/grpcv1.go @@ -174,12 +174,11 @@ func (api headscaleV1APIServer) RegisterMachine( } } - machine, err := api.h.RegisterMachine( + machine, err := api.h.RegisterMachineFromAuthCallback( request.GetKey(), request.GetNamespace(), RegisterMethodCLI, &requestedTime, - nil, nil, nil, ) if err != nil { return nil, err diff --git a/machine.go b/machine.go index b805de6..7425155 100644 --- a/machine.go +++ b/machine.go @@ -20,11 +20,15 @@ import ( ) const ( - errMachineNotFound = Error("machine not found") - errMachineAlreadyRegistered = Error("machine already registered") - errMachineRouteIsNotAvailable = Error("route is not available on machine") - errMachineAddressesInvalid = Error("failed to parse machine addresses") - errHostnameTooLong = Error("Hostname too long") + errMachineNotFound = Error("machine not found") + errMachineAlreadyRegistered = Error("machine already registered") + errMachineRouteIsNotAvailable = Error("route is not available on machine") + errMachineAddressesInvalid = Error("failed to parse machine addresses") + errMachineNotFoundRegistrationCache = Error( + "machine not found in registration cache", + ) + errCouldNotConvertMachineInterface = Error("failed to convert machine interface") + errHostnameTooLong = Error("Hostname too long") ) const ( @@ -686,14 +690,44 @@ func (machine *Machine) toProto() *v1.Machine { return machineProto } -// RegisterMachine is executed from the CLI to register a new Machine using its MachineKey. -func (h *Headscale) RegisterMachine( +func (h *Headscale) RegisterMachineFromAuthCallback( machineKeyStr string, namespaceName string, registrationMethod string, + expiry *time.Time, +) (*Machine, error) { + if machineInterface, ok := h.registrationCache.Get(machineKeyStr); ok { + if registrationMachine, ok := machineInterface.(Machine); ok { + machine, err := h.RegisterMachine( + registrationMachine.Name, + machineKeyStr, + namespaceName, + registrationMethod, + expiry, + nil, + ®istrationMachine.NodeKey, + registrationMachine.LastSeen, + ) + + return machine, err + + } else { + return nil, errCouldNotConvertMachineInterface + } + } + + return nil, errMachineNotFoundRegistrationCache +} + +// RegisterMachine is executed from the CLI to register a new Machine using its MachineKey. +func (h *Headscale) RegisterMachine( + machineName string, + machineKeyStr string, + namespaceName string, + registrationMethod string, + expiry *time.Time, // Optionals - expiry *time.Time, authKey *PreAuthKey, nodePublicKey *string, lastSeen *time.Time, @@ -768,6 +802,7 @@ func (h *Headscale) RegisterMachine( machine.LastSeen = lastSeen } + machine.Name = machineName machine.NamespaceID = namespace.ID // TODO(kradalby): This field is uneccessary metadata, @@ -780,6 +815,7 @@ func (h *Headscale) RegisterMachine( // Let us simplify the model, a machine is _only_ saved if // it is registered. machine.Registered = true + h.db.Save(&machine) log.Trace(). diff --git a/oidc.go b/oidc.go index 5207c64..48664ae 100644 --- a/oidc.go +++ b/oidc.go @@ -279,8 +279,6 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - now := time.Now().UTC() - namespaceName, err := NormalizeNamespaceName( claims.Email, h.cfg.OIDC.StripEmaildomain, @@ -328,14 +326,11 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - _, err = h.RegisterMachine( + _, err = h.RegisterMachineFromAuthCallback( machineKeyStr, namespace.Name, RegisterMethodOIDC, &requestedTime, - nil, - nil, - &now, ) if err != nil { log.Error(). diff --git a/preauth_keys.go b/preauth_keys.go index 50bc474..55f6222 100644 --- a/preauth_keys.go +++ b/preauth_keys.go @@ -113,6 +113,12 @@ func (h *Headscale) ExpirePreAuthKey(k *PreAuthKey) error { return nil } +// UsePreAuthKey marks a PreAuthKey as used. +func (h *Headscale) UsePreAuthKey(k *PreAuthKey) { + k.Used = true + h.db.Save(k) +} + // checkKeyValidity does the heavy lifting for validation of the PreAuthKey coming from a node // If returns no error and a PreAuthKey, it can be used. func (h *Headscale) checkKeyValidity(k string) (*PreAuthKey, error) { From 9a61725e9fc1f6e99ef188f391b765ecb9d3151b Mon Sep 17 00:00:00 2001 From: Nico Rey Date: Mon, 28 Feb 2022 10:40:02 -0300 Subject: [PATCH 112/204] Metrics: Disable toggle. Set default port to 9090 --- app.go | 39 +++++++++---------- cmd/headscale/cli/utils.go | 1 - cmd/headscale/headscale_test.go | 3 +- config-example.yaml | 5 +-- docs/examples/kustomize/base/configmap.yaml | 3 +- .../kustomize/postgres/deployment.yaml | 5 --- .../kustomize/sqlite/statefulset.yaml | 5 --- integration_test/etc/config.yaml | 3 +- 8 files changed, 22 insertions(+), 42 deletions(-) diff --git a/app.go b/app.go index f8b18fb..01fe730 100644 --- a/app.go +++ b/app.go @@ -72,7 +72,6 @@ const ( type Config struct { ServerURL string Addr string - MetricsEnabled bool MetricsAddr string GRPCAddr string GRPCAllowInsecure bool @@ -658,29 +657,27 @@ func (h *Headscale) Serve() error { log.Info(). Msgf("listening and serving HTTP on: %s", h.cfg.Addr) - if h.cfg.MetricsEnabled { - promRouter := h.createPrometheusRouter() + promRouter := h.createPrometheusRouter() - promHTTPServer := &http.Server{ - Addr: h.cfg.MetricsAddr, - Handler: promRouter, - ReadTimeout: HTTPReadTimeout, - WriteTimeout: 0, - } - - var promHTTPListener net.Listener - promHTTPListener, err = net.Listen("tcp", h.cfg.MetricsAddr) - - if err != nil { - return fmt.Errorf("failed to bind to TCP address: %w", err) - } - - errorGroup.Go(func() error { return promHTTPServer.Serve(promHTTPListener) }) - - log.Info(). - Msgf("listening and serving metrics on: %s", h.cfg.MetricsAddr) + promHTTPServer := &http.Server{ + Addr: h.cfg.MetricsAddr, + Handler: promRouter, + ReadTimeout: HTTPReadTimeout, + WriteTimeout: 0, } + var promHTTPListener net.Listener + promHTTPListener, err = net.Listen("tcp", h.cfg.MetricsAddr) + + if err != nil { + return fmt.Errorf("failed to bind to TCP address: %w", err) + } + + errorGroup.Go(func() error { return promHTTPServer.Serve(promHTTPListener) }) + + log.Info(). + Msgf("listening and serving metrics on: %s", h.cfg.MetricsAddr) + return errorGroup.Wait() } diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 381f180..49fc23c 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -304,7 +304,6 @@ func getHeadscaleConfig() headscale.Config { return headscale.Config{ ServerURL: viper.GetString("server_url"), Addr: viper.GetString("listen_addr"), - MetricsEnabled: viper.GetBool("metrics_enabled"), MetricsAddr: viper.GetString("metrics_listen_addr"), GRPCAddr: viper.GetString("grpc_listen_addr"), GRPCAllowInsecure: viper.GetBool("grpc_allow_insecure"), diff --git a/cmd/headscale/headscale_test.go b/cmd/headscale/headscale_test.go index d75e6e6..c971220 100644 --- a/cmd/headscale/headscale_test.go +++ b/cmd/headscale/headscale_test.go @@ -55,8 +55,7 @@ func (*Suite) TestConfigLoading(c *check.C) { // Test that config file was interpreted correctly c.Assert(viper.GetString("server_url"), check.Equals, "http://127.0.0.1:8080") c.Assert(viper.GetString("listen_addr"), check.Equals, "0.0.0.0:8080") - c.Assert(viper.GetString("metrics_listen_addr"), check.Equals, "127.0.0.1:9915") - c.Assert(viper.GetString("metrics_enabled"), check.Equals, "true") + c.Assert(viper.GetString("metrics_listen_addr"), check.Equals, "127.0.0.1:9090") c.Assert(viper.GetString("db_type"), check.Equals, "sqlite3") c.Assert(viper.GetString("db_path"), check.Equals, "/var/lib/headscale/db.sqlite") c.Assert(viper.GetString("tls_letsencrypt_hostname"), check.Equals, "") diff --git a/config-example.yaml b/config-example.yaml index 157805e..0939d6c 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -16,14 +16,11 @@ server_url: http://127.0.0.1:8080 # listen_addr: 0.0.0.0:8080 -# Enable Prometheus metrics endpoint -metrics_enabled: true - # Address to listen to /metrics, you may want # to keep this endpoint private to your internal # network # -metrics_listen_addr: 127.0.0.1:9915 +metrics_listen_addr: 127.0.0.1:9090 # Address to listen for gRPC. # gRPC is used for controlling a headscale server diff --git a/docs/examples/kustomize/base/configmap.yaml b/docs/examples/kustomize/base/configmap.yaml index a8287c6..0ac2d56 100644 --- a/docs/examples/kustomize/base/configmap.yaml +++ b/docs/examples/kustomize/base/configmap.yaml @@ -5,6 +5,5 @@ metadata: data: server_url: $(PUBLIC_PROTO)://$(PUBLIC_HOSTNAME) listen_addr: "0.0.0.0:8080" - metrics_enabled: "true" - metrics_listen_addr: "127.0.0.1:9915" + metrics_listen_addr: "127.0.0.1:9090" ephemeral_node_inactivity_timeout: "30m" diff --git a/docs/examples/kustomize/postgres/deployment.yaml b/docs/examples/kustomize/postgres/deployment.yaml index 3d380ac..1dd88b4 100644 --- a/docs/examples/kustomize/postgres/deployment.yaml +++ b/docs/examples/kustomize/postgres/deployment.yaml @@ -30,11 +30,6 @@ spec: configMapKeyRef: name: headscale-config key: metrics_listen_addr - - name: METRICS_ENABLED - valueFrom: - configMapKeyRef: - name: headscale-config - key: metrics_enabled - name: DERP_MAP_PATH value: /vol/config/derp.yaml - name: EPHEMERAL_NODE_INACTIVITY_TIMEOUT diff --git a/docs/examples/kustomize/sqlite/statefulset.yaml b/docs/examples/kustomize/sqlite/statefulset.yaml index 5b3b908..2321d39 100644 --- a/docs/examples/kustomize/sqlite/statefulset.yaml +++ b/docs/examples/kustomize/sqlite/statefulset.yaml @@ -31,11 +31,6 @@ spec: configMapKeyRef: name: headscale-config key: metrics_listen_addr - - name: METRICS_ENABLED - valueFrom: - configMapKeyRef: - name: headscale-config - key: metrics_enabled - name: DERP_MAP_PATH value: /vol/config/derp.yaml - name: EPHEMERAL_NODE_INACTIVITY_TIMEOUT diff --git a/integration_test/etc/config.yaml b/integration_test/etc/config.yaml index 128722f..f055b4c 100644 --- a/integration_test/etc/config.yaml +++ b/integration_test/etc/config.yaml @@ -14,8 +14,7 @@ dns_config: db_path: /tmp/integration_test_db.sqlite3 private_key_path: private.key listen_addr: 0.0.0.0:8080 -metrics_enabled: true -metrics_listen_addr: 127.0.0.1:9915 +metrics_listen_addr: 127.0.0.1:9090 server_url: http://headscale:8080 derp: From 402a76070f501bf490dd75391b72ef1743db66e8 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 16:34:28 +0000 Subject: [PATCH 113/204] Reuse machine structure for parameters, named parameters --- machine.go | 89 +++++++++++++++++------------------------------------- 1 file changed, 27 insertions(+), 62 deletions(-) diff --git a/machine.go b/machine.go index 7425155..6e5b62d 100644 --- a/machine.go +++ b/machine.go @@ -21,7 +21,6 @@ import ( const ( errMachineNotFound = Error("machine not found") - errMachineAlreadyRegistered = Error("machine already registered") errMachineRouteIsNotAvailable = Error("route is not available on machine") errMachineAddressesInvalid = Error("failed to parse machine addresses") errMachineNotFoundRegistrationCache = Error( @@ -698,19 +697,23 @@ func (h *Headscale) RegisterMachineFromAuthCallback( ) (*Machine, error) { if machineInterface, ok := h.registrationCache.Get(machineKeyStr); ok { if registrationMachine, ok := machineInterface.(Machine); ok { + namespace, err := h.GetNamespace(namespaceName) + if err != nil { + return nil, fmt.Errorf( + "failed to find namespace in register machine from auth callback, %w", + err, + ) + } + + registrationMachine.NamespaceID = namespace.ID + registrationMachine.RegisterMethod = registrationMethod + registrationMachine.Expiry = expiry + machine, err := h.RegisterMachine( - registrationMachine.Name, - machineKeyStr, - namespaceName, - registrationMethod, - expiry, - nil, - ®istrationMachine.NodeKey, - registrationMachine.LastSeen, + registrationMachine, ) return machine, err - } else { return nil, errCouldNotConvertMachineInterface } @@ -720,49 +723,30 @@ func (h *Headscale) RegisterMachineFromAuthCallback( } // RegisterMachine is executed from the CLI to register a new Machine using its MachineKey. -func (h *Headscale) RegisterMachine( - machineName string, - machineKeyStr string, - namespaceName string, - registrationMethod string, - expiry *time.Time, - - // Optionals - authKey *PreAuthKey, - nodePublicKey *string, - lastSeen *time.Time, +func (h *Headscale) RegisterMachine(machine Machine, ) (*Machine, error) { - namespace, err := h.GetNamespace(namespaceName) - if err != nil { - return nil, err - } - - var machineKey key.MachinePublic - err = machineKey.UnmarshalText([]byte(MachinePublicKeyEnsurePrefix(machineKeyStr))) - if err != nil { - return nil, err - } - log.Trace(). Caller(). - Str("machine_key_str", machineKeyStr). - Str("machine_key", machineKey.String()). + Str("machine_key", machine.MachineKey). Msg("Registering machine") - machine, err := h.GetMachineByMachineKey(machineKey) - if err != nil { - return nil, err - } - + // If the machine is already in the database, it is seeking + // reauthentication, and by reaching this step, has been authenticated + // and need to have an updated expiry. + var machineKey key.MachinePublic + _ = machineKey.UnmarshalText( + []byte(MachinePublicKeyEnsurePrefix(machine.MachineKey)), + ) + machineFromDatabase, _ := h.GetMachineByMachineKey(machineKey) if machine.isRegistered() { log.Trace(). Caller(). Str("machine", machine.Name). Msg("machine already registered, reauthenticating") - h.RefreshMachine(machine, *expiry) + h.RefreshMachine(machineFromDatabase, *machine.Expiry) - return machine, nil + return machineFromDatabase, nil } log.Trace(). @@ -786,28 +770,9 @@ func (h *Headscale) RegisterMachine( machine.IPAddresses = ips - if expiry != nil { - machine.Expiry = expiry - } - - if authKey != nil { - machine.AuthKeyID = uint(authKey.ID) - } - - if nodePublicKey != nil { - machine.NodeKey = *nodePublicKey - } - - if lastSeen != nil { - machine.LastSeen = lastSeen - } - - machine.Name = machineName - machine.NamespaceID = namespace.ID - // TODO(kradalby): This field is uneccessary metadata, // move it to tags instead of having a column. - machine.RegisterMethod = registrationMethod + // machine.RegisterMethod = registrationMethod // TODO(kradalby): Registered is a very frustrating value // to keep up to date, and it makes is have to care if a @@ -824,7 +789,7 @@ func (h *Headscale) RegisterMachine( Str("ip", strings.Join(ips.ToStringSlice(), ",")). Msg("Machine registered with the database") - return machine, nil + return &machine, nil } func (machine *Machine) GetAdvertisedRoutes() ([]netaddr.IPPrefix, error) { From 54cc3c067ffabf2cae5339a615598ab82feb02fd Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 16:34:50 +0000 Subject: [PATCH 114/204] Implement new machine register parameter --- api.go | 21 +++++++++++++-------- grpcv1.go | 10 +++++----- oidc.go | 1 - 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/api.go b/api.go index 60ca63f..f831cac 100644 --- a/api.go +++ b/api.go @@ -154,6 +154,7 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { ) h.handleMachineRegistrationNew(ctx, machineKey, req) + return } @@ -573,15 +574,19 @@ func (h *Headscale) handleAuthKey( nodeKey := NodePublicKeyStripPrefix(registerRequest.NodeKey) now := time.Now().UTC() + machineToRegister := Machine{ + Name: registerRequest.Hostinfo.Hostname, + NamespaceID: pak.Namespace.ID, + MachineKey: machineKeyStr, + RegisterMethod: RegisterMethodAuthKey, + Expiry: ®isterRequest.Expiry, + NodeKey: nodeKey, + LastSeen: &now, + AuthKeyID: uint(pak.ID), + } + machine, err := h.RegisterMachine( - registerRequest.Hostinfo.Hostname, - machineKeyStr, - pak.Namespace.Name, - RegisterMethodAuthKey, - ®isterRequest.Expiry, - pak, - &nodeKey, - &now, + machineToRegister, ) if err != nil { log.Error(). diff --git a/grpcv1.go b/grpcv1.go index 3a2e19c..75732b1 100644 --- a/grpcv1.go +++ b/grpcv1.go @@ -415,11 +415,11 @@ func (api headscaleV1APIServer) DebugCreateMachine( HostInfo: datatypes.JSON(hostinfoJson), } - // log.Trace().Caller().Interface("machine", newMachine).Msg("") - - if err := api.h.db.Create(&newMachine).Error; err != nil { - return nil, err - } + api.h.registrationCache.Set( + request.GetKey(), + newMachine, + requestedExpiryCacheExpiration, + ) return &v1.DebugCreateMachineResponse{Machine: newMachine.toProto()}, nil } diff --git a/oidc.go b/oidc.go index 48664ae..952e260 100644 --- a/oidc.go +++ b/oidc.go @@ -344,7 +344,6 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - } var content bytes.Buffer From 50053e616a42109b22a1aa15cba56461c04035eb Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 16:35:08 +0000 Subject: [PATCH 115/204] Ignore complexity linter --- .golangci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.golangci.yaml b/.golangci.yaml index 153cd7c..56fdc28 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -29,6 +29,7 @@ linters: - wrapcheck - dupl - makezero + - maintidx # We might want to enable this, but it might be a lot of work - cyclop From c6b87de95901193b7a72494832fdfc94456dceae Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 16:36:16 +0000 Subject: [PATCH 116/204] Remove poorly aged test --- cli_test.go | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 cli_test.go diff --git a/cli_test.go b/cli_test.go deleted file mode 100644 index fab8201..0000000 --- a/cli_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package headscale - -import ( - "time" - - "gopkg.in/check.v1" - "inet.af/netaddr" -) - -func (s *Suite) TestRegisterMachine(c *check.C) { - namespace, err := app.CreateNamespace("test") - c.Assert(err, check.IsNil) - - now := time.Now().UTC() - - machine := Machine{ - ID: 0, - MachineKey: "8ce002a935f8c394e55e78fbbb410576575ff8ec5cfa2e627e4b807f1be15b0e", - NodeKey: "bar", - DiscoKey: "faa", - Name: "testmachine", - NamespaceID: namespace.ID, - IPAddresses: []netaddr.IP{netaddr.MustParseIP("10.0.0.1")}, - Expiry: &now, - } - err = app.db.Save(&machine).Error - c.Assert(err, check.IsNil) - - _, err = app.GetMachine(namespace.Name, machine.Name) - c.Assert(err, check.IsNil) - - machineAfterRegistering, err := app.RegisterMachine( - "testmachine", - machine.MachineKey, - namespace.Name, - RegisterMethodCLI, - nil, nil, nil, nil, - ) - c.Assert(err, check.IsNil) - c.Assert(machineAfterRegistering.Registered, check.Equals, true) - - _, err = machineAfterRegistering.GetHostInfo() - c.Assert(err, check.IsNil) -} From e7bef567184622a7e5374023ae5238e2fccd00ed Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 16:36:29 +0000 Subject: [PATCH 117/204] Remove reference to registered in integration test --- integration_cli_test.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/integration_cli_test.go b/integration_cli_test.go index aae80cb..7ce0758 100644 --- a/integration_cli_test.go +++ b/integration_cli_test.go @@ -621,12 +621,6 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { assert.Equal(s.T(), "machine-4", listAll[3].Name) assert.Equal(s.T(), "machine-5", listAll[4].Name) - assert.True(s.T(), listAll[0].Registered) - assert.True(s.T(), listAll[1].Registered) - assert.True(s.T(), listAll[2].Registered) - assert.True(s.T(), listAll[3].Registered) - assert.True(s.T(), listAll[4].Registered) - otherNamespaceMachineKeys := []string{ "b5b444774186d4217adcec407563a1223929465ee2c68a4da13af0d0185b4f8e", "dc721977ac7415aafa87f7d4574cbe07c6b171834a6d37375782bdc1fb6b3584", @@ -710,9 +704,6 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { assert.Equal(s.T(), "otherNamespace-machine-1", listAllWithotherNamespace[5].Name) assert.Equal(s.T(), "otherNamespace-machine-2", listAllWithotherNamespace[6].Name) - assert.True(s.T(), listAllWithotherNamespace[5].Registered) - assert.True(s.T(), listAllWithotherNamespace[6].Registered) - // Test list all nodes after added otherNamespace listOnlyotherNamespaceMachineNamespaceResult, err := ExecuteCommand( &s.headscale, @@ -752,9 +743,6 @@ func (s *IntegrationCLITestSuite) TestNodeCommand() { listOnlyotherNamespaceMachineNamespace[1].Name, ) - assert.True(s.T(), listOnlyotherNamespaceMachineNamespace[0].Registered) - assert.True(s.T(), listOnlyotherNamespaceMachineNamespace[1].Registered) - // Delete a machines _, err = ExecuteCommand( &s.headscale, @@ -979,7 +967,6 @@ func (s *IntegrationCLITestSuite) TestRouteCommand() { assert.Equal(s.T(), uint64(1), machine.Id) assert.Equal(s.T(), "route-machine", machine.Name) - assert.True(s.T(), machine.Registered) listAllResult, err := ExecuteCommand( &s.headscale, From 35616eb8611ab7514e45ab3a7eb01a5abe0c52f3 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 16:41:28 +0000 Subject: [PATCH 118/204] Fix oidc error were namespace isnt created #365 --- oidc.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/oidc.go b/oidc.go index 952e260..f291e8c 100644 --- a/oidc.go +++ b/oidc.go @@ -17,7 +17,6 @@ import ( "github.com/patrickmn/go-cache" "github.com/rs/zerolog/log" "golang.org/x/oauth2" - "gorm.io/gorm" "tailscale.com/types/key" ) @@ -297,7 +296,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { log.Debug().Msg("Registering new machine after successful callback") namespace, err := h.GetNamespace(namespaceName) - if errors.Is(err, gorm.ErrRecordNotFound) { + if errors.Is(err, errNamespaceNotFound) { namespace, err = h.CreateNamespace(namespaceName) if err != nil { From 16b21e8158d7a32d1ed1b093f05268a633a5bd17 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 16:55:57 +0000 Subject: [PATCH 119/204] Remove all references to Machine.Registered --- machine.go | 24 +++------------- oidc.go | 81 +++++++++++++++++++++++++++--------------------------- 2 files changed, 44 insertions(+), 61 deletions(-) diff --git a/machine.go b/machine.go index 6e5b62d..16d6d86 100644 --- a/machine.go +++ b/machine.go @@ -72,11 +72,6 @@ type ( MachinesP []*Machine ) -// For the time being this method is rather naive. -func (machine Machine) isRegistered() bool { - return machine.Registered -} - type MachineAddresses []netaddr.IP func (ma MachineAddresses) ToStringSlice() []string { @@ -221,7 +216,7 @@ func (h *Headscale) ListPeers(machine *Machine) (Machines, error) { Msg("Finding direct peers") machines := Machines{} - if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Where("machine_key <> ? AND registered", + if err := h.db.Preload("AuthKey").Preload("AuthKey.Namespace").Preload("Namespace").Where("machine_key <> ?", machine.MachineKey).Find(&machines).Error; err != nil { log.Error().Err(err).Msg("Error accessing db") @@ -284,7 +279,7 @@ func (h *Headscale) getValidPeers(machine *Machine) (Machines, error) { } for _, peer := range peers { - if peer.isRegistered() && !peer.isExpired() { + if !peer.isExpired() { validPeers = append(validPeers, peer) } } @@ -373,8 +368,6 @@ func (h *Headscale) RefreshMachine(machine *Machine, expiry time.Time) { // DeleteMachine softs deletes a Machine from the database. func (h *Headscale) DeleteMachine(machine *Machine) error { - machine.Registered = false - h.db.Save(&machine) // we mark it as unregistered, just in case if err := h.db.Delete(&machine).Error; err != nil { return err } @@ -642,7 +635,7 @@ func (machine Machine) toNode( LastSeen: machine.LastSeen, KeepAlive: true, - MachineAuthorized: machine.Registered, + MachineAuthorized: !machine.isExpired(), Capabilities: []string{tailcfg.CapabilityFileSharing}, } @@ -660,8 +653,6 @@ func (machine *Machine) toProto() *v1.Machine { Name: machine.Name, Namespace: machine.Namespace.toProto(), - Registered: machine.Registered, - // TODO(kradalby): Implement register method enum converter // RegisterMethod: , @@ -738,7 +729,7 @@ func (h *Headscale) RegisterMachine(machine Machine, []byte(MachinePublicKeyEnsurePrefix(machine.MachineKey)), ) machineFromDatabase, _ := h.GetMachineByMachineKey(machineKey) - if machine.isRegistered() { + if machineFromDatabase != nil { log.Trace(). Caller(). Str("machine", machine.Name). @@ -774,13 +765,6 @@ func (h *Headscale) RegisterMachine(machine Machine, // move it to tags instead of having a column. // machine.RegisterMethod = registrationMethod - // TODO(kradalby): Registered is a very frustrating value - // to keep up to date, and it makes is have to care if a - // machine is registered, authenticated and expired. - // Let us simplify the model, a machine is _only_ saved if - // it is registered. - machine.Registered = true - h.db.Save(&machine) log.Trace(). diff --git a/oidc.go b/oidc.go index f291e8c..e745236 100644 --- a/oidc.go +++ b/oidc.go @@ -248,7 +248,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - if machine.isRegistered() { + if machine != nil { log.Trace(). Caller(). Str("machine", machine.Name). @@ -291,58 +291,57 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } + // register the machine if it's new - if !machine.Registered { - log.Debug().Msg("Registering new machine after successful callback") + log.Debug().Msg("Registering new machine after successful callback") - namespace, err := h.GetNamespace(namespaceName) - if errors.Is(err, errNamespaceNotFound) { - namespace, err = h.CreateNamespace(namespaceName) + namespace, err := h.GetNamespace(namespaceName) + if errors.Is(err, errNamespaceNotFound) { + namespace, err = h.CreateNamespace(namespaceName) - if err != nil { - log.Error(). - Err(err). - Caller(). - Msgf("could not create new namespace '%s'", namespaceName) - ctx.String( - http.StatusInternalServerError, - "could not create new namespace", - ) - - return - } - } else if err != nil { - log.Error(). - Caller(). - Err(err). - Str("namespace", namespaceName). - Msg("could not find or create namespace") - ctx.String( - http.StatusInternalServerError, - "could not find or create namespace", - ) - - return - } - - _, err = h.RegisterMachineFromAuthCallback( - machineKeyStr, - namespace.Name, - RegisterMethodOIDC, - &requestedTime, - ) if err != nil { log.Error(). - Caller(). Err(err). - Msg("could not register machine") + Caller(). + Msgf("could not create new namespace '%s'", namespaceName) ctx.String( http.StatusInternalServerError, - "could not register machine", + "could not create new namespace", ) return } + } else if err != nil { + log.Error(). + Caller(). + Err(err). + Str("namespace", namespaceName). + Msg("could not find or create namespace") + ctx.String( + http.StatusInternalServerError, + "could not find or create namespace", + ) + + return + } + + _, err = h.RegisterMachineFromAuthCallback( + machineKeyStr, + namespace.Name, + RegisterMethodOIDC, + &requestedTime, + ) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("could not register machine") + ctx.String( + http.StatusInternalServerError, + "could not register machine", + ) + + return } var content bytes.Buffer From a8649d83c4b655eae469d556eacafe8c81985a40 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 17:42:03 +0000 Subject: [PATCH 120/204] Remove all references to Machine.Registered from tests --- acls_test.go | 7 ------- dns_test.go | 8 -------- machine_test.go | 7 ------- namespaces_test.go | 5 ----- preauth_keys_test.go | 3 --- routes_test.go | 2 -- utils_test.go | 3 --- 7 files changed, 35 deletions(-) diff --git a/acls_test.go b/acls_test.go index 5534257..edea854 100644 --- a/acls_test.go +++ b/acls_test.go @@ -119,7 +119,6 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { Name: "testmachine", IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), HostInfo: datatypes.JSON(hostInfo), @@ -163,7 +162,6 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { Name: "testmachine", IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), HostInfo: datatypes.JSON(hostInfo), @@ -207,7 +205,6 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { Name: "testmachine", IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), HostInfo: datatypes.JSON(hostInfo), @@ -250,7 +247,6 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { Name: "webserver", IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), HostInfo: datatypes.JSON(hostInfo), @@ -267,7 +263,6 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { Name: "user", IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), HostInfo: datatypes.JSON(hostInfo), @@ -345,7 +340,6 @@ func (s *Suite) TestPortNamespace(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: ips, AuthKeyID: uint(pak.ID), @@ -388,7 +382,6 @@ func (s *Suite) TestPortGroup(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: ips, AuthKeyID: uint(pak.ID), diff --git a/dns_test.go b/dns_test.go index 23a34ca..5fd30d3 100644 --- a/dns_test.go +++ b/dns_test.go @@ -164,7 +164,6 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { Name: "test_get_shared_nodes_1", NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.1")}, AuthKeyID: uint(preAuthKeyInShared1.ID), @@ -182,7 +181,6 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { Name: "test_get_shared_nodes_2", NamespaceID: namespaceShared2.ID, Namespace: *namespaceShared2, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.2")}, AuthKeyID: uint(preAuthKeyInShared2.ID), @@ -200,7 +198,6 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { Name: "test_get_shared_nodes_3", NamespaceID: namespaceShared3.ID, Namespace: *namespaceShared3, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.3")}, AuthKeyID: uint(preAuthKeyInShared3.ID), @@ -218,7 +215,6 @@ func (s *Suite) TestDNSConfigMapResponseWithMagicDNS(c *check.C) { Name: "test_get_shared_nodes_4", NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.4")}, AuthKeyID: uint(PreAuthKey2InShared1.ID), @@ -311,7 +307,6 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { Name: "test_get_shared_nodes_1", NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.1")}, AuthKeyID: uint(preAuthKeyInShared1.ID), @@ -329,7 +324,6 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { Name: "test_get_shared_nodes_2", NamespaceID: namespaceShared2.ID, Namespace: *namespaceShared2, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.2")}, AuthKeyID: uint(preAuthKeyInShared2.ID), @@ -347,7 +341,6 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { Name: "test_get_shared_nodes_3", NamespaceID: namespaceShared3.ID, Namespace: *namespaceShared3, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.3")}, AuthKeyID: uint(preAuthKeyInShared3.ID), @@ -365,7 +358,6 @@ func (s *Suite) TestDNSConfigMapResponseWithoutMagicDNS(c *check.C) { Name: "test_get_shared_nodes_4", NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.4")}, AuthKeyID: uint(preAuthKey2InShared1.ID), diff --git a/machine_test.go b/machine_test.go index e9c91f8..733270e 100644 --- a/machine_test.go +++ b/machine_test.go @@ -29,7 +29,6 @@ func (s *Suite) TestGetMachine(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } @@ -59,7 +58,6 @@ func (s *Suite) TestGetMachineByID(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } @@ -82,7 +80,6 @@ func (s *Suite) TestDeleteMachine(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(1), } @@ -105,7 +102,6 @@ func (s *Suite) TestHardDeleteMachine(c *check.C) { DiscoKey: "faa", Name: "testmachine3", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(1), } @@ -136,7 +132,6 @@ func (s *Suite) TestListPeers(c *check.C) { DiscoKey: "faa" + strconv.Itoa(index), Name: "testmachine" + strconv.Itoa(index), NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } @@ -188,7 +183,6 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { }, Name: "testmachine" + strconv.Itoa(index), NamespaceID: stor[index%2].namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(stor[index%2].key.ID), } @@ -258,7 +252,6 @@ func (s *Suite) TestExpireMachine(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), Expiry: &time.Time{}, diff --git a/namespaces_test.go b/namespaces_test.go index 585ba93..1710f7d 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -54,7 +54,6 @@ func (s *Suite) TestDestroyNamespaceErrors(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } @@ -146,7 +145,6 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { Name: "test_get_shared_nodes_1", NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.1")}, AuthKeyID: uint(preAuthKeyShared1.ID), @@ -164,7 +162,6 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { Name: "test_get_shared_nodes_2", NamespaceID: namespaceShared2.ID, Namespace: *namespaceShared2, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.2")}, AuthKeyID: uint(preAuthKeyShared2.ID), @@ -182,7 +179,6 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { Name: "test_get_shared_nodes_3", NamespaceID: namespaceShared3.ID, Namespace: *namespaceShared3, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.3")}, AuthKeyID: uint(preAuthKeyShared3.ID), @@ -200,7 +196,6 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { Name: "test_get_shared_nodes_4", NamespaceID: namespaceShared1.ID, Namespace: *namespaceShared1, - Registered: true, RegisterMethod: RegisterMethodAuthKey, IPAddresses: []netaddr.IP{netaddr.MustParseIP("100.64.0.4")}, AuthKeyID: uint(preAuthKey2Shared1.ID), diff --git a/preauth_keys_test.go b/preauth_keys_test.go index f8cf276..6f233a9 100644 --- a/preauth_keys_test.go +++ b/preauth_keys_test.go @@ -80,7 +80,6 @@ func (*Suite) TestAlreadyUsedKey(c *check.C) { DiscoKey: "faa", Name: "testest", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } @@ -105,7 +104,6 @@ func (*Suite) TestReusableBeingUsedKey(c *check.C) { DiscoKey: "faa", Name: "testest", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } @@ -143,7 +141,6 @@ func (*Suite) TestEphemeralKey(c *check.C) { DiscoKey: "faa", Name: "testest", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, LastSeen: &now, AuthKeyID: uint(pak.ID), diff --git a/routes_test.go b/routes_test.go index 94bda45..1c24bf2 100644 --- a/routes_test.go +++ b/routes_test.go @@ -35,7 +35,6 @@ func (s *Suite) TestGetRoutes(c *check.C) { DiscoKey: "faa", Name: "test_get_route_machine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), HostInfo: datatypes.JSON(hostinfo), @@ -89,7 +88,6 @@ func (s *Suite) TestGetEnableRoutes(c *check.C) { DiscoKey: "faa", Name: "test_enable_route_machine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), HostInfo: datatypes.JSON(hostinfo), diff --git a/utils_test.go b/utils_test.go index 271013a..7c72c09 100644 --- a/utils_test.go +++ b/utils_test.go @@ -36,7 +36,6 @@ func (s *Suite) TestGetUsedIps(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), IPAddresses: ips, @@ -85,7 +84,6 @@ func (s *Suite) TestGetMultiIp(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), IPAddresses: ips, @@ -176,7 +174,6 @@ func (s *Suite) TestGetAvailableIpMachineWithoutIP(c *check.C) { DiscoKey: "faa", Name: "testmachine", NamespaceID: namespace.ID, - Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), } From 78251ce8ec5e37295e2498dabb87170c3f5e1cce Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 18:05:03 +0000 Subject: [PATCH 121/204] Remove registrated field This commit removes the field from the database and does a DB migration **removing** all unregistered machines from headscale. This means that from this version, all machines in the database is considered registered. --- db.go | 33 +++++++++++++++++++++++++++++++++ machine.go | 1 - 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/db.go b/db.go index 8db7bc6..e87cb6d 100644 --- a/db.go +++ b/db.go @@ -5,6 +5,7 @@ import ( "time" "github.com/glebarez/sqlite" + "github.com/rs/zerolog/log" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -34,6 +35,38 @@ func (h *Headscale) initDB() error { _ = db.Migrator().RenameColumn(&Machine{}, "ip_address", "ip_addresses") + // If the Machine table has a column for registered, + // find all occourences of "false" and drop them. Then + // remove the column. + if db.Migrator().HasColumn(&Machine{}, "registered") { + log.Info(). + Msg(`Database has legacy "registered" column in machine, removing...`) + + machines := Machines{} + if err := h.db.Not("registered").Find(&machines).Error; err != nil { + log.Error().Err(err).Msg("Error accessing db") + } + + for _, machine := range machines { + log.Info(). + Str("machine", machine.Name). + Str("machine_key", machine.MachineKey). + Msg("Deleting unregistered machine") + if err := h.db.Delete(&Machine{}, machine.ID).Error; err != nil { + log.Error(). + Err(err). + Str("machine", machine.Name). + Str("machine_key", machine.MachineKey). + Msg("Error deleting unregistered machine") + } + } + + err := db.Migrator().DropColumn(&Machine{}, "registered") + if err != nil { + log.Error().Err(err).Msg("Error dropping registered column") + } + } + err = db.AutoMigrate(&Machine{}) if err != nil { return err diff --git a/machine.go b/machine.go index 16d6d86..ac1a1c8 100644 --- a/machine.go +++ b/machine.go @@ -45,7 +45,6 @@ type Machine struct { NamespaceID uint Namespace Namespace `gorm:"foreignKey:NamespaceID"` - Registered bool // temp RegisterMethod string // TODO(kradalby): This seems like irrelevant information? From eea8e7ba6f2d69d41a065959d566e69013480e67 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 22:11:31 +0000 Subject: [PATCH 122/204] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d44db56..20c23c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ **Changes**: - Fix a bug were the same IP could be assigned to multiple hosts if joined in quick succession [#346](https://github.com/juanfont/headscale/pull/346) +- Simplify the code behind registration of machines [#366](https://github.com/juanfont/headscale/pull/366) + - Nodes are now only written to database if they are registrated successfully **0.14.0 (2022-02-24):** From 5e1b12948e305dca78eeccdce826784092174cd0 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 22:21:06 +0000 Subject: [PATCH 123/204] Remove registered field from proto --- proto/headscale/v1/machine.proto | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/proto/headscale/v1/machine.proto b/proto/headscale/v1/machine.proto index 7451db8..75552d7 100644 --- a/proto/headscale/v1/machine.proto +++ b/proto/headscale/v1/machine.proto @@ -22,16 +22,16 @@ message Machine { string name = 6; Namespace namespace = 7; - bool registered = 8; - RegisterMethod register_method = 9; - google.protobuf.Timestamp last_seen = 10; - google.protobuf.Timestamp last_successful_update = 11; - google.protobuf.Timestamp expiry = 12; + google.protobuf.Timestamp last_seen = 8; + google.protobuf.Timestamp last_successful_update = 9; + google.protobuf.Timestamp expiry = 10; - PreAuthKey pre_auth_key = 13; + PreAuthKey pre_auth_key = 11; - google.protobuf.Timestamp created_at = 14; + google.protobuf.Timestamp created_at = 12; + + RegisterMethod register_method = 13; // google.protobuf.Timestamp updated_at = 14; // google.protobuf.Timestamp deleted_at = 15; From e64bee778f4e925553c4045b6087ef933bff3779 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 22:21:14 +0000 Subject: [PATCH 124/204] Regenerate proto --- gen/go/headscale/v1/machine.pb.go | 100 ++++++++---------- .../headscale/v1/headscale.swagger.json | 9 +- 2 files changed, 48 insertions(+), 61 deletions(-) diff --git a/gen/go/headscale/v1/machine.pb.go b/gen/go/headscale/v1/machine.pb.go index 9a5064f..b25db29 100644 --- a/gen/go/headscale/v1/machine.pb.go +++ b/gen/go/headscale/v1/machine.pb.go @@ -85,13 +85,12 @@ type Machine struct { IpAddresses []string `protobuf:"bytes,5,rep,name=ip_addresses,json=ipAddresses,proto3" json:"ip_addresses,omitempty"` Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` Namespace *Namespace `protobuf:"bytes,7,opt,name=namespace,proto3" json:"namespace,omitempty"` - Registered bool `protobuf:"varint,8,opt,name=registered,proto3" json:"registered,omitempty"` - RegisterMethod RegisterMethod `protobuf:"varint,9,opt,name=register_method,json=registerMethod,proto3,enum=headscale.v1.RegisterMethod" json:"register_method,omitempty"` - LastSeen *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=last_seen,json=lastSeen,proto3" json:"last_seen,omitempty"` - LastSuccessfulUpdate *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=last_successful_update,json=lastSuccessfulUpdate,proto3" json:"last_successful_update,omitempty"` - Expiry *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=expiry,proto3" json:"expiry,omitempty"` - PreAuthKey *PreAuthKey `protobuf:"bytes,13,opt,name=pre_auth_key,json=preAuthKey,proto3" json:"pre_auth_key,omitempty"` - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,14,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + LastSeen *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=last_seen,json=lastSeen,proto3" json:"last_seen,omitempty"` + LastSuccessfulUpdate *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=last_successful_update,json=lastSuccessfulUpdate,proto3" json:"last_successful_update,omitempty"` + Expiry *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=expiry,proto3" json:"expiry,omitempty"` + PreAuthKey *PreAuthKey `protobuf:"bytes,11,opt,name=pre_auth_key,json=preAuthKey,proto3" json:"pre_auth_key,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + RegisterMethod RegisterMethod `protobuf:"varint,13,opt,name=register_method,json=registerMethod,proto3,enum=headscale.v1.RegisterMethod" json:"register_method,omitempty"` } func (x *Machine) Reset() { @@ -175,20 +174,6 @@ func (x *Machine) GetNamespace() *Namespace { return nil } -func (x *Machine) GetRegistered() bool { - if x != nil { - return x.Registered - } - return false -} - -func (x *Machine) GetRegisterMethod() RegisterMethod { - if x != nil { - return x.RegisterMethod - } - return RegisterMethod_REGISTER_METHOD_UNSPECIFIED -} - func (x *Machine) GetLastSeen() *timestamppb.Timestamp { if x != nil { return x.LastSeen @@ -224,6 +209,13 @@ func (x *Machine) GetCreatedAt() *timestamppb.Timestamp { return nil } +func (x *Machine) GetRegisterMethod() RegisterMethod { + if x != nil { + return x.RegisterMethod + } + return RegisterMethod_REGISTER_METHOD_UNSPECIFIED +} + type RegisterMachineRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -822,7 +814,7 @@ var file_headscale_v1_machine_proto_rawDesc = []byte{ 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x65, 0x61, 0x75, 0x74, 0x68, 0x6b, - 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfd, 0x04, 0x0a, 0x07, 0x4d, 0x61, 0x63, + 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdd, 0x04, 0x0a, 0x07, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, @@ -836,33 +828,31 @@ var file_headscale_v1_machine_proto_rawDesc = []byte{ 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0a, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, 0x45, 0x0a, 0x0f, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x12, 0x37, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x12, 0x50, 0x0a, 0x16, 0x6c, - 0x61, 0x73, 0x74, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x5f, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x75, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x32, 0x0a, - 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, - 0x79, 0x12, 0x3a, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, - 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, - 0x79, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x39, 0x0a, - 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x48, 0x0a, 0x16, 0x52, 0x65, 0x67, 0x69, + 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x6c, + 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, + 0x53, 0x65, 0x65, 0x6e, 0x12, 0x50, 0x0a, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x3a, 0x0a, 0x0c, 0x70, 0x72, + 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x72, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x41, + 0x75, 0x74, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x12, 0x45, 0x0a, 0x0f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x68, 0x65, 0x61, + 0x64, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x65, 0x72, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x48, 0x0a, 0x16, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, @@ -962,12 +952,12 @@ var file_headscale_v1_machine_proto_goTypes = []interface{}{ } var file_headscale_v1_machine_proto_depIdxs = []int32{ 14, // 0: headscale.v1.Machine.namespace:type_name -> headscale.v1.Namespace - 0, // 1: headscale.v1.Machine.register_method:type_name -> headscale.v1.RegisterMethod - 15, // 2: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp - 15, // 3: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp - 15, // 4: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp - 16, // 5: headscale.v1.Machine.pre_auth_key:type_name -> headscale.v1.PreAuthKey - 15, // 6: headscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp + 15, // 1: headscale.v1.Machine.last_seen:type_name -> google.protobuf.Timestamp + 15, // 2: headscale.v1.Machine.last_successful_update:type_name -> google.protobuf.Timestamp + 15, // 3: headscale.v1.Machine.expiry:type_name -> google.protobuf.Timestamp + 16, // 4: headscale.v1.Machine.pre_auth_key:type_name -> headscale.v1.PreAuthKey + 15, // 5: headscale.v1.Machine.created_at:type_name -> google.protobuf.Timestamp + 0, // 6: headscale.v1.Machine.register_method:type_name -> headscale.v1.RegisterMethod 1, // 7: headscale.v1.RegisterMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 8: headscale.v1.GetMachineResponse.machine:type_name -> headscale.v1.Machine 1, // 9: headscale.v1.ExpireMachineResponse.machine:type_name -> headscale.v1.Machine diff --git a/gen/openapiv2/headscale/v1/headscale.swagger.json b/gen/openapiv2/headscale/v1/headscale.swagger.json index db348f4..8d808f9 100644 --- a/gen/openapiv2/headscale/v1/headscale.swagger.json +++ b/gen/openapiv2/headscale/v1/headscale.swagger.json @@ -885,12 +885,6 @@ "namespace": { "$ref": "#/definitions/v1Namespace" }, - "registered": { - "type": "boolean" - }, - "registerMethod": { - "$ref": "#/definitions/v1RegisterMethod" - }, "lastSeen": { "type": "string", "format": "date-time" @@ -909,6 +903,9 @@ "createdAt": { "type": "string", "format": "date-time" + }, + "registerMethod": { + "$ref": "#/definitions/v1RegisterMethod" } } }, From 5e92ddad4363815c0b29bd5933ec274db55bbb29 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 22:42:30 +0000 Subject: [PATCH 125/204] Remove redundant caches This commit removes the two extra caches (oidc, requested time) and uses the new central registration cache instead. The requested time is unified into the main machine object and the oidc key is just added to the same cache, as a string with the state as a key instead of machine key. --- api.go | 25 ++++++++++--------------- app.go | 33 ++++++++++++--------------------- app_test.go | 5 ----- grpcv1.go | 17 +---------------- machine.go | 2 -- oidc.go | 29 ++++------------------------- 6 files changed, 27 insertions(+), 84 deletions(-) diff --git a/api.go b/api.go index f831cac..9b8fafd 100644 --- a/api.go +++ b/api.go @@ -140,17 +140,25 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { // We create the machine and then keep it around until a callback // happens newMachine := Machine{ - Expiry: &time.Time{}, MachineKey: machineKeyStr, Name: req.Hostinfo.Hostname, NodeKey: NodePublicKeyStripPrefix(req.NodeKey), LastSeen: &now, } + if !req.Expiry.IsZero() { + log.Trace(). + Caller(). + Str("machine", req.Hostinfo.Hostname). + Time("expiry", req.Expiry). + Msg("Non-zero expiry time requested") + newMachine.Expiry = &req.Expiry + } + h.registrationCache.Set( machineKeyStr, newMachine, - requestedExpiryCacheExpiration, + registerCacheExpiration, ) h.handleMachineRegistrationNew(ctx, machineKey, req) @@ -490,19 +498,6 @@ func (h *Headscale) handleMachineRegistrationNew( strings.TrimSuffix(h.cfg.ServerURL, "/"), MachinePublicKeyStripPrefix(machineKey)) } - if !registerRequest.Expiry.IsZero() { - log.Trace(). - Caller(). - Str("machine", registerRequest.Hostinfo.Hostname). - Time("expiry", registerRequest.Expiry). - Msg("Non-zero expiry time requested, adding to cache") - h.requestedExpiryCache.Set( - machineKey.String(), - registerRequest.Expiry, - requestedExpiryCacheExpiration, - ) - } - respBody, err := encode(resp, &machineKey, h.privateKey) if err != nil { log.Error(). diff --git a/app.go b/app.go index 63ca10e..f7a6e63 100644 --- a/app.go +++ b/app.go @@ -55,8 +55,8 @@ const ( HTTPReadTimeout = 30 * time.Second privateKeyFileMode = 0o600 - requestedExpiryCacheExpiration = time.Minute * 5 - requestedExpiryCacheCleanupInterval = time.Minute * 10 + registerCacheExpiration = time.Minute * 15 + registerCacheCleanup = time.Minute * 20 errUnsupportedDatabase = Error("unsupported DB") errUnsupportedLetsEncryptChallengeType = Error( @@ -148,11 +148,8 @@ type Headscale struct { lastStateChange sync.Map - oidcProvider *oidc.Provider - oauth2Config *oauth2.Config - oidcStateCache *cache.Cache - - requestedExpiryCache *cache.Cache + oidcProvider *oidc.Provider + oauth2Config *oauth2.Config registrationCache *cache.Cache @@ -204,25 +201,19 @@ func NewHeadscale(cfg Config) (*Headscale, error) { return nil, errUnsupportedDatabase } - requestedExpiryCache := cache.New( - requestedExpiryCacheExpiration, - requestedExpiryCacheCleanupInterval, - ) - registrationCache := cache.New( // TODO(kradalby): Add unified cache expiry config options - requestedExpiryCacheExpiration, - requestedExpiryCacheCleanupInterval, + registerCacheExpiration, + registerCacheCleanup, ) app := Headscale{ - cfg: cfg, - dbType: cfg.DBtype, - dbString: dbString, - privateKey: privKey, - aclRules: tailcfg.FilterAllowAll, // default allowall - requestedExpiryCache: requestedExpiryCache, - registrationCache: registrationCache, + cfg: cfg, + dbType: cfg.DBtype, + dbString: dbString, + privateKey: privKey, + aclRules: tailcfg.FilterAllowAll, // default allowall + registrationCache: registrationCache, } err = app.initDB() diff --git a/app_test.go b/app_test.go index 53c703a..96036a1 100644 --- a/app_test.go +++ b/app_test.go @@ -5,7 +5,6 @@ import ( "os" "testing" - "github.com/patrickmn/go-cache" "gopkg.in/check.v1" "inet.af/netaddr" ) @@ -50,10 +49,6 @@ func (s *Suite) ResetDB(c *check.C) { cfg: cfg, dbType: "sqlite3", dbString: tmpDir + "/headscale_test.db", - requestedExpiryCache: cache.New( - requestedExpiryCacheExpiration, - requestedExpiryCacheCleanupInterval, - ), } err = app.initDB() if err != nil { diff --git a/grpcv1.go b/grpcv1.go index 75732b1..1c02290 100644 --- a/grpcv1.go +++ b/grpcv1.go @@ -160,25 +160,10 @@ func (api headscaleV1APIServer) RegisterMachine( Str("machine_key", request.GetKey()). Msg("Registering machine") - // TODO(kradalby): Currently, if it fails to find a requested expiry, non will be set - // This means that if a user is to slow with register a machine, it will possibly not - // have the correct expiry. - requestedTime := time.Time{} - if requestedTimeIf, found := api.h.requestedExpiryCache.Get(request.GetKey()); found { - log.Trace(). - Caller(). - Str("machine", request.Key). - Msg("Expiry time found in cache, assigning to node") - if reqTime, ok := requestedTimeIf.(time.Time); ok { - requestedTime = reqTime - } - } - machine, err := api.h.RegisterMachineFromAuthCallback( request.GetKey(), request.GetNamespace(), RegisterMethodCLI, - &requestedTime, ) if err != nil { return nil, err @@ -418,7 +403,7 @@ func (api headscaleV1APIServer) DebugCreateMachine( api.h.registrationCache.Set( request.GetKey(), newMachine, - requestedExpiryCacheExpiration, + registerCacheExpiration, ) return &v1.DebugCreateMachineResponse{Machine: newMachine.toProto()}, nil diff --git a/machine.go b/machine.go index ac1a1c8..03f727a 100644 --- a/machine.go +++ b/machine.go @@ -683,7 +683,6 @@ func (h *Headscale) RegisterMachineFromAuthCallback( machineKeyStr string, namespaceName string, registrationMethod string, - expiry *time.Time, ) (*Machine, error) { if machineInterface, ok := h.registrationCache.Get(machineKeyStr); ok { if registrationMachine, ok := machineInterface.(Machine); ok { @@ -697,7 +696,6 @@ func (h *Headscale) RegisterMachineFromAuthCallback( registrationMachine.NamespaceID = namespace.ID registrationMachine.RegisterMethod = registrationMethod - registrationMachine.Expiry = expiry machine, err := h.RegisterMachine( registrationMachine, diff --git a/oidc.go b/oidc.go index e745236..fe69a76 100644 --- a/oidc.go +++ b/oidc.go @@ -10,20 +10,16 @@ import ( "html/template" "net/http" "strings" - "time" "github.com/coreos/go-oidc/v3/oidc" "github.com/gin-gonic/gin" - "github.com/patrickmn/go-cache" "github.com/rs/zerolog/log" "golang.org/x/oauth2" "tailscale.com/types/key" ) const ( - oidcStateCacheExpiration = time.Minute * 5 - oidcStateCacheCleanupInterval = time.Minute * 10 - randomByteSize = 16 + randomByteSize = 16 ) type IDTokenClaims struct { @@ -60,14 +56,6 @@ func (h *Headscale) initOIDC() error { } } - // init the state cache if it hasn't been already - if h.oidcStateCache == nil { - h.oidcStateCache = cache.New( - oidcStateCacheExpiration, - oidcStateCacheCleanupInterval, - ) - } - return nil } @@ -100,7 +88,7 @@ func (h *Headscale) RegisterOIDC(ctx *gin.Context) { stateStr := hex.EncodeToString(randomBlob)[:32] // place the machine key into the state cache, so it can be retrieved later - h.oidcStateCache.Set(stateStr, machineKeyStr, oidcStateCacheExpiration) + h.registrationCache.Set(stateStr, machineKeyStr, registerCacheExpiration) authURL := h.oauth2Config.AuthCodeURL(stateStr) log.Debug().Msgf("Redirecting to %s for authentication", authURL) @@ -196,7 +184,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { } // retrieve machinekey from state cache - machineKeyIf, machineKeyFound := h.oidcStateCache.Get(state) + machineKeyIf, machineKeyFound := h.registrationCache.Get(state) if !machineKeyFound { log.Error(). @@ -228,14 +216,6 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - // TODO(kradalby): Currently, if it fails to find a requested expiry, non will be set - requestedTime := time.Time{} - if requestedTimeIf, found := h.requestedExpiryCache.Get(machineKey.String()); found { - if reqTime, ok := requestedTimeIf.(time.Time); ok { - requestedTime = reqTime - } - } - // retrieve machine information machine, err := h.GetMachineByMachineKey(machineKey) if err != nil { @@ -254,7 +234,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { Str("machine", machine.Name). Msg("machine already registered, reauthenticating") - h.RefreshMachine(machine, requestedTime) + h.RefreshMachine(machine, *machine.Expiry) var content bytes.Buffer if err := oidcCallbackTemplate.Execute(&content, oidcCallbackTemplateConfig{ @@ -329,7 +309,6 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { machineKeyStr, namespace.Name, RegisterMethodOIDC, - &requestedTime, ) if err != nil { log.Error(). From 8bef04d8df774d3d816e6f872436e4ec416bf8cc Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 22:45:42 +0000 Subject: [PATCH 126/204] Remove sorted todo --- oidc.go | 1 - 1 file changed, 1 deletion(-) diff --git a/oidc.go b/oidc.go index fe69a76..93fc1be 100644 --- a/oidc.go +++ b/oidc.go @@ -112,7 +112,6 @@ var oidcCallbackTemplate = template.Must( `), ) -// TODO: Why is the entire machine registration logic duplicated here? // OIDCCallback handles the callback from the OIDC endpoint // Retrieves the mkey from the state cache and adds the machine to the users email namespace // TODO: A confirmation page for new machines should be added to avoid phishing vulnerabilities From 379017602cec416135e8f34b4b407c4099d722c7 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 22:50:35 +0000 Subject: [PATCH 127/204] Reformat and add db backup note --- CHANGELOG.md | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20c23c9..1a2bda3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,29 +1,31 @@ # CHANGELOG -**0.15.0 (2022-xx-xx):** +## 0.15.0 (2022-xx-xx) -**BREAKING**: +**Note:** Take a backup of your database before upgrading. + +### BREAKING - Boundaries between Namespaces has been removed and all nodes can communicate by default [#357](https://github.com/juanfont/headscale/pull/357) - To limit access between nodes, use [ACLs](./docs/acls.md). -**Changes**: +### Changes - Fix a bug were the same IP could be assigned to multiple hosts if joined in quick succession [#346](https://github.com/juanfont/headscale/pull/346) - Simplify the code behind registration of machines [#366](https://github.com/juanfont/headscale/pull/366) - Nodes are now only written to database if they are registrated successfully -**0.14.0 (2022-02-24):** +## 0.14.0 (2022-02-24) -**UPCOMING BREAKING**: -From the **next** version (`0.15.0`), all machines will be able to communicate regardless of +**UPCOMING ### BREAKING +From the **next\*\* version (`0.15.0`), all machines will be able to communicate regardless of if they are in the same namespace. This means that the behaviour currently limited to ACLs will become default. From version `0.15.0`, all limitation of communications must be done with ACLs. This is a part of aligning `headscale`'s behaviour with Tailscale's upstream behaviour. -**BREAKING**: +### BREAKING - ACLs have been rewritten to align with the bevaviour Tailscale Control Panel provides. **NOTE:** This is only active if you use ACLs - Namespaces are now treated as Users @@ -31,17 +33,17 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - Tags should now work correctly and adding a host to Headscale should now reload the rules. - The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features -**Features**: +### Features - Add support for configurable mTLS [docs](docs/tls.md#configuring-mutual-tls-authentication-mtls) [#297](https://github.com/juanfont/headscale/pull/297) -**Changes**: +### Changes - Remove dependency on CGO (switch from CGO SQLite to pure Go) [#346](https://github.com/juanfont/headscale/pull/346) **0.13.0 (2022-02-18):** -**Features**: +### Features - Add IPv6 support to the prefix assigned to namespaces - Add API Key support @@ -52,7 +54,7 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - `oidc.domain_map` option has been removed - `strip_email_domain` option has been added (see [config-example.yaml](./config_example.yaml)) -**Changes**: +### Changes - `ip_prefix` is now superseded by `ip_prefixes` in the configuration [#208](https://github.com/juanfont/headscale/pull/208) - Upgrade `tailscale` (1.20.4) and other dependencies to latest [#314](https://github.com/juanfont/headscale/pull/314) @@ -61,35 +63,35 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh **0.12.4 (2022-01-29):** -**Changes**: +### Changes - Make gRPC Unix Socket permissions configurable [#292](https://github.com/juanfont/headscale/pull/292) - Trim whitespace before reading Private Key from file [#289](https://github.com/juanfont/headscale/pull/289) - Add new command to generate a private key for `headscale` [#290](https://github.com/juanfont/headscale/pull/290) - Fixed issue where hosts deleted from control server may be written back to the database, as long as they are connected to the control server [#278](https://github.com/juanfont/headscale/pull/278) -**0.12.3 (2022-01-13):** +## 0.12.3 (2022-01-13) -**Changes**: +### Changes - Added Alpine container [#270](https://github.com/juanfont/headscale/pull/270) - Minor updates in dependencies [#271](https://github.com/juanfont/headscale/pull/271) -**0.12.2 (2022-01-11):** +## 0.12.2 (2022-01-11) Happy New Year! -**Changes**: +### Changes - Fix Docker release [#258](https://github.com/juanfont/headscale/pull/258) - Rewrite main docs [#262](https://github.com/juanfont/headscale/pull/262) - Improve Docker docs [#263](https://github.com/juanfont/headscale/pull/263) -**0.12.1 (2021-12-24):** +## 0.12.1 (2021-12-24) (We are skipping 0.12.0 to correct a mishap done weeks ago with the version tagging) -**BREAKING**: +### BREAKING - Upgrade to Tailscale 1.18 [#229](https://github.com/juanfont/headscale/pull/229) - This change requires a new format for private key, private keys are now generated automatically: @@ -97,19 +99,19 @@ Happy New Year! 2. Restart `headscale`, a new key will be generated. 3. Restart all Tailscale clients to fetch the new key -**Changes**: +### Changes - Unify configuration example [#197](https://github.com/juanfont/headscale/pull/197) - Add stricter linting and formatting [#223](https://github.com/juanfont/headscale/pull/223) -**Features**: +### Features - Add gRPC and HTTP API (HTTP API is currently disabled) [#204](https://github.com/juanfont/headscale/pull/204) - Use gRPC between the CLI and the server [#206](https://github.com/juanfont/headscale/pull/206), [#212](https://github.com/juanfont/headscale/pull/212) - Beta OpenID Connect support [#126](https://github.com/juanfont/headscale/pull/126), [#227](https://github.com/juanfont/headscale/pull/227) -**0.11.0 (2021-10-25):** +## 0.11.0 (2021-10-25) -**BREAKING**: +### BREAKING - Make headscale fetch DERP map from URL and file [#196](https://github.com/juanfont/headscale/pull/196) From 82cb6b9ddce6d0f2e7b3539313378d301b54e671 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 23:00:41 +0000 Subject: [PATCH 128/204] Cleanup some unreachable code --- machine.go | 23 ----------------------- oidc.go | 2 +- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/machine.go b/machine.go index 03f727a..1560858 100644 --- a/machine.go +++ b/machine.go @@ -718,25 +718,6 @@ func (h *Headscale) RegisterMachine(machine Machine, Str("machine_key", machine.MachineKey). Msg("Registering machine") - // If the machine is already in the database, it is seeking - // reauthentication, and by reaching this step, has been authenticated - // and need to have an updated expiry. - var machineKey key.MachinePublic - _ = machineKey.UnmarshalText( - []byte(MachinePublicKeyEnsurePrefix(machine.MachineKey)), - ) - machineFromDatabase, _ := h.GetMachineByMachineKey(machineKey) - if machineFromDatabase != nil { - log.Trace(). - Caller(). - Str("machine", machine.Name). - Msg("machine already registered, reauthenticating") - - h.RefreshMachine(machineFromDatabase, *machine.Expiry) - - return machineFromDatabase, nil - } - log.Trace(). Caller(). Str("machine", machine.Name). @@ -758,10 +739,6 @@ func (h *Headscale) RegisterMachine(machine Machine, machine.IPAddresses = ips - // TODO(kradalby): This field is uneccessary metadata, - // move it to tags instead of having a column. - // machine.RegisterMethod = registrationMethod - h.db.Save(&machine) log.Trace(). diff --git a/oidc.go b/oidc.go index 93fc1be..8e89e27 100644 --- a/oidc.go +++ b/oidc.go @@ -215,7 +215,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - // retrieve machine information + // retrieve machine information if it exist machine, err := h.GetMachineByMachineKey(machineKey) if err != nil { log.Error().Msg("machine key not found in database") From 7c63412df53f2db419ddfcb66a6add530109a3c6 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 28 Feb 2022 23:02:41 +0000 Subject: [PATCH 129/204] Remove todo --- app.go | 1 - 1 file changed, 1 deletion(-) diff --git a/app.go b/app.go index f7a6e63..5818509 100644 --- a/app.go +++ b/app.go @@ -202,7 +202,6 @@ func NewHeadscale(cfg Config) (*Headscale, error) { } registrationCache := cache.New( - // TODO(kradalby): Add unified cache expiry config options registerCacheExpiration, registerCacheCleanup, ) From 5157f356cb5e1fdd83c29f7d6050450b9635d182 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 1 Mar 2022 07:30:35 +0000 Subject: [PATCH 130/204] Fix apple profile issue being generated with escaped characters --- apple_mobileconfig.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apple_mobileconfig.go b/apple_mobileconfig.go index e5d9eed..69f61a6 100644 --- a/apple_mobileconfig.go +++ b/apple_mobileconfig.go @@ -4,6 +4,7 @@ import ( "bytes" "html/template" "net/http" + textTemplate "text/template" "github.com/gin-gonic/gin" "github.com/gofrs/uuid" @@ -30,7 +31,7 @@ func (h *Headscale) AppleMobileConfig(ctx *gin.Context) {

curl {{.Url}}/apple/ios

-->

curl {{.Url}}/apple/macos

- +

Profiles

- +

macOS

Headscale can be set to the default server by installing a Headscale configuration profile:

@@ -58,7 +59,7 @@ func (h *Headscale) AppleMobileConfig(ctx *gin.Context) { defaults write io.tailscale.ipn.macos ControlURL {{.URL}}

Restart Tailscale.app and log in.

- + `)) @@ -202,8 +203,8 @@ type AppleMobilePlatformConfig struct { URL string } -var commonTemplate = template.Must( - template.New("mobileconfig").Parse(` +var commonTemplate = textTemplate.Must( + textTemplate.New("mobileconfig").Parse(` @@ -229,7 +230,7 @@ var commonTemplate = template.Must( `), ) -var iosTemplate = template.Must(template.New("iosTemplate").Parse(` +var iosTemplate = textTemplate.Must(textTemplate.New("iosTemplate").Parse(` PayloadType io.tailscale.ipn.ios From 1cb39d914cf4ff5c4a451f3479746a39b71580a0 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 1 Mar 2022 07:35:17 +0000 Subject: [PATCH 131/204] Update dependencies --- go.mod | 26 +++++++++++++------------- go.sum | 35 +++++++++++++++++++++++++++++++++++ machine.go | 2 +- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 8b721fa..04ce927 100644 --- a/go.mod +++ b/go.mod @@ -13,12 +13,12 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 github.com/infobloxopen/protoc-gen-gorm v1.1.0 - github.com/klauspost/compress v1.14.2 + github.com/klauspost/compress v1.14.4 github.com/ory/dockertest/v3 v3.8.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/philip-bui/grpc-zerolog v1.0.1 github.com/prometheus/client_golang v1.12.1 - github.com/pterm/pterm v0.12.36 + github.com/pterm/pterm v0.12.37 github.com/rs/zerolog v1.26.1 github.com/spf13/cobra v1.3.0 github.com/spf13/viper v1.10.1 @@ -27,9 +27,9 @@ require ( github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e github.com/zsais/go-gin-prometheus v0.1.0 golang.org/x/crypto v0.0.0-20220214200702-86341886e292 - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 + golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336 + google.golang.org/genproto v0.0.0-20220228195345-15d65a4533f7 google.golang.org/grpc v1.44.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 google.golang.org/protobuf v1.27.1 @@ -39,12 +39,12 @@ require ( gorm.io/driver/postgres v1.3.1 gorm.io/gorm v1.23.1 inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 - tailscale.com v1.20.4 + tailscale.com v1.22.0 ) require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Microsoft/go-winio v0.5.1 // indirect + github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/atomicgo/cursor v0.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -58,7 +58,7 @@ require ( github.com/docker/go-units v0.4.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/gin-contrib/sse v0.1.0 // indirect - github.com/glebarez/go-sqlite v1.14.7 // indirect + github.com/glebarez/go-sqlite v1.14.8 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.10.0 // indirect @@ -92,7 +92,7 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/lib/pq v1.10.3 // indirect - github.com/magiconair/properties v1.8.5 // indirect + github.com/magiconair/properties v1.8.6 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect @@ -121,7 +121,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.2.0 // indirect - github.com/ugorji/go/codec v1.2.6 // indirect + github.com/ugorji/go/codec v1.2.7 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -129,8 +129,8 @@ require ( go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect go4.org/mem v0.0.0-20210711025021-927187094b94 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37 // indirect - golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect - golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect + golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect + golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.7 // indirect @@ -140,9 +140,9 @@ require ( gorm.io/driver/mysql v1.3.2 // indirect gorm.io/driver/sqlite v1.3.1 // indirect gorm.io/driver/sqlserver v1.3.1 // indirect - modernc.org/libc v1.14.3 // indirect + modernc.org/libc v1.14.5 // indirect modernc.org/mathutil v1.4.1 // indirect modernc.org/memory v1.0.5 // indirect - modernc.org/sqlite v1.14.5 // indirect + modernc.org/sqlite v1.14.7 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 20eec3f..e35d636 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,8 @@ github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030I github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= @@ -109,6 +111,7 @@ github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuD github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +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.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -214,6 +217,8 @@ github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= github.com/glebarez/go-sqlite v1.14.7 h1:eXrKp59O5eWBfxv2Xfq5d7uex4+clKrOtWfMzzGSkoM= github.com/glebarez/go-sqlite v1.14.7/go.mod h1:TKAw5tjyB/ocvVht7Xv4772qRAun5CG/xLCEbkDwNUc= +github.com/glebarez/go-sqlite v1.14.8 h1:30RsIS/olgfOMr7SxiCaYhpq50BTteA/CUKaWVOOHYg= +github.com/glebarez/go-sqlite v1.14.8/go.mod h1:gf9QVsKCYMcu+7nd+ZbDqvXnEXEb22qLcqRUQ9XEI34= github.com/glebarez/sqlite v1.3.5 h1:R9op5nxb9Z10t4VXQSdAVyqRalLhWdLrlaT/iuvOGHI= github.com/glebarez/sqlite v1.3.5/go.mod h1:ZffEtp/afVhV+jvIzQi8wlYEIkuGAYshr9OPKM/NmQc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -355,6 +360,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.3.0/go.mod h1:d2gYTOTUQklu06xp0AJYYmRdTVU1VKrqhkYfYag2L08= github.com/grpc-ecosystem/grpc-gateway/v2 v2.4.0/go.mod h1:IOyTYjcIO0rkmnGBfJTL0NJ11exy/Tc2QEuv7hCXp24= @@ -499,6 +505,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4= +github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= @@ -537,6 +545,8 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -673,6 +683,8 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= github.com/pterm/pterm v0.12.36 h1:Ui5zZj7xA8lXR0CxWXlKGCQMW1cZVUMOS8jEXs6ur/g= github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= +github.com/pterm/pterm v0.12.37 h1:QGOyuaDUmY3yTbP0k6i0uPNqNHA9YofEBQDy0tIyKTA= +github.com/pterm/pterm v0.12.37/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= @@ -763,9 +775,13 @@ github.com/twitchtv/twirp v7.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vF github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= +github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= +github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= @@ -942,6 +958,8 @@ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -961,6 +979,8 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= 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= @@ -1063,9 +1083,12 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1276,6 +1299,8 @@ google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336 h1:RK2ysGpQApbI6U7xn+ROT2rrm08lE/t8AcGqG8XI1CY= google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220228195345-15d65a4533f7 h1:ntPPoHzFW6Xp09ueznmahONZufyoSakK/piXnr2BU3I= +google.golang.org/genproto v0.0.0-20220228195345-15d65a4533f7/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1450,7 +1475,10 @@ modernc.org/ccgo/v3 v3.14.0/go.mod h1:hBrkiBlUwvr5vV/ZH9YzXIp982jKE8Ek8tR1ytoAL6 modernc.org/ccgo/v3 v3.15.1/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8= +modernc.org/ccgo/v3 v3.15.12/go.mod h1:VFePOWoCd8uDGRJpq/zfJ29D0EVzMSyID8LCMWYbX6I= +modernc.org/ccgo/v3 v3.15.13/go.mod h1:QHtvdpeODlXjdK3tsbpyK+7U9JV4PQsrPGIbtmc0KfY= modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/ccorpus v1.11.4/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= @@ -1496,6 +1524,8 @@ modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34= modernc.org/libc v1.14.3 h1:ruQJ8VDhnWkUR/otUG/Ksw+sWHUw9cPAq6mjDaY/Y7c= modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ= +modernc.org/libc v1.14.5 h1:DAHvwGoVRDZs5iJXnX9RJrgXSsorupCWmJ2ac964Owk= +modernc.org/libc v1.14.5/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak= modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= @@ -1507,8 +1537,11 @@ modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sqlite v1.14.5 h1:bYrrjwH9Y7QUGk1MbchZDhRfmpGuEAs/D45sVjNbfvs= modernc.org/sqlite v1.14.5/go.mod h1:YyX5Rx0WbXokitdWl2GJIDy4BrPxBP0PwwhpXOHCDLE= +modernc.org/sqlite v1.14.7 h1:A+6rGjtRQbt9SORXfV+hUyXOP3mDf7J5uz+EES/CNPE= +modernc.org/sqlite v1.14.7/go.mod h1:yiCvMv3HblGmzENNIaNtFhfaNIwcla4u2JQEwJPzfEc= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= modernc.org/tcl v1.10.0/go.mod h1:WzWapmP/7dHVhFoyPpEaNSVTL8xtewhouN/cqSJ5A2s= +modernc.org/tcl v1.11.0/go.mod h1:zsTUpbQ+NxQEjOjCUlImDLPv1sG8Ww0qp66ZvyOxCgw= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.2.21/go.mod h1:uXrObx4pGqXWIMliC5MiKuwAyMrltzwpteOFUP1PWCc= modernc.org/z v1.3.0/go.mod h1:+mvgLH814oDjtATDdT3rs84JnUIpkvAF5B8AVkNlE2g= @@ -1519,3 +1552,5 @@ sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= tailscale.com v1.20.4 h1:7cl/Q2Sbo2Jb2dX7zA+Exbbl7DT5UGZ4iGhQ2xj23X0= tailscale.com v1.20.4/go.mod h1:kjVy3ji2OH5lZhPLIIRacoY3CN4Bo3Yyb2mtoM8nfJ4= +tailscale.com v1.22.0 h1:/a1f6eKEl9vL/wGFP8mkhe7O1zDRGtWa9Ft2rGp5N80= +tailscale.com v1.22.0/go.mod h1:D2zuDnjHT7v4aCt71c4+ytQUUAGpnypW+DoubYLaHjg= diff --git a/machine.go b/machine.go index dac4459..3106d0b 100644 --- a/machine.go +++ b/machine.go @@ -630,7 +630,7 @@ func (machine Machine) toNode( Endpoints: endpoints, DERP: derp, - Hostinfo: hostinfo, + Hostinfo: hostinfo.View(), Created: machine.CreatedAt, LastSeen: machine.LastSeen, From 8a95fe517a433d5f6df938a5d1f091e996d84d5e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 1 Mar 2022 16:31:25 +0000 Subject: [PATCH 132/204] Use specific types for all fields on machine (no datatypes.json) This commit removes the need for datatypes.JSON and makes the code a bit cleaner by allowing us to use proper types throughout the code when it comes to hostinfo and other datatypes on the machine object. This allows us to remove alot of unmarshal/marshal operations and remove a lot of obsolete error checks. This following commits will clean away a lot of untyped data and uneccessary error checks. --- db.go | 76 ++++++++++++++++++++++++++++ go.mod | 7 +-- go.sum | 47 ----------------- machine.go | 144 +++++++++-------------------------------------------- 4 files changed, 101 insertions(+), 173 deletions(-) diff --git a/db.go b/db.go index 8db7bc6..5906402 100644 --- a/db.go +++ b/db.go @@ -1,13 +1,18 @@ package headscale import ( + "database/sql/driver" + "encoding/json" "errors" + "fmt" "time" "github.com/glebarez/sqlite" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" + "inet.af/netaddr" + "tailscale.com/tailcfg" ) const ( @@ -141,3 +146,74 @@ func (h *Headscale) setValue(key string, value string) error { return nil } + +// This is a "wrapper" type around tailscales +// Hostinfo to allow us to add database "serialization" +// methods. This allows us to use a typed values throughout +// the code and not have to marshal/unmarshal and error +// check all over the code. +type HostInfo tailcfg.Hostinfo + +func (hi *HostInfo) Scan(destination interface{}) error { + switch value := destination.(type) { + case []byte: + return json.Unmarshal(value, hi) + + case string: + return json.Unmarshal([]byte(value), hi) + + default: + return fmt.Errorf("%w: unexpected data type %T", errMachineAddressesInvalid, destination) + } +} + +// Value return json value, implement driver.Valuer interface. +func (hi HostInfo) Value() (driver.Value, error) { + bytes, err := json.Marshal(hi) + + return string(bytes), err +} + +type IPPrefixes []netaddr.IPPrefix + +func (i *IPPrefixes) Scan(destination interface{}) error { + switch value := destination.(type) { + case []byte: + return json.Unmarshal(value, i) + + case string: + return json.Unmarshal([]byte(value), i) + + default: + return fmt.Errorf("%w: unexpected data type %T", errMachineAddressesInvalid, destination) + } +} + +// Value return json value, implement driver.Valuer interface. +func (i IPPrefixes) Value() (driver.Value, error) { + bytes, err := json.Marshal(i) + + return string(bytes), err +} + +type StringList []string + +func (i *StringList) Scan(destination interface{}) error { + switch value := destination.(type) { + case []byte: + return json.Unmarshal(value, i) + + case string: + return json.Unmarshal([]byte(value), i) + + default: + return fmt.Errorf("%w: unexpected data type %T", errMachineAddressesInvalid, destination) + } +} + +// Value return json value, implement driver.Valuer interface. +func (i StringList) Value() (driver.Value, error) { + bytes, err := json.Marshal(i) + + return string(bytes), err +} diff --git a/go.mod b/go.mod index 04ce927..a121826 100644 --- a/go.mod +++ b/go.mod @@ -35,7 +35,7 @@ require ( google.golang.org/protobuf v1.27.1 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/yaml.v2 v2.4.0 - gorm.io/datatypes v1.0.5 + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gorm.io/driver/postgres v1.3.1 gorm.io/gorm v1.23.1 inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 @@ -52,6 +52,7 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/containerd/continuity v0.2.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/denisenkom/go-mssqldb v0.12.0 // indirect github.com/docker/cli v20.10.12+incompatible // indirect github.com/docker/docker v20.10.12+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -136,10 +137,6 @@ require ( google.golang.org/appengine v1.6.7 // indirect gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - gorm.io/driver/mysql v1.3.2 // indirect - gorm.io/driver/sqlite v1.3.1 // indirect - gorm.io/driver/sqlserver v1.3.1 // indirect modernc.org/libc v1.14.5 // indirect modernc.org/mathutil v1.4.1 // indirect modernc.org/memory v1.0.5 // indirect diff --git a/go.sum b/go.sum index e35d636..558d3d7 100644 --- a/go.sum +++ b/go.sum @@ -73,7 +73,6 @@ github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzX github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= @@ -111,7 +110,6 @@ github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuD github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -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.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -215,7 +213,6 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= -github.com/glebarez/go-sqlite v1.14.7 h1:eXrKp59O5eWBfxv2Xfq5d7uex4+clKrOtWfMzzGSkoM= github.com/glebarez/go-sqlite v1.14.7/go.mod h1:TKAw5tjyB/ocvVht7Xv4772qRAun5CG/xLCEbkDwNUc= github.com/glebarez/go-sqlite v1.14.8 h1:30RsIS/olgfOMr7SxiCaYhpq50BTteA/CUKaWVOOHYg= github.com/glebarez/go-sqlite v1.14.8/go.mod h1:gf9QVsKCYMcu+7nd+ZbDqvXnEXEb22qLcqRUQ9XEI34= @@ -360,7 +357,6 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.3.0/go.mod h1:d2gYTOTUQklu06xp0AJYYmRdTVU1VKrqhkYfYag2L08= github.com/grpc-ecosystem/grpc-gateway/v2 v2.4.0/go.mod h1:IOyTYjcIO0rkmnGBfJTL0NJ11exy/Tc2QEuv7hCXp24= @@ -418,7 +414,6 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/infobloxopen/atlas-app-toolkit v0.24.1-0.20210416193901-4c7518b07e08/go.mod h1:9BTHnpff654rY1J8KxSUOLJ+ZUDn2Vi3mmk26gQDo1M= github.com/infobloxopen/protoc-gen-gorm v1.1.0 h1:l6JKEkqMTFbtoGIfQmh/aOy7KfljgX4ql772LtG4kas= github.com/infobloxopen/protoc-gen-gorm v1.1.0/go.mod h1:ohzLmmFMWQztw2RBHunfjKSCjTPUW4JvbgU1Mdazwxg= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -440,7 +435,6 @@ github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5W github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -456,7 +450,6 @@ github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01C github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38= github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= @@ -464,7 +457,6 @@ github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08 github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8= github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w= github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= @@ -480,8 +472,6 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -503,8 +493,6 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= -github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.14.4 h1:eijASRJcobkVtSt81Olfh7JX43osYLwy5krOJo6YEu4= github.com/klauspost/compress v1.14.4/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= @@ -543,7 +531,6 @@ github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc8 github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -568,7 +555,6 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ= github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= @@ -681,8 +667,6 @@ github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= -github.com/pterm/pterm v0.12.36 h1:Ui5zZj7xA8lXR0CxWXlKGCQMW1cZVUMOS8jEXs6ur/g= -github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= github.com/pterm/pterm v0.12.37 h1:QGOyuaDUmY3yTbP0k6i0uPNqNHA9YofEBQDy0tIyKTA= github.com/pterm/pterm v0.12.37/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= @@ -774,12 +758,8 @@ github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9 github.com/twitchtv/twirp v7.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= -github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= -github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -861,8 +841,6 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2 h1:XdAboW3BNMv9ocSCOk/u1MFioZGzCNkiJZ19v9Oe3Ig= -golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -956,7 +934,6 @@ golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -977,7 +954,6 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= @@ -1085,8 +1061,6 @@ golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1297,8 +1271,6 @@ google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336 h1:RK2ysGpQApbI6U7xn+ROT2rrm08lE/t8AcGqG8XI1CY= -google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220228195345-15d65a4533f7 h1:ntPPoHzFW6Xp09ueznmahONZufyoSakK/piXnr2BU3I= google.golang.org/genproto v0.0.0-20220228195345-15d65a4533f7/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1384,23 +1356,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/datatypes v1.0.5 h1:3vHCfg4Bz8SDx83zE+ASskF+g/j0kWrcKrY9jFUyAl0= -gorm.io/datatypes v1.0.5/go.mod h1:acG/OHGwod+1KrbwPL1t+aavb7jOBOETeyl5M8K5VQs= -gorm.io/driver/mysql v1.2.2/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo= -gorm.io/driver/mysql v1.2.3 h1:cZqzlOfg5Kf1VIdLC1D9hT6Cy9BgxhExLj/2tIgUe7Y= -gorm.io/driver/mysql v1.2.3/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo= -gorm.io/driver/mysql v1.3.2 h1:QJryWiqQ91EvZ0jZL48NOpdlPdMjdip1hQ8bTgo4H7I= -gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= -gorm.io/driver/postgres v1.2.3 h1:f4t0TmNMy9gh3TU2PX+EppoA6YsgFnyq8Ojtddb42To= -gorm.io/driver/postgres v1.2.3/go.mod h1:pJV6RgYQPG47aM1f0QeOzFH9HxQc8JcmAgjRCgS0wjs= gorm.io/driver/postgres v1.3.1 h1:Pyv+gg1Gq1IgsLYytj/S2k7ebII3CzEdpqQkPOdH24g= gorm.io/driver/postgres v1.3.1/go.mod h1:WwvWOuR9unCLpGWCL6Y3JOeBWvbKi6JLhayiVclSZZU= -gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= -gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= -gorm.io/driver/sqlserver v1.3.1 h1:F5t6ScMzOgy1zukRTIZgLZwKahgt3q1woAILVolKpOI= -gorm.io/driver/sqlserver v1.3.1/go.mod h1:w25Vrx2BG+CJNUu/xKbFhaKlGxT/nzRkhWCCoptX8tQ= -gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk= gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.1 h1:aj5IlhDzEPsoIyOPtTRVI+SyaN1u6k613sbt4pwbxG0= gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= @@ -1522,7 +1479,6 @@ modernc.org/libc v1.13.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= modernc.org/libc v1.13.2/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34= -modernc.org/libc v1.14.3 h1:ruQJ8VDhnWkUR/otUG/Ksw+sWHUw9cPAq6mjDaY/Y7c= modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ= modernc.org/libc v1.14.5 h1:DAHvwGoVRDZs5iJXnX9RJrgXSsorupCWmJ2ac964Owk= modernc.org/libc v1.14.5/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak= @@ -1535,7 +1491,6 @@ modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14= modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.14.5 h1:bYrrjwH9Y7QUGk1MbchZDhRfmpGuEAs/D45sVjNbfvs= modernc.org/sqlite v1.14.5/go.mod h1:YyX5Rx0WbXokitdWl2GJIDy4BrPxBP0PwwhpXOHCDLE= modernc.org/sqlite v1.14.7 h1:A+6rGjtRQbt9SORXfV+hUyXOP3mDf7J5uz+EES/CNPE= modernc.org/sqlite v1.14.7/go.mod h1:yiCvMv3HblGmzENNIaNtFhfaNIwcla4u2JQEwJPzfEc= @@ -1550,7 +1505,5 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -tailscale.com v1.20.4 h1:7cl/Q2Sbo2Jb2dX7zA+Exbbl7DT5UGZ4iGhQ2xj23X0= -tailscale.com v1.20.4/go.mod h1:kjVy3ji2OH5lZhPLIIRacoY3CN4Bo3Yyb2mtoM8nfJ4= tailscale.com v1.22.0 h1:/a1f6eKEl9vL/wGFP8mkhe7O1zDRGtWa9Ft2rGp5N80= tailscale.com v1.22.0/go.mod h1:D2zuDnjHT7v4aCt71c4+ytQUUAGpnypW+DoubYLaHjg= diff --git a/machine.go b/machine.go index 3106d0b..b53bd10 100644 --- a/machine.go +++ b/machine.go @@ -2,7 +2,6 @@ package headscale import ( "database/sql/driver" - "encoding/json" "fmt" "sort" "strconv" @@ -13,7 +12,6 @@ import ( v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/rs/zerolog/log" "google.golang.org/protobuf/types/known/timestamppb" - "gorm.io/datatypes" "inet.af/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" @@ -51,9 +49,9 @@ type Machine struct { LastSuccessfulUpdate *time.Time Expiry *time.Time - HostInfo datatypes.JSON - Endpoints datatypes.JSON - EnabledRoutes datatypes.JSON + HostInfo HostInfo + Endpoints StringList + EnabledRoutes IPPrefixes CreatedAt time.Time UpdatedAt time.Time @@ -393,20 +391,8 @@ func (h *Headscale) HardDeleteMachine(machine *Machine) error { } // GetHostInfo returns a Hostinfo struct for the machine. -func (machine *Machine) GetHostInfo() (*tailcfg.Hostinfo, error) { - hostinfo := tailcfg.Hostinfo{} - if len(machine.HostInfo) != 0 { - hi, err := machine.HostInfo.MarshalJSON() - if err != nil { - return nil, err - } - err = json.Unmarshal(hi, &hostinfo) - if err != nil { - return nil, err - } - } - - return &hostinfo, nil +func (machine *Machine) GetHostInfo() tailcfg.Hostinfo { + return tailcfg.Hostinfo(machine.HostInfo) } func (h *Headscale) isOutdated(machine *Machine) bool { @@ -536,54 +522,12 @@ func (machine Machine) toNode( // TODO(kradalby): Needs investigation, We probably dont need this condition // now that we dont have shared nodes if includeRoutes { - routesStr := []string{} - if len(machine.EnabledRoutes) != 0 { - allwIps, err := machine.EnabledRoutes.MarshalJSON() - if err != nil { - return nil, err - } - err = json.Unmarshal(allwIps, &routesStr) - if err != nil { - return nil, err - } - } - - for _, routeStr := range routesStr { - ip, err := netaddr.ParseIPPrefix(routeStr) - if err != nil { - return nil, err - } - allowedIPs = append(allowedIPs, ip) - } - } - - endpoints := []string{} - if len(machine.Endpoints) != 0 { - be, err := machine.Endpoints.MarshalJSON() - if err != nil { - return nil, err - } - err = json.Unmarshal(be, &endpoints) - if err != nil { - return nil, err - } - } - - hostinfo := tailcfg.Hostinfo{} - if len(machine.HostInfo) != 0 { - hi, err := machine.HostInfo.MarshalJSON() - if err != nil { - return nil, err - } - err = json.Unmarshal(hi, &hostinfo) - if err != nil { - return nil, err - } + allowedIPs = append(allowedIPs, machine.EnabledRoutes...) } var derp string - if hostinfo.NetInfo != nil { - derp = fmt.Sprintf("127.3.3.40:%d", hostinfo.NetInfo.PreferredDERP) + if machine.HostInfo.NetInfo != nil { + derp = fmt.Sprintf("127.3.3.40:%d", machine.HostInfo.NetInfo.PreferredDERP) } else { derp = "127.3.3.40:0" // Zero means disconnected or unknown. } @@ -614,6 +558,8 @@ func (machine Machine) toNode( hostname = machine.Name } + hostInfo := machine.GetHostInfo() + node := tailcfg.Node{ ID: tailcfg.NodeID(machine.ID), // this is the actual ID StableID: tailcfg.StableNodeID( @@ -627,10 +573,10 @@ func (machine Machine) toNode( DiscoKey: discoKey, Addresses: addrs, AllowedIPs: allowedIPs, - Endpoints: endpoints, + Endpoints: machine.Endpoints, DERP: derp, - Hostinfo: hostinfo.View(), + Hostinfo: hostInfo.View(), Created: machine.CreatedAt, LastSeen: machine.LastSeen, @@ -786,37 +732,12 @@ func (h *Headscale) RegisterMachine( return machine, nil } -func (machine *Machine) GetAdvertisedRoutes() ([]netaddr.IPPrefix, error) { - hostInfo, err := machine.GetHostInfo() - if err != nil { - return nil, err - } - - return hostInfo.RoutableIPs, nil +func (machine *Machine) GetAdvertisedRoutes() []netaddr.IPPrefix { + return machine.HostInfo.RoutableIPs } -func (machine *Machine) GetEnabledRoutes() ([]netaddr.IPPrefix, error) { - data, err := machine.EnabledRoutes.MarshalJSON() - if err != nil { - return nil, err - } - - routesStr := []string{} - err = json.Unmarshal(data, &routesStr) - if err != nil { - return nil, err - } - - routes := make([]netaddr.IPPrefix, len(routesStr)) - for index, routeStr := range routesStr { - route, err := netaddr.ParseIPPrefix(routeStr) - if err != nil { - return nil, err - } - routes[index] = route - } - - return routes, nil +func (machine *Machine) GetEnabledRoutes() []netaddr.IPPrefix { + return machine.EnabledRoutes } func (machine *Machine) IsRoutesEnabled(routeStr string) bool { @@ -825,10 +746,7 @@ func (machine *Machine) IsRoutesEnabled(routeStr string) bool { return false } - enabledRoutes, err := machine.GetEnabledRoutes() - if err != nil { - return false - } + enabledRoutes := machine.GetEnabledRoutes() for _, enabledRoute := range enabledRoutes { if route == enabledRoute { @@ -852,13 +770,8 @@ func (h *Headscale) EnableRoutes(machine *Machine, routeStrs ...string) error { newRoutes[index] = route } - availableRoutes, err := machine.GetAdvertisedRoutes() - if err != nil { - return err - } - for _, newRoute := range newRoutes { - if !containsIPPrefix(availableRoutes, newRoute) { + if !containsIPPrefix(machine.GetAdvertisedRoutes(), newRoute) { return fmt.Errorf( "route (%s) is not available on node %s: %w", machine.Name, @@ -867,30 +780,19 @@ func (h *Headscale) EnableRoutes(machine *Machine, routeStrs ...string) error { } } - routes, err := json.Marshal(newRoutes) - if err != nil { - return err - } - - machine.EnabledRoutes = datatypes.JSON(routes) + machine.EnabledRoutes = newRoutes h.db.Save(&machine) return nil } -func (machine *Machine) RoutesToProto() (*v1.Routes, error) { - availableRoutes, err := machine.GetAdvertisedRoutes() - if err != nil { - return nil, err - } +func (machine *Machine) RoutesToProto() *v1.Routes { + availableRoutes := machine.GetAdvertisedRoutes() - enabledRoutes, err := machine.GetEnabledRoutes() - if err != nil { - return nil, err - } + enabledRoutes := machine.GetEnabledRoutes() return &v1.Routes{ AdvertisedRoutes: ipPrefixToString(availableRoutes), EnabledRoutes: ipPrefixToString(enabledRoutes), - }, nil + } } From 6477e6a5837b90ba2eb6002ae1137f8ded62042c Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 1 Mar 2022 16:34:24 +0000 Subject: [PATCH 133/204] Use new machine types --- acls.go | 17 ++--------------- grpcv1.go | 25 +++---------------------- poll.go | 21 ++------------------- routes.go | 39 +++------------------------------------ 4 files changed, 10 insertions(+), 92 deletions(-) diff --git a/acls.go b/acls.go index 1a597c2..194da12 100644 --- a/acls.go +++ b/acls.go @@ -247,13 +247,7 @@ func expandAlias( for _, namespace := range owners { machines := filterMachinesByNamespace(machines, namespace) for _, machine := range machines { - if len(machine.HostInfo) == 0 { - continue - } - hi, err := machine.GetHostInfo() - if err != nil { - return ips, err - } + hi := machine.GetHostInfo() for _, t := range hi.RequestTags { if alias == t { ips = append(ips, machine.IPAddresses.ToStringSlice()...) @@ -315,15 +309,8 @@ func excludeCorrectlyTaggedNodes( } // for each machine if tag is in tags list, don't append it. for _, machine := range nodes { - if len(machine.HostInfo) == 0 { - out = append(out, machine) + hi := machine.GetHostInfo() - continue - } - hi, err := machine.GetHostInfo() - if err != nil { - return out, err - } found := false for _, t := range hi.RequestTags { if containsString(tags, t) { diff --git a/grpcv1.go b/grpcv1.go index 60e181d..bbda19f 100644 --- a/grpcv1.go +++ b/grpcv1.go @@ -3,12 +3,10 @@ package headscale import ( "context" - "encoding/json" "time" "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/rs/zerolog/log" - "gorm.io/datatypes" "tailscale.com/tailcfg" ) @@ -262,13 +260,8 @@ func (api headscaleV1APIServer) GetMachineRoute( return nil, err } - routes, err := machine.RoutesToProto() - if err != nil { - return nil, err - } - return &v1.GetMachineRouteResponse{ - Routes: routes, + Routes: machine.RoutesToProto(), }, nil } @@ -286,13 +279,8 @@ func (api headscaleV1APIServer) EnableMachineRoutes( return nil, err } - routes, err := machine.RoutesToProto() - if err != nil { - return nil, err - } - return &v1.EnableMachineRoutesResponse{ - Routes: routes, + Routes: machine.RoutesToProto(), }, nil } @@ -379,13 +367,6 @@ func (api headscaleV1APIServer) DebugCreateMachine( Hostname: "DebugTestMachine", } - log.Trace().Caller().Interface("hostinfo", hostinfo).Msg("") - - hostinfoJson, err := json.Marshal(hostinfo) - if err != nil { - return nil, err - } - newMachine := Machine{ MachineKey: request.GetKey(), Name: request.GetName(), @@ -395,7 +376,7 @@ func (api headscaleV1APIServer) DebugCreateMachine( LastSeen: &time.Time{}, LastSuccessfulUpdate: &time.Time{}, - HostInfo: datatypes.JSON(hostinfoJson), + HostInfo: HostInfo(hostinfo), } // log.Trace().Caller().Interface("machine", newMachine).Msg("") diff --git a/poll.go b/poll.go index 21aa3b3..1ae8cd0 100644 --- a/poll.go +++ b/poll.go @@ -2,7 +2,6 @@ package headscale import ( "context" - "encoding/json" "errors" "fmt" "io" @@ -11,7 +10,6 @@ import ( "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" - "gorm.io/datatypes" "gorm.io/gorm" "tailscale.com/tailcfg" "tailscale.com/types/key" @@ -85,12 +83,8 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { Str("machine", machine.Name). Msg("Found machine in database") - hostinfo, err := json.Marshal(req.Hostinfo) - if err != nil { - return - } machine.Name = req.Hostinfo.Hostname - machine.HostInfo = datatypes.JSON(hostinfo) + machine.HostInfo = HostInfo(*req.Hostinfo) machine.DiscoKey = DiscoPublicKeyStripPrefix(req.DiscoKey) now := time.Now().UTC() @@ -114,18 +108,7 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { // The intended use is for clients to discover the DERP map at start-up // before their first real endpoint update. if !req.ReadOnly { - endpoints, err := json.Marshal(req.Endpoints) - if err != nil { - log.Error(). - Caller(). - Str("func", "PollNetMapHandler"). - Err(err). - Msg("Failed to mashal requested endpoints for the client") - ctx.String(http.StatusInternalServerError, ":(") - - return - } - machine.Endpoints = datatypes.JSON(endpoints) + machine.Endpoints = req.Endpoints machine.LastSeen = &now } h.db.Updates(machine) diff --git a/routes.go b/routes.go index 0065a03..e8de299 100644 --- a/routes.go +++ b/routes.go @@ -1,9 +1,6 @@ package headscale import ( - "encoding/json" - - "gorm.io/datatypes" "inet.af/netaddr" ) @@ -23,12 +20,7 @@ func (h *Headscale) GetAdvertisedNodeRoutes( return nil, err } - hostInfo, err := machine.GetHostInfo() - if err != nil { - return nil, err - } - - return &hostInfo.RoutableIPs, nil + return &machine.HostInfo.RoutableIPs, nil } // Deprecated: use machine function instead @@ -43,27 +35,7 @@ func (h *Headscale) GetEnabledNodeRoutes( return nil, err } - data, err := machine.EnabledRoutes.MarshalJSON() - if err != nil { - return nil, err - } - - routesStr := []string{} - err = json.Unmarshal(data, &routesStr) - if err != nil { - return nil, err - } - - routes := make([]netaddr.IPPrefix, len(routesStr)) - for index, routeStr := range routesStr { - route, err := netaddr.ParseIPPrefix(routeStr) - if err != nil { - return nil, err - } - routes[index] = route - } - - return routes, nil + return machine.EnabledRoutes, nil } // Deprecated: use machine function instead @@ -135,12 +107,7 @@ func (h *Headscale) EnableNodeRoute( return errRouteIsNotAvailable } - routes, err := json.Marshal(enabledRoutes) - if err != nil { - return err - } - - machine.EnabledRoutes = datatypes.JSON(routes) + machine.EnabledRoutes = enabledRoutes h.db.Save(&machine) return nil From 49cd761bf62851a62f4f61b2e610b7f66cef0059 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 1 Mar 2022 16:34:35 +0000 Subject: [PATCH 134/204] Use new machine types in tests --- acls_test.go | 132 ++++++++++++++++++++++++++++++------------------ cli_test.go | 3 -- machine_test.go | 16 +----- routes_test.go | 11 +--- 4 files changed, 87 insertions(+), 75 deletions(-) diff --git a/acls_test.go b/acls_test.go index 9f0432a..b06255a 100644 --- a/acls_test.go +++ b/acls_test.go @@ -6,7 +6,6 @@ import ( "testing" "gopkg.in/check.v1" - "gorm.io/datatypes" "inet.af/netaddr" "tailscale.com/tailcfg" ) @@ -108,9 +107,12 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { _, err = app.GetMachine("user1", "testmachine") c.Assert(err, check.NotNil) - hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"testmachine\",\"RequestTags\":[\"tag:test\"]}", - ) + hostInfo := tailcfg.Hostinfo{ + OS: "centos", + Hostname: "testmachine", + RequestTags: []string{"tag:test"}, + } + machine := Machine{ ID: 0, MachineKey: "foo", @@ -122,7 +124,7 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(hostInfo), + HostInfo: HostInfo(hostInfo), } app.db.Save(&machine) @@ -152,9 +154,12 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { _, err = app.GetMachine("user1", "testmachine") c.Assert(err, check.NotNil) - hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"testmachine\",\"RequestTags\":[\"tag:test\"]}", - ) + hostInfo := tailcfg.Hostinfo{ + OS: "centos", + Hostname: "testmachine", + RequestTags: []string{"tag:test"}, + } + machine := Machine{ ID: 1, MachineKey: "12345", @@ -166,7 +171,7 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(hostInfo), + HostInfo: HostInfo(hostInfo), } app.db.Save(&machine) @@ -196,9 +201,12 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { _, err = app.GetMachine("user1", "testmachine") c.Assert(err, check.NotNil) - hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"testmachine\",\"RequestTags\":[\"tag:foo\"]}", - ) + hostInfo := tailcfg.Hostinfo{ + OS: "centos", + Hostname: "testmachine", + RequestTags: []string{"tag:foo"}, + } + machine := Machine{ ID: 1, MachineKey: "12345", @@ -210,7 +218,7 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(hostInfo), + HostInfo: HostInfo(hostInfo), } app.db.Save(&machine) @@ -239,9 +247,12 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { _, err = app.GetMachine("user1", "webserver") c.Assert(err, check.NotNil) - hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}", - ) + hostInfo := tailcfg.Hostinfo{ + OS: "centos", + Hostname: "webserver", + RequestTags: []string{"tag:webapp"}, + } + machine := Machine{ ID: 1, MachineKey: "12345", @@ -253,11 +264,14 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(hostInfo), + HostInfo: HostInfo(hostInfo), } app.db.Save(&machine) _, err = app.GetMachine("user1", "user") - hostInfo = []byte("{\"OS\":\"debian\",\"Hostname\":\"user\"}") + hostInfo2 := tailcfg.Hostinfo{ + OS: "debian", + Hostname: "Hostname", + } c.Assert(err, check.NotNil) machine = Machine{ ID: 2, @@ -270,7 +284,7 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(hostInfo), + HostInfo: HostInfo(hostInfo2), } app.db.Save(&machine) @@ -872,18 +886,22 @@ func Test_expandAlias(t *testing.T) { netaddr.MustParseIP("100.64.0.1"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:hr-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "foo", + RequestTags: []string{"tag:hr-webserver"}, + }, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:hr-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "foo", + RequestTags: []string{"tag:hr-webserver"}, + }, }, { IPAddresses: MachineAddresses{ @@ -955,18 +973,22 @@ func Test_expandAlias(t *testing.T) { netaddr.MustParseIP("100.64.0.1"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "foo", + RequestTags: []string{"tag:accountant-webserver"}, + }, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "foo", + RequestTags: []string{"tag:accountant-webserver"}, + }, }, { IPAddresses: MachineAddresses{ @@ -1032,18 +1054,22 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { netaddr.MustParseIP("100.64.0.1"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "foo", + RequestTags: []string{"tag:accountant-webserver"}, + }, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "foo", + RequestTags: []string{"tag:accountant-webserver"}, + }, }, { IPAddresses: MachineAddresses{ @@ -1074,18 +1100,22 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { netaddr.MustParseIP("100.64.0.1"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"hr-web1\",\"RequestTags\":[\"tag:hr-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "hr-web1", + RequestTags: []string{"tag:hr-webserver"}, + }, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"hr-web2\",\"RequestTags\":[\"tag:hr-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "hr-web2", + RequestTags: []string{"tag:hr-webserver"}, + }, }, { IPAddresses: MachineAddresses{ @@ -1102,18 +1132,22 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { netaddr.MustParseIP("100.64.0.1"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"hr-web1\",\"RequestTags\":[\"tag:hr-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "hr-web1", + RequestTags: []string{"tag:hr-webserver"}, + }, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, Namespace: Namespace{Name: "joe"}, - HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"hr-web2\",\"RequestTags\":[\"tag:hr-webserver\"]}", - ), + HostInfo: HostInfo{ + OS: "centos", + Hostname: "hr-web2", + RequestTags: []string{"tag:hr-webserver"}, + }, }, { IPAddresses: MachineAddresses{ diff --git a/cli_test.go b/cli_test.go index 71f2bea..ab98167 100644 --- a/cli_test.go +++ b/cli_test.go @@ -35,7 +35,4 @@ func (s *Suite) TestRegisterMachine(c *check.C) { ) c.Assert(err, check.IsNil) c.Assert(machineAfterRegistering.Registered, check.Equals, true) - - _, err = machineAfterRegistering.GetHostInfo() - c.Assert(err, check.IsNil) } diff --git a/machine_test.go b/machine_test.go index e9c91f8..e20308f 100644 --- a/machine_test.go +++ b/machine_test.go @@ -35,10 +35,7 @@ func (s *Suite) TestGetMachine(c *check.C) { } app.db.Save(machine) - machineFromDB, err := app.GetMachine("test", "testmachine") - c.Assert(err, check.IsNil) - - _, err = machineFromDB.GetHostInfo() + _, err = app.GetMachine("test", "testmachine") c.Assert(err, check.IsNil) } @@ -65,10 +62,7 @@ func (s *Suite) TestGetMachineByID(c *check.C) { } app.db.Save(&machine) - machineByID, err := app.GetMachineByID(0) - c.Assert(err, check.IsNil) - - _, err = machineByID.GetHostInfo() + _, err = app.GetMachineByID(0) c.Assert(err, check.IsNil) } @@ -146,9 +140,6 @@ func (s *Suite) TestListPeers(c *check.C) { machine0ByID, err := app.GetMachineByID(0) c.Assert(err, check.IsNil) - _, err = machine0ByID.GetHostInfo() - c.Assert(err, check.IsNil) - peersOfMachine0, err := app.ListPeers(machine0ByID) c.Assert(err, check.IsNil) @@ -219,9 +210,6 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { c.Logf("Machine(%v), namespace: %v", testMachine.Name, testMachine.Namespace) c.Assert(err, check.IsNil) - _, err = testMachine.GetHostInfo() - c.Assert(err, check.IsNil) - machines, err := app.ListMachines() c.Assert(err, check.IsNil) diff --git a/routes_test.go b/routes_test.go index 94bda45..87fc079 100644 --- a/routes_test.go +++ b/routes_test.go @@ -1,10 +1,7 @@ package headscale import ( - "encoding/json" - "gopkg.in/check.v1" - "gorm.io/datatypes" "inet.af/netaddr" "tailscale.com/tailcfg" ) @@ -25,8 +22,6 @@ func (s *Suite) TestGetRoutes(c *check.C) { hostInfo := tailcfg.Hostinfo{ RoutableIPs: []netaddr.IPPrefix{route}, } - hostinfo, err := json.Marshal(hostInfo) - c.Assert(err, check.IsNil) machine := Machine{ ID: 0, @@ -38,7 +33,7 @@ func (s *Suite) TestGetRoutes(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(hostinfo), + HostInfo: HostInfo(hostInfo), } app.db.Save(&machine) @@ -79,8 +74,6 @@ func (s *Suite) TestGetEnableRoutes(c *check.C) { hostInfo := tailcfg.Hostinfo{ RoutableIPs: []netaddr.IPPrefix{route, route2}, } - hostinfo, err := json.Marshal(hostInfo) - c.Assert(err, check.IsNil) machine := Machine{ ID: 0, @@ -92,7 +85,7 @@ func (s *Suite) TestGetEnableRoutes(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(hostinfo), + HostInfo: HostInfo(hostInfo), } app.db.Save(&machine) From a455a874add8b559eaa287c4d380ecda0196b357 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 1 Mar 2022 21:01:46 +0100 Subject: [PATCH 135/204] feat(acls): normalize the group name --- acls.go | 46 ++++++++++++++++----- acls_test.go | 115 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 124 insertions(+), 37 deletions(-) diff --git a/acls.go b/acls.go index 1a597c2..7b93ad7 100644 --- a/acls.go +++ b/acls.go @@ -160,7 +160,7 @@ func (h *Headscale) generateACLPolicySrcIP( aclPolicy ACLPolicy, u string, ) ([]string, error) { - return expandAlias(machines, aclPolicy, u) + return expandAlias(machines, aclPolicy, u, h.cfg.OIDC.StripEmaildomain) } func (h *Headscale) generateACLPolicyDestPorts( @@ -186,7 +186,12 @@ func (h *Headscale) generateACLPolicyDestPorts( alias = fmt.Sprintf("%s:%s", tokens[0], tokens[1]) } - expanded, err := expandAlias(machines, aclPolicy, alias) + expanded, err := expandAlias( + machines, + aclPolicy, + alias, + h.cfg.OIDC.StripEmaildomain, + ) if err != nil { return nil, err } @@ -218,6 +223,7 @@ func expandAlias( machines []Machine, aclPolicy ACLPolicy, alias string, + stripEmailDomain bool, ) ([]string, error) { ips := []string{} if alias == "*" { @@ -225,7 +231,7 @@ func expandAlias( } if strings.HasPrefix(alias, "group:") { - namespaces, err := expandGroup(aclPolicy, alias) + namespaces, err := expandGroup(aclPolicy, alias, stripEmailDomain) if err != nil { return ips, err } @@ -240,7 +246,7 @@ func expandAlias( } if strings.HasPrefix(alias, "tag:") { - owners, err := expandTagOwners(aclPolicy, alias) + owners, err := expandTagOwners(aclPolicy, alias, stripEmailDomain) if err != nil { return ips, err } @@ -396,7 +402,11 @@ func filterMachinesByNamespace(machines []Machine, namespace string) []Machine { // expandTagOwners will return a list of namespace. An owner can be either a namespace or a group // a group cannot be composed of groups. -func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { +func expandTagOwners( + aclPolicy ACLPolicy, + tag string, + stripEmailDomain bool, +) ([]string, error) { var owners []string ows, ok := aclPolicy.TagOwners[tag] if !ok { @@ -408,7 +418,7 @@ func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { } for _, owner := range ows { if strings.HasPrefix(owner, "group:") { - gs, err := expandGroup(aclPolicy, owner) + gs, err := expandGroup(aclPolicy, owner, stripEmailDomain) if err != nil { return []string{}, err } @@ -423,8 +433,13 @@ func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { // expandGroup will return the list of namespace inside the group // after some validation. -func expandGroup(aclPolicy ACLPolicy, group string) ([]string, error) { - groups, ok := aclPolicy.Groups[group] +func expandGroup( + aclPolicy ACLPolicy, + group string, + stripEmailDomain bool, +) ([]string, error) { + outGroups := []string{} + aclGroups, ok := aclPolicy.Groups[group] if !ok { return []string{}, fmt.Errorf( "group %v isn't registered. %w", @@ -432,14 +447,23 @@ func expandGroup(aclPolicy ACLPolicy, group string) ([]string, error) { errInvalidGroup, ) } - for _, g := range groups { - if strings.HasPrefix(g, "group:") { + for _, group := range aclGroups { + if strings.HasPrefix(group, "group:") { return []string{}, fmt.Errorf( "%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup, ) } + grp, err := NormalizeNamespaceName(group, stripEmailDomain) + if err != nil { + return []string{}, fmt.Errorf( + "failed to normalize group %q, err: %w", + group, + errInvalidGroup, + ) + } + outGroups = append(outGroups, grp) } - return groups, nil + return outGroups, nil } diff --git a/acls_test.go b/acls_test.go index 9f0432a..6cee02c 100644 --- a/acls_test.go +++ b/acls_test.go @@ -430,8 +430,9 @@ func (s *Suite) TestPortGroup(c *check.C) { func Test_expandGroup(t *testing.T) { type args struct { - aclPolicy ACLPolicy - group string + aclPolicy ACLPolicy + group string + stripEmailDomain bool } tests := []struct { name string @@ -448,7 +449,8 @@ func Test_expandGroup(t *testing.T) { "group:foo": []string{"user2", "user3"}, }, }, - group: "group:test", + group: "group:test", + stripEmailDomain: true, }, want: []string{"user1", "user2", "user3"}, wantErr: false, @@ -462,15 +464,54 @@ func Test_expandGroup(t *testing.T) { "group:foo": []string{"user2", "user3"}, }, }, - group: "group:undefined", + group: "group:undefined", + stripEmailDomain: true, }, want: []string{}, wantErr: true, }, + { + name: "Expand emails in group", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{ + "group:admin": []string{ + "joe.bar@gmail.com", + "john.doe@yahoo.fr", + }, + }, + }, + group: "group:admin", + stripEmailDomain: true, + }, + want: []string{"joe.bar", "john.doe"}, + wantErr: false, + }, + { + name: "Expand emails in group", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{ + "group:admin": []string{ + "joe.bar@gmail.com", + "john.doe@yahoo.fr", + }, + }, + }, + group: "group:admin", + stripEmailDomain: false, + }, + want: []string{"joe.bar.gmail.com", "john.doe.yahoo.fr"}, + wantErr: false, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := expandGroup(test.args.aclPolicy, test.args.group) + got, err := expandGroup( + test.args.aclPolicy, + test.args.group, + test.args.stripEmailDomain, + ) if (err != nil) != test.wantErr { t.Errorf("expandGroup() error = %v, wantErr %v", err, test.wantErr) @@ -485,8 +526,9 @@ func Test_expandGroup(t *testing.T) { func Test_expandTagOwners(t *testing.T) { type args struct { - aclPolicy ACLPolicy - tag string + aclPolicy ACLPolicy + tag string + stripEmailDomain bool } tests := []struct { name string @@ -500,7 +542,8 @@ func Test_expandTagOwners(t *testing.T) { aclPolicy: ACLPolicy{ TagOwners: TagOwners{"tag:test": []string{"user1"}}, }, - tag: "tag:test", + tag: "tag:test", + stripEmailDomain: true, }, want: []string{"user1"}, wantErr: false, @@ -512,7 +555,8 @@ func Test_expandTagOwners(t *testing.T) { Groups: Groups{"group:foo": []string{"user1", "user2"}}, TagOwners: TagOwners{"tag:test": []string{"group:foo"}}, }, - tag: "tag:test", + tag: "tag:test", + stripEmailDomain: true, }, want: []string{"user1", "user2"}, wantErr: false, @@ -524,7 +568,8 @@ func Test_expandTagOwners(t *testing.T) { Groups: Groups{"group:foo": []string{"user1", "user2"}}, TagOwners: TagOwners{"tag:test": []string{"group:foo", "user3"}}, }, - tag: "tag:test", + tag: "tag:test", + stripEmailDomain: true, }, want: []string{"user1", "user2", "user3"}, wantErr: false, @@ -535,7 +580,8 @@ func Test_expandTagOwners(t *testing.T) { aclPolicy: ACLPolicy{ TagOwners: TagOwners{"tag:foo": []string{"group:foo", "user1"}}, }, - tag: "tag:test", + tag: "tag:test", + stripEmailDomain: true, }, want: []string{}, wantErr: true, @@ -547,7 +593,8 @@ func Test_expandTagOwners(t *testing.T) { Groups: Groups{"group:bar": []string{"user1", "user2"}}, TagOwners: TagOwners{"tag:test": []string{"group:foo", "user2"}}, }, - tag: "tag:test", + tag: "tag:test", + stripEmailDomain: true, }, want: []string{}, wantErr: true, @@ -555,7 +602,11 @@ func Test_expandTagOwners(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := expandTagOwners(test.args.aclPolicy, test.args.tag) + got, err := expandTagOwners( + test.args.aclPolicy, + test.args.tag, + test.args.stripEmailDomain, + ) if (err != nil) != test.wantErr { t.Errorf("expandTagOwners() error = %v, wantErr %v", err, test.wantErr) @@ -717,9 +768,10 @@ func Test_listMachinesInNamespace(t *testing.T) { // nolint func Test_expandAlias(t *testing.T) { type args struct { - machines []Machine - aclPolicy ACLPolicy - alias string + machines []Machine + aclPolicy ACLPolicy + alias string + stripEmailDomain bool } tests := []struct { name string @@ -739,7 +791,8 @@ func Test_expandAlias(t *testing.T) { }, }, }, - aclPolicy: ACLPolicy{}, + aclPolicy: ACLPolicy{}, + stripEmailDomain: true, }, want: []string{"*"}, wantErr: false, @@ -777,6 +830,7 @@ func Test_expandAlias(t *testing.T) { aclPolicy: ACLPolicy{ Groups: Groups{"group:accountant": []string{"joe", "marc"}}, }, + stripEmailDomain: true, }, want: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, wantErr: false, @@ -814,6 +868,7 @@ func Test_expandAlias(t *testing.T) { aclPolicy: ACLPolicy{ Groups: Groups{"group:accountant": []string{"joe", "marc"}}, }, + stripEmailDomain: true, }, want: []string{}, wantErr: true, @@ -821,9 +876,10 @@ func Test_expandAlias(t *testing.T) { { name: "simple ipaddress", args: args{ - alias: "10.0.0.3", - machines: []Machine{}, - aclPolicy: ACLPolicy{}, + alias: "10.0.0.3", + machines: []Machine{}, + aclPolicy: ACLPolicy{}, + stripEmailDomain: true, }, want: []string{"10.0.0.3"}, wantErr: false, @@ -838,6 +894,7 @@ func Test_expandAlias(t *testing.T) { "homeNetwork": netaddr.MustParseIPPrefix("192.168.1.0/24"), }, }, + stripEmailDomain: true, }, want: []string{"192.168.1.0/24"}, wantErr: false, @@ -845,9 +902,10 @@ func Test_expandAlias(t *testing.T) { { name: "simple host", args: args{ - alias: "10.0.0.1", - machines: []Machine{}, - aclPolicy: ACLPolicy{}, + alias: "10.0.0.1", + machines: []Machine{}, + aclPolicy: ACLPolicy{}, + stripEmailDomain: true, }, want: []string{"10.0.0.1"}, wantErr: false, @@ -855,9 +913,10 @@ func Test_expandAlias(t *testing.T) { { name: "simple CIDR", args: args{ - alias: "10.0.0.0/16", - machines: []Machine{}, - aclPolicy: ACLPolicy{}, + alias: "10.0.0.0/16", + machines: []Machine{}, + aclPolicy: ACLPolicy{}, + stripEmailDomain: true, }, want: []string{"10.0.0.0/16"}, wantErr: false, @@ -901,6 +960,7 @@ func Test_expandAlias(t *testing.T) { aclPolicy: ACLPolicy{ TagOwners: TagOwners{"tag:hr-webserver": []string{"joe"}}, }, + stripEmailDomain: true, }, want: []string{"100.64.0.1", "100.64.0.2"}, wantErr: false, @@ -941,6 +1001,7 @@ func Test_expandAlias(t *testing.T) { "tag:accountant-webserver": []string{"group:accountant"}, }, }, + stripEmailDomain: true, }, want: []string{}, wantErr: true, @@ -984,6 +1045,7 @@ func Test_expandAlias(t *testing.T) { aclPolicy: ACLPolicy{ TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, + stripEmailDomain: true, }, want: []string{"100.64.0.4"}, wantErr: false, @@ -995,6 +1057,7 @@ func Test_expandAlias(t *testing.T) { test.args.machines, test.args.aclPolicy, test.args.alias, + test.args.stripEmailDomain, ) if (err != nil) != test.wantErr { t.Errorf("expandAlias() error = %v, wantErr %v", err, test.wantErr) From b2dca80e7a2f0364d476972dc0d6de2e653939e5 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 1 Mar 2022 21:16:33 +0100 Subject: [PATCH 136/204] docs: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2b93ef..c1b3ee8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ **Features**: - Add support for writing ACL files with YAML [#359](https://github.com/juanfont/headscale/pull/359) +- Users can now use emails in ACL's groups [#372](https://github.com/juanfont/headscale/issues/372) **Changes**: From 361b4f7f4f48fc399da149ffc2bf4b8d5e76c074 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 1 Mar 2022 22:43:25 +0100 Subject: [PATCH 137/204] fix(machine): allow to use * in ACL sources --- machine.go | 20 ++++- machine_test.go | 205 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 223 insertions(+), 2 deletions(-) diff --git a/machine.go b/machine.go index 3106d0b..479380a 100644 --- a/machine.go +++ b/machine.go @@ -173,6 +173,12 @@ func getFilteredByACLPeers( machine.IPAddresses.ToStringSlice(), peer.IPAddresses.ToStringSlice(), ) || // match source and destination + matchSourceAndDestinationWithRule( + rule.SrcIPs, + dst, + peer.IPAddresses.ToStringSlice(), + machine.IPAddresses.ToStringSlice(), + ) || // match return path matchSourceAndDestinationWithRule( rule.SrcIPs, dst, @@ -182,9 +188,21 @@ func getFilteredByACLPeers( matchSourceAndDestinationWithRule( rule.SrcIPs, dst, + []string{"*"}, + []string{"*"}, + ) || // match source and all destination + matchSourceAndDestinationWithRule( + rule.SrcIPs, + dst, + []string{"*"}, peer.IPAddresses.ToStringSlice(), + ) || // match source and all destination + matchSourceAndDestinationWithRule( + rule.SrcIPs, + dst, + []string{"*"}, machine.IPAddresses.ToStringSlice(), - ) { // match return path + ) { // match all sources and source peers[peer.ID] = peer } } diff --git a/machine_test.go b/machine_test.go index e9c91f8..ed95aaf 100644 --- a/machine_test.go +++ b/machine_test.go @@ -296,6 +296,7 @@ func (s *Suite) TestSerdeAddressStrignSlice(c *check.C) { } } +// nolint func Test_getFilteredByACLPeers(t *testing.T) { type args struct { machines []Machine @@ -443,7 +444,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, machine: &Machine{ // current machine - ID: 1, + ID: 2, IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "marc"}, }, @@ -456,6 +457,208 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, }, + { + name: "rules allows all hosts to reach one destination", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + { + SrcIPs: []string{"*"}, + DstPorts: []tailcfg.NetPortRange{ + {IP: "100.64.0.2"}, + }, + }, + }, + machine: &Machine{ // current machine + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, + }, + }, + want: Machines{ + { + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, + }, + }, + }, + { + name: "rules allows all hosts to reach one destination, destination can reach all hosts", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + { + SrcIPs: []string{"*"}, + DstPorts: []tailcfg.NetPortRange{ + {IP: "100.64.0.2"}, + }, + }, + }, + machine: &Machine{ // current machine + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, + }, + }, + want: Machines{ + { + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, + }, + }, + }, + { + name: "rule allows all hosts to reach all destinations", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + { + SrcIPs: []string{"*"}, + DstPorts: []tailcfg.NetPortRange{ + {IP: "*"}, + }, + }, + }, + machine: &Machine{ // current machine + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + }, + want: Machines{ + { + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + }, + { + name: "without rule all communications are forbidden", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + }, + machine: &Machine{ // current machine + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + }, + want: Machines{}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 77fe0b01f7d42f51e67ea0307cf52c2c975844ab Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 1 Mar 2022 22:50:22 +0100 Subject: [PATCH 138/204] docs: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1b3ee8..d75388b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ **Changes**: - Fix a bug were the same IP could be assigned to multiple hosts if joined in quick succession [#346](https://github.com/juanfont/headscale/pull/346) +- Fix a limitation in the ACLs that prevented users to write rules with `*` as source [#374](https://github.com/juanfont/headscale/issues/374) **0.14.0 (2022-02-24):** From dbb2af0238161ed4cbdf3096fc893910bb1bbfbe Mon Sep 17 00:00:00 2001 From: zakaria Date: Wed, 2 Mar 2022 14:20:04 +1000 Subject: [PATCH 139/204] feat(aliases): add aliases for `route` command - `r` is alias for `route` command - `ls`, or `show` is alias for `list` subcommand --- cmd/headscale/cli/routes.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmd/headscale/cli/routes.go b/cmd/headscale/cli/routes.go index ced1a0b..dc060fb 100644 --- a/cmd/headscale/cli/routes.go +++ b/cmd/headscale/cli/routes.go @@ -35,13 +35,15 @@ func init() { } var routesCmd = &cobra.Command{ - Use: "routes", - Short: "Manage the routes of Headscale", + Use: "routes", + Short: "Manage the routes of Headscale", + Aliases: []string{"r", "route"}, } var listRoutesCmd = &cobra.Command{ - Use: "list", - Short: "List routes advertised and enabled by a given node", + Use: "list", + Short: "List routes advertised and enabled by a given node", + Aliases: []string{"ls", "show"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") From 21eee912a39ad4a9898fba5de340a5df0db16ca4 Mon Sep 17 00:00:00 2001 From: zakaria Date: Wed, 2 Mar 2022 14:27:34 +1000 Subject: [PATCH 140/204] feat(aliases): add aliases for `nodes` command - `node`, `machine`, `machines` are aliases for `nodes` command - `ls`, `show` aliases for `list` subcommand - `logout`, `exp`, `e` are aliases for `expire` subcommand - `del` is an alias for `delete` subcommand --- cmd/headscale/cli/nodes.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cmd/headscale/cli/nodes.go b/cmd/headscale/cli/nodes.go index a05339c..0abe87b 100644 --- a/cmd/headscale/cli/nodes.go +++ b/cmd/headscale/cli/nodes.go @@ -49,8 +49,9 @@ func init() { } var nodeCmd = &cobra.Command{ - Use: "nodes", - Short: "Manage the nodes of Headscale", + Use: "nodes", + Short: "Manage the nodes of Headscale", + Aliases: []string{"node", "machine", "machines"}, } var registerNodeCmd = &cobra.Command{ @@ -104,8 +105,9 @@ var registerNodeCmd = &cobra.Command{ } var listNodesCmd = &cobra.Command{ - Use: "list", - Short: "List nodes", + Use: "list", + Short: "List nodes", + Aliases: []string{"ls", "show"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") namespace, err := cmd.Flags().GetString("namespace") @@ -164,7 +166,7 @@ var expireNodeCmd = &cobra.Command{ Use: "expire", Short: "Expire (log out) a machine in your network", Long: "Expiring a node will keep the node in the database and force it to reauthenticate.", - Aliases: []string{"logout"}, + Aliases: []string{"logout", "exp", "e"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") @@ -206,8 +208,9 @@ var expireNodeCmd = &cobra.Command{ } var deleteNodeCmd = &cobra.Command{ - Use: "delete", - Short: "Delete a node", + Use: "delete", + Short: "Delete a node", + Aliases: []string{"del"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") From aff6b84250868beee6a8df2aa764b8f19b0ad156 Mon Sep 17 00:00:00 2001 From: zakaria Date: Wed, 2 Mar 2022 14:29:33 +1000 Subject: [PATCH 141/204] feat(aliases): add 'gen' alias for 'generate' command --- cmd/headscale/cli/generate.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/headscale/cli/generate.go b/cmd/headscale/cli/generate.go index 2484414..3590641 100644 --- a/cmd/headscale/cli/generate.go +++ b/cmd/headscale/cli/generate.go @@ -13,8 +13,9 @@ func init() { } var generateCmd = &cobra.Command{ - Use: "generate", - Short: "Generate commands", + Use: "generate", + Short: "Generate commands", + Aliases: []string{"gen"}, } var generatePrivateKeyCmd = &cobra.Command{ From 5310f8692bf071a20dcda81e96c9321b5ecdb53b Mon Sep 17 00:00:00 2001 From: zakaria Date: Wed, 2 Mar 2022 14:35:20 +1000 Subject: [PATCH 142/204] feat(aliases): add aliases for `namespaces` command - `namespace`, `ns`, `user`, `users` are aliases for `namespaces` command - `c`, `new` are aliases for the `create` subcommand - `delete` is an alias for the `destroy` subcommand - `mv` is an alias for the `rename` subcommand - `ls`, `show` are aliases for the `list` subcommand --- cmd/headscale/cli/namespaces.go | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/cmd/headscale/cli/namespaces.go b/cmd/headscale/cli/namespaces.go index 361e9be..729e213 100644 --- a/cmd/headscale/cli/namespaces.go +++ b/cmd/headscale/cli/namespaces.go @@ -25,13 +25,15 @@ const ( ) var namespaceCmd = &cobra.Command{ - Use: "namespaces", - Short: "Manage the namespaces of Headscale", + Use: "namespaces", + Short: "Manage the namespaces of Headscale", + Aliases: []string{"namespace", "ns", "user", "users"}, } var createNamespaceCmd = &cobra.Command{ - Use: "create NAME", - Short: "Creates a new namespace", + Use: "create NAME", + Short: "Creates a new namespace", + Aliases: []string{"c", "new"}, Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return errMissingParameter @@ -72,8 +74,9 @@ var createNamespaceCmd = &cobra.Command{ } var destroyNamespaceCmd = &cobra.Command{ - Use: "destroy NAME", - Short: "Destroys a namespace", + Use: "destroy NAME", + Short: "Destroys a namespace", + Aliases: []string{"delete"}, Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return errMissingParameter @@ -144,8 +147,9 @@ var destroyNamespaceCmd = &cobra.Command{ } var listNamespacesCmd = &cobra.Command{ - Use: "list", - Short: "List all the namespaces", + Use: "list", + Short: "List all the namespaces", + Aliases: []string{"ls", "show"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") @@ -197,8 +201,9 @@ var listNamespacesCmd = &cobra.Command{ } var renameNamespaceCmd = &cobra.Command{ - Use: "rename OLD_NAME NEW_NAME", - Short: "Renames a namespace", + Use: "rename OLD_NAME NEW_NAME", + Short: "Renames a namespace", + Aliases: []string{"mv"}, Args: func(cmd *cobra.Command, args []string) error { expectedArguments := 2 if len(args) < expectedArguments { From 052dbfe4403028b6a7356a3b5daf78392b4e14f7 Mon Sep 17 00:00:00 2001 From: zakaria Date: Wed, 2 Mar 2022 15:31:11 +1000 Subject: [PATCH 143/204] feat(aliases): add aliases for `apikeys` command - `apikey`, `api` are aliases for `apikeys` command - `ls`, `show` are aliases for `list` subcommand - `c`, `new` are aliases for `create` subcommand - `revoke`, `exp`, `e` are aliases for the `expire` subcommand --- cmd/headscale/cli/api_key.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/cmd/headscale/cli/api_key.go b/cmd/headscale/cli/api_key.go index 975149f..06099aa 100644 --- a/cmd/headscale/cli/api_key.go +++ b/cmd/headscale/cli/api_key.go @@ -36,13 +36,15 @@ func init() { } var apiKeysCmd = &cobra.Command{ - Use: "apikeys", - Short: "Handle the Api keys in Headscale", + Use: "apikeys", + Short: "Handle the Api keys in Headscale", + Aliases: []string{"apikey", "api"}, } var listAPIKeys = &cobra.Command{ - Use: "list", - Short: "List the Api keys for headscale", + Use: "list", + Short: "List the Api keys for headscale", + Aliases: []string{"ls", "show"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") @@ -107,6 +109,7 @@ var createAPIKeyCmd = &cobra.Command{ Creates a new Api key, the Api key is only visible on creation and cannot be retrieved again. If you loose a key, create a new one and revoke (expire) the old one.`, + Aliases: []string{"c", "new"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") @@ -144,7 +147,7 @@ If you loose a key, create a new one and revoke (expire) the old one.`, var expireAPIKeyCmd = &cobra.Command{ Use: "expire", Short: "Expire an ApiKey", - Aliases: []string{"revoke"}, + Aliases: []string{"revoke", "exp", "e"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") From 12b3b5f8f10ae9d4ff2044e0552a493c16d4739b Mon Sep 17 00:00:00 2001 From: zakaria Date: Wed, 2 Mar 2022 15:39:30 +1000 Subject: [PATCH 144/204] feat(aliases): add aliases for `preauthkeys` command - `preauthkey`, `authkey`, `pre` are aliases for `preauthkey` command - `ls`, `show` are aliases for `list` subcommand - `c`, `new` are aliases for `create` subcommand - `revoke`, `exp`, `e` are aliases for `expire` subcommand --- cmd/headscale/cli/preauthkeys.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/cmd/headscale/cli/preauthkeys.go b/cmd/headscale/cli/preauthkeys.go index 580184f..950cbcc 100644 --- a/cmd/headscale/cli/preauthkeys.go +++ b/cmd/headscale/cli/preauthkeys.go @@ -35,13 +35,15 @@ func init() { } var preauthkeysCmd = &cobra.Command{ - Use: "preauthkeys", - Short: "Handle the preauthkeys in Headscale", + Use: "preauthkeys", + Short: "Handle the preauthkeys in Headscale", + Aliases: []string{"preauthkey", "authkey", "pre"}, } var listPreAuthKeys = &cobra.Command{ - Use: "list", - Short: "List the preauthkeys for this namespace", + Use: "list", + Short: "List the preauthkeys for this namespace", + Aliases: []string{"ls", "show"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") @@ -118,8 +120,9 @@ var listPreAuthKeys = &cobra.Command{ } var createPreAuthKeyCmd = &cobra.Command{ - Use: "create", - Short: "Creates a new preauthkey in the specified namespace", + Use: "create", + Short: "Creates a new preauthkey in the specified namespace", + Aliases: []string{"c", "new"}, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") @@ -172,8 +175,9 @@ var createPreAuthKeyCmd = &cobra.Command{ } var expirePreAuthKeyCmd = &cobra.Command{ - Use: "expire KEY", - Short: "Expire a preauthkey", + Use: "expire KEY", + Short: "Expire a preauthkey", + Aliases: []string{"revoke", "exp", "e"}, Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return errMissingParameter From 86ade72c193626560ea80b327510af91f1a12890 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 1 Mar 2022 18:51:56 +0000 Subject: [PATCH 145/204] Remove err check --- oidc.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/oidc.go b/oidc.go index 8e89e27..f7cb249 100644 --- a/oidc.go +++ b/oidc.go @@ -216,16 +216,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { } // retrieve machine information if it exist - machine, err := h.GetMachineByMachineKey(machineKey) - if err != nil { - log.Error().Msg("machine key not found in database") - ctx.String( - http.StatusInternalServerError, - "could not get machine info from database", - ) - - return - } + machine, _ := h.GetMachineByMachineKey(machineKey) if machine != nil { log.Trace(). From ec4dc68524b5396443e3a6b25d546d3855ad2c2f Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 2 Mar 2022 06:55:21 +0000 Subject: [PATCH 146/204] Use correct machinekey format for oidc reg --- oidc.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/oidc.go b/oidc.go index f7cb249..c200f5e 100644 --- a/oidc.go +++ b/oidc.go @@ -193,10 +193,12 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - machineKeyStr, machineKeyOK := machineKeyIf.(string) + machineKeyFromCache, machineKeyOK := machineKeyIf.(string) var machineKey key.MachinePublic - err = machineKey.UnmarshalText([]byte(MachinePublicKeyEnsurePrefix(machineKeyStr))) + err = machineKey.UnmarshalText( + []byte(MachinePublicKeyEnsurePrefix(machineKeyFromCache)), + ) if err != nil { log.Error(). Msg("could not parse machine public key") @@ -295,6 +297,8 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } + machineKeyStr := MachinePublicKeyStripPrefix(machineKey) + _, err = h.RegisterMachineFromAuthCallback( machineKeyStr, namespace.Name, From ef422e69882f4c1ba0e04bc8019350e41fdabd59 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 2 Mar 2022 07:15:20 +0000 Subject: [PATCH 147/204] Protect against expiry nil --- api.go | 1 + machine.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api.go b/api.go index 9b8fafd..3b3b675 100644 --- a/api.go +++ b/api.go @@ -144,6 +144,7 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { Name: req.Hostinfo.Hostname, NodeKey: NodePublicKeyStripPrefix(req.NodeKey), LastSeen: &now, + Expiry: &time.Time{}, } if !req.Expiry.IsZero() { diff --git a/machine.go b/machine.go index bd842ae..c9370c2 100644 --- a/machine.go +++ b/machine.go @@ -117,7 +117,7 @@ func (machine Machine) isExpired() bool { // If Expiry is not set, the client has not indicated that // it wants an expiry time, it is therefor considered // to mean "not expired" - if machine.Expiry.IsZero() { + if machine.Expiry == nil || machine.Expiry.IsZero() { return false } From 1f8c7f427b82f6ff1259c4b35eb9969e90880d1d Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 2 Mar 2022 07:29:40 +0000 Subject: [PATCH 148/204] Add comment --- oidc.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/oidc.go b/oidc.go index c200f5e..987bc8b 100644 --- a/oidc.go +++ b/oidc.go @@ -218,6 +218,9 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { } // retrieve machine information if it exist + // The error is not important, because if it does not + // exist, then this is a new machine and we will move + // on to registration. machine, _ := h.GetMachineByMachineKey(machineKey) if machine != nil { From c80e364f02e2dee7cab996ad13f14a82a7e65fff Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 2 Mar 2022 08:15:14 +0000 Subject: [PATCH 149/204] Remove always nil error --- acls.go | 10 ++++------ acls_test.go | 13 +------------ 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/acls.go b/acls.go index 2666a85..84063a1 100644 --- a/acls.go +++ b/acls.go @@ -267,10 +267,8 @@ func expandAlias( // if alias is a namespace nodes := filterMachinesByNamespace(machines, alias) - nodes, err := excludeCorrectlyTaggedNodes(aclPolicy, nodes, alias) - if err != nil { - return ips, err - } + nodes = excludeCorrectlyTaggedNodes(aclPolicy, nodes, alias) + for _, n := range nodes { ips = append(ips, n.IPAddresses.ToStringSlice()...) } @@ -305,7 +303,7 @@ func excludeCorrectlyTaggedNodes( aclPolicy ACLPolicy, nodes []Machine, namespace string, -) ([]Machine, error) { +) []Machine { out := []Machine{} tags := []string{} for tag, ns := range aclPolicy.TagOwners { @@ -330,7 +328,7 @@ func excludeCorrectlyTaggedNodes( } } - return out, nil + return out } func expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { diff --git a/acls_test.go b/acls_test.go index c434ab7..9dcc40b 100644 --- a/acls_test.go +++ b/acls_test.go @@ -1142,7 +1142,6 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { Namespace: Namespace{Name: "joe"}, }, }, - wantErr: false, }, { name: "all nodes have invalid tags, don't exclude them", @@ -1212,25 +1211,15 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { Namespace: Namespace{Name: "joe"}, }, }, - wantErr: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := excludeCorrectlyTaggedNodes( + got := excludeCorrectlyTaggedNodes( test.args.aclPolicy, test.args.nodes, test.args.namespace, ) - if (err != nil) != test.wantErr { - t.Errorf( - "excludeCorrectlyTaggedNodes() error = %v, wantErr %v", - err, - test.wantErr, - ) - - return - } if !reflect.DeepEqual(got, test.want) { t.Errorf("excludeCorrectlyTaggedNodes() = %v, want %v", got, test.want) } From 0835bffc3c711901f45f3aac54f0f2a3c4ef9d57 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 2 Mar 2022 08:15:21 +0000 Subject: [PATCH 150/204] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1a992b..b6d0dc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Simplify the code behind registration of machines [#366](https://github.com/juanfont/headscale/pull/366) - Nodes are now only written to database if they are registrated successfully - Fix a limitation in the ACLs that prevented users to write rules with `*` as source [#374](https://github.com/juanfont/headscale/issues/374) +- Reduce the overhead of marshal/unmarshal for Hostinfo, routes and endpoints by using specific types in Machine [#371](https://github.com/juanfont/headscale/pull/371) ## 0.14.0 (2022-02-24) From 32ac690494bc54ade569da9b44f23990e6b8d875 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 2 Mar 2022 09:08:30 +0000 Subject: [PATCH 151/204] Update contributors.yml --- .github/workflows/contributors.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 4a73009..5419129 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -10,6 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - name: Delete upstream contributor branch + run: git push origin --delete update-contributors + - name: Create up-to-date contributors branch + run: git checkout -B update-contributors - uses: BobAnkh/add-contributors@v0.2.2 with: CONTRIBUTOR: "## Contributors" From 2b6a5173da1253150369515518dab017d9763296 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 2 Mar 2022 09:12:00 +0000 Subject: [PATCH 152/204] Allow upstream delete continue on failure --- .github/workflows/contributors.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 5419129..832abb9 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -11,6 +11,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Delete upstream contributor branch + # Allow continue on failure to account for when the + # upstream branch is deleted or does not exist. + continue-on-error: true run: git push origin --delete update-contributors - name: Create up-to-date contributors branch run: git checkout -B update-contributors From a614f158be3c3bea3193a572a7ddf220142718e5 Mon Sep 17 00:00:00 2001 From: zakaria Date: Wed, 2 Mar 2022 19:53:07 +1000 Subject: [PATCH 153/204] docs: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1b3ee8..eaf7ade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Add support for writing ACL files with YAML [#359](https://github.com/juanfont/headscale/pull/359) - Users can now use emails in ACL's groups [#372](https://github.com/juanfont/headscale/issues/372) +- Add shorthand aliases for commands and subcommands [#376](https://github.com/juanfont/headscale/pull/376) **Changes**: From dcc46af8de0d69d0d87e20b2a190ef5d8cd3bc47 Mon Sep 17 00:00:00 2001 From: Nico Rey Date: Wed, 2 Mar 2022 09:22:29 -0300 Subject: [PATCH 154/204] Changelog: add breaking change --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4445444..1186bad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ - Boundaries between Namespaces has been removed and all nodes can communicate by default [#357](https://github.com/juanfont/headscale/pull/357) - To limit access between nodes, use [ACLs](./docs/acls.md). +- `/metrics` is now a configurable host:port endpoint: [#344](https://github.com/juanfont/headscale/pull/344). You must update your `config.yaml` file to include: + ```yaml + metrics_listen_addr: 127.0.0.1:9090 + ``` ### Features From f9c0597875b1aa4f5d3f1ab27e69b1eb4bb20806 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 2 Mar 2022 13:40:37 +0000 Subject: [PATCH 155/204] Second contributor attempt --- .github/workflows/contributors.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 832abb9..aa0d926 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -17,6 +17,10 @@ jobs: run: git push origin --delete update-contributors - name: Create up-to-date contributors branch run: git checkout -B update-contributors + - name: Push empty contributors branch + run: git push origin update-contributors + - name: Switch back to main + run: git checkout main - uses: BobAnkh/add-contributors@v0.2.2 with: CONTRIBUTOR: "## Contributors" From e208ccc98269308a3494c71d03c2e44e312f1c3c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 13:42:25 +0000 Subject: [PATCH 156/204] docs(README): update contributors --- README.md | 68 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index fb5d969..c33dddf 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,13 @@ make build Juan Font
+ + Adrien +
+ Adrien Raffin-Caboisse +
+
Ward @@ -176,12 +183,14 @@ make build - - Adrien + + Justin
- Adrien Raffin-Caboisse + Justin Angel
Alessandro @@ -189,8 +198,6 @@ make build Alessandro (Ale) Segala
unreality/ @@ -198,6 +205,20 @@ make build unreality + + Nico/ +
+ Nico +
+
+ + e-zk/ +
+ e-zk +
+
Eugen @@ -212,6 +233,8 @@ make build Aaron Bieber
Fernando @@ -233,8 +256,6 @@ make build Michael G.
Paul @@ -256,6 +277,8 @@ make build Silver Bullet
Stefan @@ -264,10 +287,10 @@ make build - - lachy-2849/ + + fincac/
- lachy-2849 + fincac
@@ -277,8 +300,6 @@ make build thomas
Abraham @@ -300,6 +321,8 @@ make build Arthur Woimbée
Bryan @@ -321,8 +344,6 @@ make build Felix Yan
JJGadgets/ @@ -344,6 +365,8 @@ make build Jim Tittsler
Pierre @@ -365,8 +388,6 @@ make build Ryan Fowler
Shaanan @@ -388,6 +409,8 @@ make build Teteros
The @@ -409,8 +432,6 @@ make build Tjerk Woudsma
Zakhar @@ -432,13 +453,8 @@ make build derelm - - e-zk/ -
- e-zk -
-
ignoramous/ @@ -453,8 +469,6 @@ make build lion24
pernila/ From e301d0d1df118a2e8af392cd9c0b4745b4defff9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 13:44:26 +0000 Subject: [PATCH 157/204] docs(README): update contributors --- README.md | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index c33dddf..d9d050f 100644 --- a/README.md +++ b/README.md @@ -205,13 +205,6 @@ make build unreality - - Nico/ -
- Nico -
-
e-zk/ @@ -233,8 +226,6 @@ make build Aaron Bieber
Fernando @@ -242,6 +233,8 @@ make build Fernando De Lucchi
Hoàng @@ -277,8 +270,6 @@ make build Silver Bullet
Stefan @@ -286,6 +277,8 @@ make build Stefan Majer
fincac/ @@ -321,8 +314,6 @@ make build Arthur Woimbée
Bryan @@ -330,6 +321,8 @@ make build Bryan Stenson
Felix @@ -365,8 +358,6 @@ make build Jim Tittsler
Pierre @@ -374,6 +365,8 @@ make build Pierre Carru
rcursaru/ @@ -409,8 +402,6 @@ make build Teteros
The @@ -418,6 +409,8 @@ make build The Gitter Badger
Tianon @@ -453,8 +446,6 @@ make build derelm
ignoramous/ @@ -462,6 +453,8 @@ make build ignoramous
lion24/ From 4a4952899bdb5021d0d2d920b18bb38ea3ac92a2 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Wed, 2 Mar 2022 21:46:02 +0100 Subject: [PATCH 158/204] feat(acls): add some logs and skip error logs looks like the following ``` 2022-03-02T20:43:08Z DBG Expanding alias=app-test 2022-03-02T20:43:08Z DBG Expanding alias=kube-test 2022-03-02T20:43:08Z DBG Expanding alias=test 2022-03-02T20:43:08Z WRN No IPs found with the alias test 2022-03-02T20:43:08Z DBG Expanding alias=prod 2022-03-02T20:43:08Z WRN No IPs found with the alias prod 2022-03-02T20:43:08Z DBG Expanding alias=prod 2022-03-02T20:43:08Z WRN No IPs found with the alias prod ``` --- acls.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/acls.go b/acls.go index 84063a1..24aadf5 100644 --- a/acls.go +++ b/acls.go @@ -230,6 +230,10 @@ func expandAlias( return []string{"*"}, nil } + log.Debug(). + Str("alias", alias). + Msg("Expanding") + if strings.HasPrefix(alias, "group:") { namespaces, err := expandGroup(aclPolicy, alias, stripEmailDomain) if err != nil { @@ -293,7 +297,9 @@ func expandAlias( return []string{cidr.String()}, nil } - return ips, errInvalidUserSection + log.Warn().Msgf("No IPs found with the alias %v", alias) + + return ips, nil } // excludeCorrectlyTaggedNodes will remove from the list of input nodes the ones From 44a5372c531d8118a3b2b01167640003f8f16365 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Thu, 3 Mar 2022 23:52:25 +0100 Subject: [PATCH 159/204] fix(poll): Normalize hostname This function is called often. Normalization of the hostname will be written in database. --- poll.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/poll.go b/poll.go index 1ae8cd0..5723a3d 100644 --- a/poll.go +++ b/poll.go @@ -83,7 +83,18 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { Str("machine", machine.Name). Msg("Found machine in database") - machine.Name = req.Hostinfo.Hostname + hname, err := NormalizeNamespaceName( + req.Hostinfo.Hostname, + h.cfg.OIDC.StripEmaildomain, + ) + if err != nil { + log.Error(). + Caller(). + Str("func", "handleAuthKey"). + Str("hostinfo.name", req.Hostinfo.Hostname). + Err(err) + } + machine.Name = hname machine.HostInfo = HostInfo(*req.Hostinfo) machine.DiscoKey = DiscoPublicKeyStripPrefix(req.DiscoKey) now := time.Now().UTC() From 6f172a6e4ccb71e94c4daa7617408e0b5dc16e92 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Thu, 3 Mar 2022 23:53:08 +0100 Subject: [PATCH 160/204] fix(acls): remove dead error code --- acls.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/acls.go b/acls.go index 24aadf5..9548480 100644 --- a/acls.go +++ b/acls.go @@ -17,12 +17,11 @@ import ( ) const ( - errEmptyPolicy = Error("empty policy") - errInvalidAction = Error("invalid action") - errInvalidUserSection = Error("invalid user section") - errInvalidGroup = Error("invalid group") - errInvalidTag = Error("invalid tag") - errInvalidPortFormat = Error("invalid port format") + errEmptyPolicy = Error("empty policy") + errInvalidAction = Error("invalid action") + errInvalidGroup = Error("invalid group") + errInvalidTag = Error("invalid tag") + errInvalidPortFormat = Error("invalid port format") ) const ( From 897d480f4dd723ad0c197e9c9a782da8a4503c7f Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Fri, 4 Mar 2022 00:01:31 +0100 Subject: [PATCH 161/204] Add an embedded DERP server to Headscale This series of commit will be adding an embedded DERP server (and STUN) to Headscale, thus making it completely self-contained and not dependant in other infrastructure. --- app.go | 58 ++++++++++-- cmd/headscale/cli/utils.go | 6 ++ derp_embedded.go | 178 +++++++++++++++++++++++++++++++++++++ 3 files changed, 235 insertions(+), 7 deletions(-) create mode 100644 derp_embedded.go diff --git a/app.go b/app.go index 5818509..ee38ed9 100644 --- a/app.go +++ b/app.go @@ -119,6 +119,7 @@ type OIDCConfig struct { } type DERPConfig struct { + EmbeddedDERP bool URLs []url.URL Paths []string AutoUpdate bool @@ -141,7 +142,8 @@ type Headscale struct { dbDebug bool privateKey *key.MachinePrivate - DERPMap *tailcfg.DERPMap + DERPMap *tailcfg.DERPMap + EmbeddedDerpServer *EmbeddedDerpServer aclPolicy *ACLPolicy aclRules []tailcfg.FilterRule @@ -238,6 +240,38 @@ func NewHeadscale(cfg Config) (*Headscale, error) { } } + if cfg.DERP.EmbeddedDERP { + embeddedDerpServer, err := app.NewEmbeddedDerpServer() + if err != nil { + return nil, err + } + app.EmbeddedDerpServer = embeddedDerpServer + + // If we are using the embedded DERP, there is no reason to use Tailscale's DERP infrastructure + serverURL, err := url.Parse(app.cfg.ServerURL) + if err != nil { + return nil, err + } + app.DERPMap = &tailcfg.DERPMap{ + Regions: map[int]*tailcfg.DERPRegion{ + 1: { + RegionID: 1, + RegionCode: "headscale", + RegionName: "Headscale Embedded DERP", + Avoid: false, + Nodes: []*tailcfg.DERPNode{ + { + Name: "1a", + RegionID: 1, + HostName: serverURL.Host, + }, + }, + }, + }, + OmitDefaultRegions: false, + } + } + return &app, nil } @@ -454,6 +488,12 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { router.GET("/swagger", SwaggerUI) router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1) + if h.cfg.DERP.EmbeddedDERP { + router.Any("/derp", h.EmbeddedDerpHandler) + router.Any("/derp/probe", h.EmbeddedDerpProbeHandler) + router.Any("/bootstrap-dns", h.EmbeddedDerpBootstrapDNSHandler) + } + api := router.Group("/api") api.Use(h.httpAuthenticationMiddleware) { @@ -469,13 +509,17 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { func (h *Headscale) Serve() error { var err error - // Fetch an initial DERP Map before we start serving - h.DERPMap = GetDERPMap(h.cfg.DERP) + if h.cfg.DERP.EmbeddedDERP { + go h.ServeSTUN() + } else { + // Fetch an initial DERP Map before we start serving + h.DERPMap = GetDERPMap(h.cfg.DERP) - if h.cfg.DERP.AutoUpdate { - derpMapCancelChannel := make(chan struct{}) - defer func() { derpMapCancelChannel <- struct{}{} }() - go h.scheduledDERPMapUpdateWorker(derpMapCancelChannel) + if h.cfg.DERP.AutoUpdate { + derpMapCancelChannel := make(chan struct{}) + defer func() { derpMapCancelChannel <- struct{}{} }() + go h.scheduledDERPMapUpdateWorker(derpMapCancelChannel) + } } go h.expireEphemeralNodes(updateInterval) diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 97c2440..cff31f3 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -117,6 +117,12 @@ func LoadConfig(path string) error { } func GetDERPConfig() headscale.DERPConfig { + if viper.GetBool("derp.embedded_derp") { + return headscale.DERPConfig{ + EmbeddedDERP: true, + } + } + urlStrs := viper.GetStringSlice("derp.urls") urls := make([]url.URL, len(urlStrs)) diff --git a/derp_embedded.go b/derp_embedded.go new file mode 100644 index 0000000..0631fff --- /dev/null +++ b/derp_embedded.go @@ -0,0 +1,178 @@ +package headscale + +import ( + "context" + "encoding/json" + "fmt" + "net" + "net/http" + "strings" + "sync/atomic" + "time" + + "github.com/gin-gonic/gin" + "github.com/rs/zerolog/log" + "tailscale.com/derp" + "tailscale.com/net/stun" + "tailscale.com/types/key" +) + +// fastStartHeader is the header (with value "1") that signals to the HTTP +// server that the DERP HTTP client does not want the HTTP 101 response +// headers and it will begin writing & reading the DERP protocol immediately +// following its HTTP request. +const fastStartHeader = "Derp-Fast-Start" + +var ( + dnsCache atomic.Value // of []byte + bootstrapDNS = "derp.tailscale.com" +) + +type EmbeddedDerpServer struct { + tailscaleDerp *derp.Server +} + +func (h *Headscale) NewEmbeddedDerpServer() (*EmbeddedDerpServer, error) { + s := derp.NewServer(key.NodePrivate(*h.privateKey), log.Info().Msgf) + return &EmbeddedDerpServer{s}, nil + +} + +func (h *Headscale) EmbeddedDerpHandler(ctx *gin.Context) { + up := strings.ToLower(ctx.Request.Header.Get("Upgrade")) + if up != "websocket" && up != "derp" { + if up != "" { + log.Warn().Caller().Msgf("Weird websockets connection upgrade: %q", up) + } + ctx.String(http.StatusUpgradeRequired, "DERP requires connection upgrade") + return + } + + fastStart := ctx.Request.Header.Get(fastStartHeader) == "1" + + hijacker, ok := ctx.Writer.(http.Hijacker) + if !ok { + log.Error().Caller().Msg("DERP requires Hijacker interface from Gin") + ctx.String(http.StatusInternalServerError, "HTTP does not support general TCP support") + return + } + + netConn, conn, err := hijacker.Hijack() + if err != nil { + log.Error().Caller().Err(err).Msgf("Hijack failed") + ctx.String(http.StatusInternalServerError, "HTTP does not support general TCP support") + return + } + + if !fastStart { + pubKey := h.privateKey.Public() + fmt.Fprintf(conn, "HTTP/1.1 101 Switching Protocols\r\n"+ + "Upgrade: DERP\r\n"+ + "Connection: Upgrade\r\n"+ + "Derp-Version: %v\r\n"+ + "Derp-Public-Key: %s\r\n\r\n", + derp.ProtocolVersion, + pubKey.UntypedHexString()) + } + + h.EmbeddedDerpServer.tailscaleDerp.Accept(netConn, conn, netConn.RemoteAddr().String()) +} + +// EmbeddedDerpProbeHandler is the endpoint that js/wasm clients hit to measure +// DERP latency, since they can't do UDP STUN queries. +func (h *Headscale) EmbeddedDerpProbeHandler(ctx *gin.Context) { + switch ctx.Request.Method { + case "HEAD", "GET": + ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*") + default: + ctx.String(http.StatusMethodNotAllowed, "bogus probe method") + } +} + +func (h *Headscale) EmbeddedDerpBootstrapDNSHandler(ctx *gin.Context) { + ctx.Header("Content-Type", "application/json") + j, _ := dnsCache.Load().([]byte) + // Bootstrap DNS requests occur cross-regions, + // and are randomized per request, + // so keeping a connection open is pointlessly expensive. + ctx.Header("Connection", "close") + ctx.Writer.Write(j) +} + +// ServeSTUN starts a STUN server on udp/3478 +func (h *Headscale) ServeSTUN() { + pc, err := net.ListenPacket("udp", "0.0.0.0:3478") + if err != nil { + log.Fatal().Msgf("failed to open STUN listener: %v", err) + } + log.Printf("running STUN server on %v", pc.LocalAddr()) + serverSTUNListener(context.Background(), pc.(*net.UDPConn)) +} + +func serverSTUNListener(ctx context.Context, pc *net.UDPConn) { + var buf [64 << 10]byte + var ( + n int + ua *net.UDPAddr + err error + ) + for { + n, ua, err = pc.ReadFromUDP(buf[:]) + if err != nil { + if ctx.Err() != nil { + return + } + log.Printf("STUN ReadFrom: %v", err) + time.Sleep(time.Second) + continue + } + pkt := buf[:n] + if !stun.Is(pkt) { + continue + } + txid, err := stun.ParseBindingRequest(pkt) + if err != nil { + continue + } + + res := stun.Response(txid, ua.IP, uint16(ua.Port)) + pc.WriteTo(res, ua) + } +} + +// Shamelessly taken from +// https://github.com/tailscale/tailscale/blob/main/cmd/derper/bootstrap_dns.go +func refreshBootstrapDNSLoop() { + if bootstrapDNS == "" { + return + } + for { + refreshBootstrapDNS() + time.Sleep(10 * time.Minute) + } +} + +func refreshBootstrapDNS() { + if bootstrapDNS == "" { + return + } + dnsEntries := make(map[string][]net.IP) + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + names := strings.Split(bootstrapDNS, ",") + var r net.Resolver + for _, name := range names { + addrs, err := r.LookupIP(ctx, "ip", name) + if err != nil { + log.Printf("bootstrap DNS lookup %q: %v", name, err) + continue + } + dnsEntries[name] = addrs + } + j, err := json.MarshalIndent(dnsEntries, "", "\t") + if err != nil { + // leave the old values in place + return + } + dnsCache.Store(j) +} From 9d43f589ae5ac9b902247b5d00ec28cc632b9168 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Fri, 4 Mar 2022 00:04:28 +0100 Subject: [PATCH 162/204] Added missing deps --- go.mod | 3 +++ go.sum | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/go.mod b/go.mod index a121826..d6754f9 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,7 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect + github.com/akutz/memconn v0.1.0 // indirect github.com/atomicgo/cursor v0.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.1.2 // indirect @@ -100,6 +101,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.11 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect + github.com/mitchellh/go-ps v1.0.0 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -134,6 +136,7 @@ require ( golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect diff --git a/go.sum b/go.sum index 558d3d7..c23db38 100644 --- a/go.sum +++ b/go.sum @@ -82,6 +82,8 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= +github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A= +github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -205,6 +207,7 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= @@ -570,6 +573,8 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= @@ -1083,6 +1088,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M= +golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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= From 745696b310b921266a7242a18101e955acc7b6b1 Mon Sep 17 00:00:00 2001 From: zakaria Date: Fri, 4 Mar 2022 12:11:43 +1000 Subject: [PATCH 163/204] docs: fix mistake in ACME challenge type comment --- config-example.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-example.yaml b/config-example.yaml index c28b608..a8c3f28 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -123,7 +123,7 @@ tls_client_auth_mode: relaxed tls_letsencrypt_cache_dir: /var/lib/headscale/cache # Type of ACME challenge to use, currently supported types: -# HTTP-01 or TLS_ALPN-01 +# HTTP-01 or TLS-ALPN-01 # See [docs/tls.md](docs/tls.md) for more information tls_letsencrypt_challenge_type: HTTP-01 # When HTTP-01 challenge is chosen, letsencrypt must set up a From b342cf0240eac731db756399130d62382ca7ad28 Mon Sep 17 00:00:00 2001 From: e-zk Date: Fri, 4 Mar 2022 17:56:54 +1000 Subject: [PATCH 164/204] feat(windows): cleanup /apple endpoint - rename the gin function to AppleConfigMessage - use
 +  for code blocks
- add headscale heading
- reword some sections
---
 app.go                |  2 +-
 apple_mobileconfig.go | 17 +++++++++--------
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/app.go b/app.go
index 763fdfe..4c1d201 100644
--- a/app.go
+++ b/app.go
@@ -456,7 +456,7 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine {
 	router.POST("/machine/:id", h.RegistrationHandler)
 	router.GET("/oidc/register/:mkey", h.RegisterOIDC)
 	router.GET("/oidc/callback", h.OIDCCallback)
-	router.GET("/apple", h.AppleMobileConfig)
+	router.GET("/apple", h.AppleConfigMessage)
 	router.GET("/apple/:platform", h.ApplePlatformConfig)
 	router.GET("/swagger", SwaggerUI)
 	router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1)
diff --git a/apple_mobileconfig.go b/apple_mobileconfig.go
index 69f61a6..137276d 100644
--- a/apple_mobileconfig.go
+++ b/apple_mobileconfig.go
@@ -11,26 +11,27 @@ import (
 	"github.com/rs/zerolog/log"
 )
 
-// AppleMobileConfig shows a simple message in the browser to point to the CLI
-// Listens in /register.
-func (h *Headscale) AppleMobileConfig(ctx *gin.Context) {
+// AppleConfigMessage shows a simple message in the browser to point the user
+// to the iOS/MacOS profile and instructions for how to install it
+func (h *Headscale) AppleConfigMessage(ctx *gin.Context) {
 	appleTemplate := template.Must(template.New("apple").Parse(`
 
 	
-		

Apple configuration profiles

+

headscale

+

Apple configuration profiles

This page provides configuration profiles for the official Tailscale clients for iOS and macOS.

- The profiles will configure Tailscale.app to use {{.Url}} as its control server. + The profiles will configure Tailscale.app to use {{.URL}} as its control server.

Caution

-

You should always inspect the profile before installing it:

+

You should always download and inspect the profile before installing it:

-

curl {{.Url}}/apple/macos

+
curl {{.URL}}/apple/macos

Profiles

From 12a50ac8ac79d05a5f896633b4809fea32034810 Mon Sep 17 00:00:00 2001 From: e-zk Date: Fri, 4 Mar 2022 19:37:55 +1000 Subject: [PATCH 165/204] feat(windows): add /windows endpoint for Windows configuration - registry file /windows/tailscale.reg is generated, filling in the associated control server URL - also includes CLI instructions - fix /apple incorrect template: 'Url' is supposed to be '.URL' --- app.go | 2 + apple_mobileconfig.go | 106 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/app.go b/app.go index 4c1d201..682d8e4 100644 --- a/app.go +++ b/app.go @@ -458,6 +458,8 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { router.GET("/oidc/callback", h.OIDCCallback) router.GET("/apple", h.AppleConfigMessage) router.GET("/apple/:platform", h.ApplePlatformConfig) + router.GET("/windows", h.WindowsConfigMessage) + router.GET("/windows/tailscale.reg", h.WindowsRegConfig) router.GET("/swagger", SwaggerUI) router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1) diff --git a/apple_mobileconfig.go b/apple_mobileconfig.go index 137276d..86273e7 100644 --- a/apple_mobileconfig.go +++ b/apple_mobileconfig.go @@ -11,6 +11,100 @@ import ( "github.com/rs/zerolog/log" ) +// WindowsConfigMessage shows a simple message in the browser for how to +// configure the Windows tailscale client. +func (h *Headscale) WindowsConfigMessage(ctx *gin.Context) { + winTemplate := template.Must(template.New("windows").Parse(` + + +

headscale

+

Windows registry configuration

+

+ This page provides Windows registry information for the official Windows Tailscale client. +

+

+ The registry file will configure Tailscale to use {{.URL}} as its control server. +

+

Caution

+

You should always download and inspect the registry file before installing it:

+
curl {{.URL}}/windows/tailscale.reg
+ +

Installation

+

Headscale can be set to the default server by running the registry file:

+ +

+ Windows registry file +

+ +
    +
  1. Download the registry file, then run it
  2. +
  3. Follow the prompts
  4. +
  5. Install and run the official windows Tailscale client
  6. +
  7. When the installation has finished, start Tailscale, and log in by clicking the icon in the system tray
  8. +
+

Or

+

Open command prompt with Administrator rights. Issue the following commands to add the required registry entries:

+
+REG ADD "HKLM\Software\Tailscale IPN" /v UnattendedMode /t REG_SZ /d always
+REG ADD "HKLM\Software\Tailscale IPN" /v LoginURL /t REG_SZ /d "{{.URL}}"
+

+ Restart Tailscale and log in. +

+ + +`)) + + config := map[string]interface{}{ + "URL": h.cfg.ServerURL, + } + + var payload bytes.Buffer + if err := winTemplate.Execute(&payload, config); err != nil { + log.Error(). + Str("handler", "WindowsRegConfig"). + Err(err). + Msg("Could not render Windows index template") + ctx.Data( + http.StatusInternalServerError, + "text/html; charset=utf-8", + []byte("Could not render Windows index template"), + ) + + return + } + + ctx.Data(http.StatusOK, "text/html; charset=utf-8", payload.Bytes()) +} + +// WindowsRegConfig generates and serves the .reg file +// pre-configured to the headscale server address +func (h *Headscale) WindowsRegConfig(ctx *gin.Context) { + config := WindowsRegistryConfig{ + URL: h.cfg.ServerURL, + } + + var content bytes.Buffer + if err := windowsRegTemplate.Execute(&content, config); err != nil { + log.Error(). + Str("handler", "WindowsRegConfig"). + Err(err). + Msg("Could not render Apple macOS template") + ctx.Data( + http.StatusInternalServerError, + "text/html; charset=utf-8", + []byte("Could not render Windows registry template"), + ) + + return + } + + ctx.Data( + http.StatusOK, + "text/x-ms-regedit; charset=utf-8", + content.Bytes(), + ) +} + // AppleConfigMessage shows a simple message in the browser to point the user // to the iOS/MacOS profile and instructions for how to install it func (h *Headscale) AppleConfigMessage(ctx *gin.Context) { @@ -193,6 +287,10 @@ func (h *Headscale) ApplePlatformConfig(ctx *gin.Context) { ) } +type WindowsRegistryConfig struct { + URL string +} + type AppleMobileConfig struct { UUID uuid.UUID URL string @@ -204,6 +302,14 @@ type AppleMobilePlatformConfig struct { URL string } +var windowsRegTemplate = textTemplate.Must( + textTemplate.New("windowsconfig").Parse(`Windows Registry Editor Version 5.00 + +[HKEY_LOCAL_MACHINE\SOFTWARE\Tailscale IPN] +"UnattendedMode"="always" +"LoginURL"="{{.URL}}" +`)) + var commonTemplate = textTemplate.Must( textTemplate.New("mobileconfig").Parse(` From f9e0c13890891b3696b5587824c96077ff65f717 Mon Sep 17 00:00:00 2001 From: e-zk Date: Fri, 4 Mar 2022 19:52:42 +1000 Subject: [PATCH 166/204] docs: update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1186bad..dc34ab9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Add support for writing ACL files with YAML [#359](https://github.com/juanfont/headscale/pull/359) - Users can now use emails in ACL's groups [#372](https://github.com/juanfont/headscale/issues/372) - Add shorthand aliases for commands and subcommands [#376](https://github.com/juanfont/headscale/pull/376) +- Add `/windows` endpoint for Windows configuration instructions + registry file download [#392](https://github.com/juanfont/headscale/pull/392) ### Changes From d69dada8ff7be8c2e13cd4e6c67e97481b2810d7 Mon Sep 17 00:00:00 2001 From: e-zk Date: Fri, 4 Mar 2022 20:03:49 +1000 Subject: [PATCH 167/204] feat(windows): rename apple_mobileconfig.go => platform_config.go rename apple_mobileconfig.go to platform_config.go since the file includes configuration info for multiple platforms now. --- apple_mobileconfig.go => platform_config.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apple_mobileconfig.go => platform_config.go (100%) diff --git a/apple_mobileconfig.go b/platform_config.go similarity index 100% rename from apple_mobileconfig.go rename to platform_config.go From 607c1eb3163999fb310170a5ee67a83c634e8196 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Fri, 4 Mar 2022 11:31:41 +0100 Subject: [PATCH 168/204] Be consistent with uppercase DERP --- app.go | 12 ++++++------ derp_embedded.go | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app.go b/app.go index 3115b99..eb3b8ad 100644 --- a/app.go +++ b/app.go @@ -144,7 +144,7 @@ type Headscale struct { privateKey *key.MachinePrivate DERPMap *tailcfg.DERPMap - EmbeddedDerpServer *EmbeddedDerpServer + EmbeddedDERPServer *EmbeddedDERPServer aclPolicy *ACLPolicy aclRules []tailcfg.FilterRule @@ -242,11 +242,11 @@ func NewHeadscale(cfg Config) (*Headscale, error) { } if cfg.DERP.EmbeddedDERP { - embeddedDerpServer, err := app.NewEmbeddedDerpServer() + embeddedDERPServer, err := app.NewEmbeddedDERPServer() if err != nil { return nil, err } - app.EmbeddedDerpServer = embeddedDerpServer + app.EmbeddedDERPServer = embeddedDERPServer // If we are using the embedded DERP, there is no reason to use Tailscale's DERP infrastructure serverURL, err := url.Parse(app.cfg.ServerURL) @@ -496,9 +496,9 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1) if h.cfg.DERP.EmbeddedDERP { - router.Any("/derp", h.EmbeddedDerpHandler) - router.Any("/derp/probe", h.EmbeddedDerpProbeHandler) - router.Any("/bootstrap-dns", h.EmbeddedDerpBootstrapDNSHandler) + router.Any("/derp", h.EmbeddedDERPHandler) + router.Any("/derp/probe", h.EmbeddedDERPProbeHandler) + router.Any("/bootstrap-dns", h.EmbeddedDERPBootstrapDNSHandler) } api := router.Group("/api") diff --git a/derp_embedded.go b/derp_embedded.go index 0631fff..1d4fb0b 100644 --- a/derp_embedded.go +++ b/derp_embedded.go @@ -28,17 +28,17 @@ var ( bootstrapDNS = "derp.tailscale.com" ) -type EmbeddedDerpServer struct { - tailscaleDerp *derp.Server +type EmbeddedDERPServer struct { + tailscaleDERP *derp.Server } -func (h *Headscale) NewEmbeddedDerpServer() (*EmbeddedDerpServer, error) { +func (h *Headscale) NewEmbeddedDERPServer() (*EmbeddedDERPServer, error) { s := derp.NewServer(key.NodePrivate(*h.privateKey), log.Info().Msgf) - return &EmbeddedDerpServer{s}, nil + return &EmbeddedDERPServer{s}, nil } -func (h *Headscale) EmbeddedDerpHandler(ctx *gin.Context) { +func (h *Headscale) EmbeddedDERPHandler(ctx *gin.Context) { up := strings.ToLower(ctx.Request.Header.Get("Upgrade")) if up != "websocket" && up != "derp" { if up != "" { @@ -75,12 +75,12 @@ func (h *Headscale) EmbeddedDerpHandler(ctx *gin.Context) { pubKey.UntypedHexString()) } - h.EmbeddedDerpServer.tailscaleDerp.Accept(netConn, conn, netConn.RemoteAddr().String()) + h.EmbeddedDERPServer.tailscaleDERP.Accept(netConn, conn, netConn.RemoteAddr().String()) } -// EmbeddedDerpProbeHandler is the endpoint that js/wasm clients hit to measure +// EmbeddedDERPProbeHandler is the endpoint that js/wasm clients hit to measure // DERP latency, since they can't do UDP STUN queries. -func (h *Headscale) EmbeddedDerpProbeHandler(ctx *gin.Context) { +func (h *Headscale) EmbeddedDERPProbeHandler(ctx *gin.Context) { switch ctx.Request.Method { case "HEAD", "GET": ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*") @@ -89,7 +89,7 @@ func (h *Headscale) EmbeddedDerpProbeHandler(ctx *gin.Context) { } } -func (h *Headscale) EmbeddedDerpBootstrapDNSHandler(ctx *gin.Context) { +func (h *Headscale) EmbeddedDERPBootstrapDNSHandler(ctx *gin.Context) { ctx.Header("Content-Type", "application/json") j, _ := dnsCache.Load().([]byte) // Bootstrap DNS requests occur cross-regions, From 575f33d18326df526214f58949a5834738b0dbaa Mon Sep 17 00:00:00 2001 From: e-zk Date: Fri, 4 Mar 2022 20:35:09 +1000 Subject: [PATCH 169/204] docs: fix comments to comply with golangci-lint --- platform_config.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/platform_config.go b/platform_config.go index 86273e7..d36a37c 100644 --- a/platform_config.go +++ b/platform_config.go @@ -11,8 +11,7 @@ import ( "github.com/rs/zerolog/log" ) -// WindowsConfigMessage shows a simple message in the browser for how to -// configure the Windows tailscale client. +// WindowsConfigMessage shows a simple message in the browser for how to configure the Windows Tailscale client. func (h *Headscale) WindowsConfigMessage(ctx *gin.Context) { winTemplate := template.Must(template.New("windows").Parse(` @@ -76,8 +75,7 @@ REG ADD "HKLM\Software\Tailscale IPN" /v LoginURL /t REG_SZ /d "{{.URL}}" ctx.Data(http.StatusOK, "text/html; charset=utf-8", payload.Bytes()) } -// WindowsRegConfig generates and serves the .reg file -// pre-configured to the headscale server address +// WindowsRegConfig generates and serves a .reg file configured with the Headscale server address. func (h *Headscale) WindowsRegConfig(ctx *gin.Context) { config := WindowsRegistryConfig{ URL: h.cfg.ServerURL, @@ -105,8 +103,7 @@ func (h *Headscale) WindowsRegConfig(ctx *gin.Context) { ) } -// AppleConfigMessage shows a simple message in the browser to point the user -// to the iOS/MacOS profile and instructions for how to install it +// AppleConfigMessage shows a simple message in the browser to point the user to the iOS/MacOS profile and instructions for how to install it. func (h *Headscale) AppleConfigMessage(ctx *gin.Context) { appleTemplate := template.Must(template.New("apple").Parse(` From a70669fca7614790bdf1f506dabcd1a89efbbdff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 4 Mar 2022 11:04:12 +0000 Subject: [PATCH 170/204] docs(README): update contributors --- README.md | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index d9d050f..1b97b1a 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,13 @@ make build Alessandro (Ale) Segala

+ + e-zk/ +
+ e-zk +
+
unreality/ @@ -206,10 +213,10 @@ make build - - e-zk/ + + Nico/
- e-zk + Nico
@@ -226,6 +233,8 @@ make build Aaron Bieber
Fernando @@ -233,8 +242,6 @@ make build Fernando De Lucchi
Hoàng @@ -270,6 +277,8 @@ make build Silver Bullet
Stefan @@ -277,13 +286,11 @@ make build Stefan Majer
- - fincac/ + + lachy2849/
- fincac + lachy2849
@@ -314,6 +321,8 @@ make build Arthur Woimbée
Bryan @@ -321,8 +330,6 @@ make build Bryan Stenson
Felix @@ -358,6 +365,8 @@ make build Jim Tittsler
Pierre @@ -365,8 +374,6 @@ make build Pierre Carru
rcursaru/ @@ -402,6 +409,8 @@ make build Teteros
The @@ -409,8 +418,6 @@ make build The Gitter Badger
Tianon @@ -446,6 +453,8 @@ make build derelm
ignoramous/ @@ -453,8 +462,6 @@ make build ignoramous
lion24/ From 22d2443281466006500f3a0ceb2e1f87b21d174d Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Fri, 4 Mar 2022 13:26:45 +0100 Subject: [PATCH 171/204] Move more stuff to common --- integration_common_test.go | 7 +++++++ integration_test.go | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/integration_common_test.go b/integration_common_test.go index de304d0..de9fdd9 100644 --- a/integration_common_test.go +++ b/integration_common_test.go @@ -18,8 +18,15 @@ const DOCKER_EXECUTE_TIMEOUT = 10 * time.Second var ( IpPrefix4 = netaddr.MustParseIPPrefix("100.64.0.0/10") IpPrefix6 = netaddr.MustParseIPPrefix("fd7a:115c:a1e0::/48") + + tailscaleVersions = []string{"1.20.4", "1.18.2", "1.16.2", "1.14.3", "1.12.3"} ) +type TestNamespace struct { + count int + tailscales map[string]dockertest.Resource +} + type ExecuteCommandConfig struct { timeout time.Duration } diff --git a/integration_test.go b/integration_test.go index 03d6d2f..523a9a9 100644 --- a/integration_test.go +++ b/integration_test.go @@ -29,13 +29,6 @@ import ( "tailscale.com/ipn/ipnstate" ) -var tailscaleVersions = []string{"1.20.4", "1.18.2", "1.16.2", "1.14.3", "1.12.3"} - -type TestNamespace struct { - count int - tailscales map[string]dockertest.Resource -} - type IntegrationTestSuite struct { suite.Suite stats *suite.SuiteInformation From 09d78c7a05b6a9dc90b1a365d0a98ee34f62b112 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Fri, 4 Mar 2022 13:54:59 +0100 Subject: [PATCH 172/204] Even more stuff moved to common --- integration_common_test.go | 33 +++++++++++++++++++++++++++++++++ integration_test.go | 32 -------------------------------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/integration_common_test.go b/integration_common_test.go index de9fdd9..a341712 100644 --- a/integration_common_test.go +++ b/integration_common_test.go @@ -6,6 +6,7 @@ package headscale import ( "bytes" "fmt" + "strings" "time" "github.com/ory/dockertest/v3" @@ -126,3 +127,35 @@ func DockerAllowNetworkAdministration(config *docker.HostConfig) { Target: "/dev/net/tun", }) } + +func getIPs( + tailscales map[string]dockertest.Resource, +) (map[string][]netaddr.IP, error) { + ips := make(map[string][]netaddr.IP) + for hostname, tailscale := range tailscales { + command := []string{"tailscale", "ip"} + + result, err := ExecuteCommand( + &tailscale, + command, + []string{}, + ) + if err != nil { + return nil, err + } + + for _, address := range strings.Split(result, "\n") { + address = strings.TrimSuffix(address, "\n") + if len(address) < 1 { + continue + } + ip, err := netaddr.ParseIP(address) + if err != nil { + return nil, err + } + ips[hostname] = append(ips[hostname], ip) + } + } + + return ips, nil +} diff --git a/integration_test.go b/integration_test.go index 523a9a9..1649f32 100644 --- a/integration_test.go +++ b/integration_test.go @@ -680,38 +680,6 @@ func (s *IntegrationTestSuite) TestMagicDNS() { } } -func getIPs( - tailscales map[string]dockertest.Resource, -) (map[string][]netaddr.IP, error) { - ips := make(map[string][]netaddr.IP) - for hostname, tailscale := range tailscales { - command := []string{"tailscale", "ip"} - - result, err := ExecuteCommand( - &tailscale, - command, - []string{}, - ) - if err != nil { - return nil, err - } - - for _, address := range strings.Split(result, "\n") { - address = strings.TrimSuffix(address, "\n") - if len(address) < 1 { - continue - } - ip, err := netaddr.ParseIP(address) - if err != nil { - return nil, err - } - ips[hostname] = append(ips[hostname], ip) - } - } - - return ips, nil -} - func getAPIURLs( tailscales map[string]dockertest.Resource, ) (map[netaddr.IP]string, error) { From 35efd8f95a5f33aebbd4e1377b55232d713299c7 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 5 Mar 2022 00:09:36 +0000 Subject: [PATCH 173/204] chore(deps): update dependency docker.io/golang to v1.17.8 --- Dockerfile | 2 +- Dockerfile.alpine | 2 +- Dockerfile.debug | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 86f5bd4..3ab9c1d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Builder image -FROM docker.io/golang:1.17.7-bullseye AS build +FROM docker.io/golang:1.17.8-bullseye AS build ENV GOPATH /go WORKDIR /go/src/headscale diff --git a/Dockerfile.alpine b/Dockerfile.alpine index af88434..1f0d635 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -1,5 +1,5 @@ # Builder image -FROM docker.io/golang:1.17.7-alpine AS build +FROM docker.io/golang:1.17.8-alpine AS build ENV GOPATH /go WORKDIR /go/src/headscale diff --git a/Dockerfile.debug b/Dockerfile.debug index 38385ce..e73c064 100644 --- a/Dockerfile.debug +++ b/Dockerfile.debug @@ -1,5 +1,5 @@ # Builder image -FROM docker.io/golang:1.17.7-bullseye AS build +FROM docker.io/golang:1.17.8-bullseye AS build ENV GOPATH /go WORKDIR /go/src/headscale From 758b1ba1cbcd13fcff10954a301b7773f5921f20 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sat, 5 Mar 2022 16:22:02 +0100 Subject: [PATCH 174/204] Renamed configuration items of the DERP server --- app.go | 50 ++++++++++++++++++++++++++------------ cmd/headscale/cli/utils.go | 9 +++---- config-example.yaml | 8 ++++++ 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/app.go b/app.go index eb3b8ad..b739a05 100644 --- a/app.go +++ b/app.go @@ -13,6 +13,7 @@ import ( "os" "os/signal" "sort" + "strconv" "strings" "sync" "syscall" @@ -120,7 +121,8 @@ type OIDCConfig struct { } type DERPConfig struct { - EmbeddedDERP bool + ServerEnabled bool + ServerInsecure bool URLs []url.URL Paths []string AutoUpdate bool @@ -143,8 +145,8 @@ type Headscale struct { dbDebug bool privateKey *key.MachinePrivate - DERPMap *tailcfg.DERPMap - EmbeddedDERPServer *EmbeddedDERPServer + DERPMap *tailcfg.DERPMap + DERPServer *DERPServer aclPolicy *ACLPolicy aclRules []tailcfg.FilterRule @@ -180,7 +182,6 @@ func LookupTLSClientAuthMode(mode string) (tls.ClientAuthType, bool) { } } -// NewHeadscale returns the Headscale app. func NewHeadscale(cfg Config) (*Headscale, error) { privKey, err := readOrCreatePrivateKey(cfg.PrivateKeyPath) if err != nil { @@ -241,30 +242,49 @@ func NewHeadscale(cfg Config) (*Headscale, error) { } } - if cfg.DERP.EmbeddedDERP { - embeddedDERPServer, err := app.NewEmbeddedDERPServer() + if cfg.DERP.ServerEnabled { + embeddedDERPServer, err := app.NewDERPServer() if err != nil { return nil, err } - app.EmbeddedDERPServer = embeddedDERPServer + app.DERPServer = embeddedDERPServer - // If we are using the embedded DERP, there is no reason to use Tailscale's DERP infrastructure serverURL, err := url.Parse(app.cfg.ServerURL) if err != nil { return nil, err } + var host string + var port int + host, portStr, err := net.SplitHostPort(serverURL.Host) + if err != nil { + if serverURL.Scheme == "https" { + host = serverURL.Host + port = 443 + } else { + host = serverURL.Host + port = 80 + } + } else { + port, err = strconv.Atoi(portStr) + if err != nil { + return nil, err + } + } + app.DERPMap = &tailcfg.DERPMap{ Regions: map[int]*tailcfg.DERPRegion{ - 1: { - RegionID: 1, + 999: { + RegionID: 999, RegionCode: "headscale", RegionName: "Headscale Embedded DERP", Avoid: false, Nodes: []*tailcfg.DERPNode{ { - Name: "1a", - RegionID: 1, - HostName: serverURL.Host, + Name: "999a", + RegionID: 999, + HostName: host, + DERPPort: port, + InsecureForTests: cfg.DERP.ServerInsecure, }, }, }, @@ -495,7 +515,7 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { router.GET("/swagger", SwaggerUI) router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1) - if h.cfg.DERP.EmbeddedDERP { + if h.cfg.DERP.ServerEnabled { router.Any("/derp", h.EmbeddedDERPHandler) router.Any("/derp/probe", h.EmbeddedDERPProbeHandler) router.Any("/bootstrap-dns", h.EmbeddedDERPBootstrapDNSHandler) @@ -516,7 +536,7 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { func (h *Headscale) Serve() error { var err error - if h.cfg.DERP.EmbeddedDERP { + if h.cfg.DERP.ServerEnabled { go h.ServeSTUN() } else { // Fetch an initial DERP Map before we start serving diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 98ffe2e..06b9ca9 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -117,11 +117,8 @@ func LoadConfig(path string) error { } func GetDERPConfig() headscale.DERPConfig { - if viper.GetBool("derp.embedded_derp") { - return headscale.DERPConfig{ - EmbeddedDERP: true, - } - } + enabled := viper.GetBool("derp.server.enabled") + insecure := viper.GetBool("derp.server.insecure") urlStrs := viper.GetStringSlice("derp.urls") @@ -144,6 +141,8 @@ func GetDERPConfig() headscale.DERPConfig { updateFrequency := viper.GetDuration("derp.update_frequency") return headscale.DERPConfig{ + ServerEnabled: enabled, + ServerInsecure: insecure, URLs: urls, Paths: paths, AutoUpdate: autoUpdate, diff --git a/config-example.yaml b/config-example.yaml index c28b608..84b1c90 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -55,6 +55,14 @@ ip_prefixes: # headscale needs a list of DERP servers that can be presented # to the clients. derp: + server: + # If enabled, runs the embedded DERP server and merges it into the rest of the DERP config + enabled: false + + # Insecure mode is recommended only for tests. It indicates the tailscale clients + # to use insecure connections to this server. + insecure: false + # List of externally available DERP maps encoded in JSON urls: - https://controlplane.tailscale.com/derpmap/default From df37d1a639b81e7b9305bba3ef941d38a64604a1 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sat, 5 Mar 2022 19:19:21 +0100 Subject: [PATCH 175/204] Do not offer the option to be DERP insecure Websockets, in which DERP is based, requires a TLS certificate. At the same time, if we use a certificate it must be valid... otherwise Tailscale wont connect (does not have an Insecure option). So there is no option to expose insecure here --- app.go | 16 +++++++--------- cmd/headscale/cli/utils.go | 2 -- config-example.yaml | 5 +---- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/app.go b/app.go index b739a05..34602d6 100644 --- a/app.go +++ b/app.go @@ -122,7 +122,6 @@ type OIDCConfig struct { type DERPConfig struct { ServerEnabled bool - ServerInsecure bool URLs []url.URL Paths []string AutoUpdate bool @@ -280,11 +279,10 @@ func NewHeadscale(cfg Config) (*Headscale, error) { Avoid: false, Nodes: []*tailcfg.DERPNode{ { - Name: "999a", - RegionID: 999, - HostName: host, - DERPPort: port, - InsecureForTests: cfg.DERP.ServerInsecure, + Name: "999a", + RegionID: 999, + HostName: host, + DERPPort: port, }, }, }, @@ -516,9 +514,9 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { router.GET("/swagger/v1/openapiv2.json", SwaggerAPIv1) if h.cfg.DERP.ServerEnabled { - router.Any("/derp", h.EmbeddedDERPHandler) - router.Any("/derp/probe", h.EmbeddedDERPProbeHandler) - router.Any("/bootstrap-dns", h.EmbeddedDERPBootstrapDNSHandler) + router.Any("/derp", h.DERPHandler) + router.Any("/derp/probe", h.DERPProbeHandler) + router.Any("/bootstrap-dns", h.DERPBootstrapDNSHandler) } api := router.Group("/api") diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 06b9ca9..7277723 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -118,7 +118,6 @@ func LoadConfig(path string) error { func GetDERPConfig() headscale.DERPConfig { enabled := viper.GetBool("derp.server.enabled") - insecure := viper.GetBool("derp.server.insecure") urlStrs := viper.GetStringSlice("derp.urls") @@ -142,7 +141,6 @@ func GetDERPConfig() headscale.DERPConfig { return headscale.DERPConfig{ ServerEnabled: enabled, - ServerInsecure: insecure, URLs: urls, Paths: paths, AutoUpdate: autoUpdate, diff --git a/config-example.yaml b/config-example.yaml index 84b1c90..08cc6c1 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -57,12 +57,9 @@ ip_prefixes: derp: server: # If enabled, runs the embedded DERP server and merges it into the rest of the DERP config + # The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place enabled: false - # Insecure mode is recommended only for tests. It indicates the tailscale clients - # to use insecure connections to this server. - insecure: false - # List of externally available DERP maps encoded in JSON urls: - https://controlplane.tailscale.com/derpmap/default From b7423796278aa4036bca3e64d587801d8a1fd0eb Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sat, 5 Mar 2022 19:30:30 +0100 Subject: [PATCH 176/204] Do not use the term embedded --- derp_embedded.go | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/derp_embedded.go b/derp_embedded.go index 1d4fb0b..d8abbc8 100644 --- a/derp_embedded.go +++ b/derp_embedded.go @@ -28,17 +28,18 @@ var ( bootstrapDNS = "derp.tailscale.com" ) -type EmbeddedDERPServer struct { +type DERPServer struct { tailscaleDERP *derp.Server } -func (h *Headscale) NewEmbeddedDERPServer() (*EmbeddedDERPServer, error) { +func (h *Headscale) NewDERPServer() (*DERPServer, error) { s := derp.NewServer(key.NodePrivate(*h.privateKey), log.Info().Msgf) - return &EmbeddedDERPServer{s}, nil + return &DERPServer{s}, nil } -func (h *Headscale) EmbeddedDERPHandler(ctx *gin.Context) { +func (h *Headscale) DERPHandler(ctx *gin.Context) { + log.Trace().Caller().Msgf("/derp request from %v", ctx.ClientIP()) up := strings.ToLower(ctx.Request.Header.Get("Upgrade")) if up != "websocket" && up != "derp" { if up != "" { @@ -75,12 +76,12 @@ func (h *Headscale) EmbeddedDERPHandler(ctx *gin.Context) { pubKey.UntypedHexString()) } - h.EmbeddedDERPServer.tailscaleDERP.Accept(netConn, conn, netConn.RemoteAddr().String()) + h.DERPServer.tailscaleDERP.Accept(netConn, conn, netConn.RemoteAddr().String()) } -// EmbeddedDERPProbeHandler is the endpoint that js/wasm clients hit to measure +// DERPProbeHandler is the endpoint that js/wasm clients hit to measure // DERP latency, since they can't do UDP STUN queries. -func (h *Headscale) EmbeddedDERPProbeHandler(ctx *gin.Context) { +func (h *Headscale) DERPProbeHandler(ctx *gin.Context) { switch ctx.Request.Method { case "HEAD", "GET": ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*") @@ -89,7 +90,7 @@ func (h *Headscale) EmbeddedDERPProbeHandler(ctx *gin.Context) { } } -func (h *Headscale) EmbeddedDERPBootstrapDNSHandler(ctx *gin.Context) { +func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) { ctx.Header("Content-Type", "application/json") j, _ := dnsCache.Load().([]byte) // Bootstrap DNS requests occur cross-regions, @@ -105,7 +106,7 @@ func (h *Headscale) ServeSTUN() { if err != nil { log.Fatal().Msgf("failed to open STUN listener: %v", err) } - log.Printf("running STUN server on %v", pc.LocalAddr()) + log.Trace().Msgf("STUN server started at %s", pc.LocalAddr()) serverSTUNListener(context.Background(), pc.(*net.UDPConn)) } @@ -122,10 +123,11 @@ func serverSTUNListener(ctx context.Context, pc *net.UDPConn) { if ctx.Err() != nil { return } - log.Printf("STUN ReadFrom: %v", err) + log.Error().Caller().Err(err).Msgf("STUN ReadFrom") time.Sleep(time.Second) continue } + log.Trace().Caller().Msgf("STUN request from %v", ua) pkt := buf[:n] if !stun.Is(pkt) { continue @@ -164,7 +166,7 @@ func refreshBootstrapDNS() { for _, name := range names { addrs, err := r.LookupIP(ctx, "ip", name) if err != nil { - log.Printf("bootstrap DNS lookup %q: %v", name, err) + log.Trace().Caller().Err(err).Msgf("bootstrap DNS lookup %q: %v", name) continue } dnsEntries[name] = addrs From 88378c22fb41383273f43c9d84aba1e44271b1f6 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sat, 5 Mar 2022 19:31:50 +0100 Subject: [PATCH 177/204] Rename the file to derp_server.go for coherence --- derp_embedded.go => derp_server.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename derp_embedded.go => derp_server.go (100%) diff --git a/derp_embedded.go b/derp_server.go similarity index 100% rename from derp_embedded.go rename to derp_server.go From e9eb90fa7691f1f45b0ad60180dd87ae59374ae7 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sat, 5 Mar 2022 19:34:06 +0100 Subject: [PATCH 178/204] Added integration tests for the embedded DERP server --- .dockerignore | 1 + Dockerfile.tailscale | 7 +- Makefile | 3 + integration_embedded_derp_test.go | 384 ++++++++++++++++++ .../etc_embedded_derp/tls/server.crt | 18 + 5 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 integration_embedded_derp_test.go create mode 100644 integration_test/etc_embedded_derp/tls/server.crt diff --git a/.dockerignore b/.dockerignore index 057a20e..e3acf99 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,6 +3,7 @@ // development integration_test.go integration_test/ +!integration_test/etc_embedded_derp/tls/server.crt Dockerfile* docker-compose* diff --git a/Dockerfile.tailscale b/Dockerfile.tailscale index f96c6b9..fded837 100644 --- a/Dockerfile.tailscale +++ b/Dockerfile.tailscale @@ -7,5 +7,10 @@ RUN apt-get update \ && curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/focal.gpg | apt-key add - \ && curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/focal.list | tee /etc/apt/sources.list.d/tailscale.list \ && apt-get update \ - && apt-get install -y tailscale=${TAILSCALE_VERSION} dnsutils \ + && apt-get install -y ca-certificates tailscale=${TAILSCALE_VERSION} dnsutils \ && rm -rf /var/lib/apt/lists/* + +ADD integration_test/etc_embedded_derp/tls/server.crt /usr/local/share/ca-certificates/ +RUN chmod 644 /usr/local/share/ca-certificates/server.crt + +RUN update-ca-certificates \ No newline at end of file diff --git a/Makefile b/Makefile index 266dadb..73630d3 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,9 @@ test_integration: test_integration_cli: go test -tags integration -v integration_cli_test.go integration_common_test.go +test_integration_derp: + go test -tags integration -v integration_embedded_derp_test.go integration_common_test.go + coverprofile_func: go tool cover -func=coverage.out diff --git a/integration_embedded_derp_test.go b/integration_embedded_derp_test.go new file mode 100644 index 0000000..d95c460 --- /dev/null +++ b/integration_embedded_derp_test.go @@ -0,0 +1,384 @@ +//go:build integration + +package headscale + +import ( + "bytes" + "context" + "crypto/tls" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "path" + "strings" + "sync" + "testing" + "time" + + v1 "github.com/juanfont/headscale/gen/go/headscale/v1" + "github.com/ory/dockertest/v3" + "github.com/ory/dockertest/v3/docker" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +const ( + headscaleHostname = "headscale-derp" + namespaceName = "derpnamespace" + totalContainers = 3 +) + +type IntegrationDERPTestSuite struct { + suite.Suite + stats *suite.SuiteInformation + + pool dockertest.Pool + networks map[int]dockertest.Network // so we keep the containers isolated + headscale dockertest.Resource + + tailscales map[string]dockertest.Resource + joinWaitGroup sync.WaitGroup +} + +func TestDERPIntegrationTestSuite(t *testing.T) { + s := new(IntegrationDERPTestSuite) + + s.tailscales = make(map[string]dockertest.Resource) + s.networks = make(map[int]dockertest.Network) + + suite.Run(t, s) + + // HandleStats, which allows us to check if we passed and save logs + // is called after TearDown, so we cannot tear down containers before + // we have potentially saved the logs. + for _, tailscale := range s.tailscales { + if err := s.pool.Purge(&tailscale); err != nil { + log.Printf("Could not purge resource: %s\n", err) + } + } + + if !s.stats.Passed() { + err := s.saveLog(&s.headscale, "test_output") + if err != nil { + log.Printf("Could not save log: %s\n", err) + } + } + if err := s.pool.Purge(&s.headscale); err != nil { + log.Printf("Could not purge resource: %s\n", err) + } + + for _, network := range s.networks { + if err := network.Close(); err != nil { + log.Printf("Could not close network: %s\n", err) + } + } +} + +func (s *IntegrationDERPTestSuite) SetupSuite() { + if ppool, err := dockertest.NewPool(""); err == nil { + s.pool = *ppool + } else { + log.Fatalf("Could not connect to docker: %s", err) + } + + for i := 0; i < totalContainers; i++ { + if pnetwork, err := s.pool.CreateNetwork(fmt.Sprintf("headscale-derp-%d", i)); err == nil { + s.networks[i] = *pnetwork + } else { + log.Fatalf("Could not create network: %s", err) + } + } + + headscaleBuildOptions := &dockertest.BuildOptions{ + Dockerfile: "Dockerfile", + ContextDir: ".", + } + + currentPath, err := os.Getwd() + if err != nil { + log.Fatalf("Could not determine current path: %s", err) + } + + headscaleOptions := &dockertest.RunOptions{ + Name: headscaleHostname, + Mounts: []string{ + fmt.Sprintf("%s/integration_test/etc_embedded_derp:/etc/headscale", currentPath), + }, + Cmd: []string{"headscale", "serve"}, + ExposedPorts: []string{"8443/tcp", "3478/udp"}, + PortBindings: map[docker.Port][]docker.PortBinding{ + "8443/tcp": {{HostPort: "8443"}}, + "3478/udp": {{HostPort: "3478"}}, + }, + } + + log.Println("Creating headscale container") + if pheadscale, err := s.pool.BuildAndRunWithBuildOptions(headscaleBuildOptions, headscaleOptions, DockerRestartPolicy); err == nil { + s.headscale = *pheadscale + } else { + log.Fatalf("Could not start resource: %s", err) + } + log.Println("Created headscale container to test DERP") + + log.Println("Creating tailscale containers") + + for i := 0; i < totalContainers; i++ { + version := tailscaleVersions[i%len(tailscaleVersions)] + hostname, container := s.tailscaleContainer( + fmt.Sprint(i), + version, + s.networks[i], + ) + s.tailscales[hostname] = *container + } + + log.Println("Waiting for headscale to be ready") + hostEndpoint := fmt.Sprintf("localhost:%s", s.headscale.GetPort("8443/tcp")) + + if err := s.pool.Retry(func() error { + url := fmt.Sprintf("https://%s/health", hostEndpoint) + insecureTransport := http.DefaultTransport.(*http.Transport).Clone() + insecureTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + client := &http.Client{Transport: insecureTransport} + resp, err := client.Get(url) + if err != nil { + return err + } + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("status code not OK") + } + + return nil + }); err != nil { + // TODO(kradalby): If we cannot access headscale, or any other fatal error during + // test setup, we need to abort and tear down. However, testify does not seem to + // support that at the moment: + // https://github.com/stretchr/testify/issues/849 + return // fmt.Errorf("Could not connect to headscale: %s", err) + } + log.Println("headscale container is ready") + + log.Printf("Creating headscale namespace: %s\n", namespaceName) + result, err := ExecuteCommand( + &s.headscale, + []string{"headscale", "namespaces", "create", namespaceName}, + []string{}, + ) + log.Println("headscale create namespace result: ", result) + assert.Nil(s.T(), err) + + log.Printf("Creating pre auth key for %s\n", namespaceName) + preAuthResult, err := ExecuteCommand( + &s.headscale, + []string{ + "headscale", + "--namespace", + namespaceName, + "preauthkeys", + "create", + "--reusable", + "--expiration", + "24h", + "--output", + "json", + }, + []string{"LOG_LEVEL=error"}, + ) + assert.Nil(s.T(), err) + + var preAuthKey v1.PreAuthKey + err = json.Unmarshal([]byte(preAuthResult), &preAuthKey) + assert.Nil(s.T(), err) + assert.True(s.T(), preAuthKey.Reusable) + + headscaleEndpoint := fmt.Sprintf("https://headscale:%s", s.headscale.GetPort("8443/tcp")) + + log.Printf( + "Joining tailscale containers to headscale at %s\n", + headscaleEndpoint, + ) + for hostname, tailscale := range s.tailscales { + s.joinWaitGroup.Add(1) + go s.Join(headscaleEndpoint, preAuthKey.Key, hostname, tailscale) + } + + s.joinWaitGroup.Wait() + + // The nodes need a bit of time to get their updated maps from headscale + // TODO: See if we can have a more deterministic wait here. + time.Sleep(60 * time.Second) +} + +func (s *IntegrationDERPTestSuite) Join( + endpoint, key, hostname string, + tailscale dockertest.Resource, +) { + defer s.joinWaitGroup.Done() + + command := []string{ + "tailscale", + "up", + "-login-server", + endpoint, + "--authkey", + key, + "--hostname", + hostname, + } + + log.Println("Join command:", command) + log.Printf("Running join command for %s\n", hostname) + _, err := ExecuteCommand( + &tailscale, + command, + []string{}, + ) + assert.Nil(s.T(), err) + log.Printf("%s joined\n", hostname) +} + +func (s *IntegrationDERPTestSuite) tailscaleContainer(identifier, version string, network dockertest.Network, +) (string, *dockertest.Resource) { + tailscaleBuildOptions := &dockertest.BuildOptions{ + Dockerfile: "Dockerfile.tailscale", + ContextDir: ".", + BuildArgs: []docker.BuildArg{ + { + Name: "TAILSCALE_VERSION", + Value: version, + }, + }, + } + hostname := fmt.Sprintf( + "tailscale-%s-%s", + strings.Replace(version, ".", "-", -1), + identifier, + ) + tailscaleOptions := &dockertest.RunOptions{ + Name: hostname, + Networks: []*dockertest.Network{&network}, + Cmd: []string{ + "tailscaled", "--tun=tsdev", + }, + + // expose the host IP address, so we can access it from inside the container + ExtraHosts: []string{"host.docker.internal:host-gateway", "headscale:host-gateway"}, + } + + pts, err := s.pool.BuildAndRunWithBuildOptions( + tailscaleBuildOptions, + tailscaleOptions, + DockerRestartPolicy, + DockerAllowLocalIPv6, + DockerAllowNetworkAdministration, + ) + if err != nil { + log.Fatalf("Could not start resource: %s", err) + } + log.Printf("Created %s container\n", hostname) + + return hostname, pts +} + +func (s *IntegrationDERPTestSuite) TearDownSuite() { +} + +func (s *IntegrationDERPTestSuite) HandleStats( + suiteName string, + stats *suite.SuiteInformation, +) { + s.stats = stats +} + +func (s *IntegrationDERPTestSuite) saveLog( + resource *dockertest.Resource, + basePath string, +) error { + err := os.MkdirAll(basePath, os.ModePerm) + if err != nil { + return err + } + + var stdout bytes.Buffer + var stderr bytes.Buffer + + err = s.pool.Client.Logs( + docker.LogsOptions{ + Context: context.TODO(), + Container: resource.Container.ID, + OutputStream: &stdout, + ErrorStream: &stderr, + Tail: "all", + RawTerminal: false, + Stdout: true, + Stderr: true, + Follow: false, + Timestamps: false, + }, + ) + if err != nil { + return err + } + + log.Printf("Saving logs for %s to %s\n", resource.Container.Name, basePath) + + err = ioutil.WriteFile( + path.Join(basePath, resource.Container.Name+".stdout.log"), + []byte(stdout.String()), + 0o644, + ) + if err != nil { + return err + } + + err = ioutil.WriteFile( + path.Join(basePath, resource.Container.Name+".stderr.log"), + []byte(stdout.String()), + 0o644, + ) + if err != nil { + return err + } + + return nil +} + +func (s *IntegrationDERPTestSuite) TestPingAllPeersByHostname() { + ips, err := getIPs(s.tailscales) + assert.Nil(s.T(), err) + for hostname, tailscale := range s.tailscales { + for peername := range ips { + if peername == hostname { + continue + } + s.T().Run(fmt.Sprintf("%s-%s", hostname, peername), func(t *testing.T) { + command := []string{ + "tailscale", "ping", + "--timeout=10s", + "--c=5", + "--until-direct=false", + peername, + } + + log.Printf( + "Pinging using hostname from %s to %s\n", + hostname, + peername, + ) + log.Println(command) + result, err := ExecuteCommand( + &tailscale, + command, + []string{}, + ) + assert.Nil(t, err) + log.Printf("Result for %s: %s\n", hostname, result) + assert.Contains(t, result, "via DERP") + }) + } + } +} diff --git a/integration_test/etc_embedded_derp/tls/server.crt b/integration_test/etc_embedded_derp/tls/server.crt new file mode 100644 index 0000000..4895388 --- /dev/null +++ b/integration_test/etc_embedded_derp/tls/server.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC8jCCAdqgAwIBAgIULbu+UbSTMG/LtxooLLh7BgSEyqEwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJaGVhZHNjYWxlMCAXDTIyMDMwNTE2NDgwM1oYDzI1MjEx +MTA0MTY0ODAzWjAUMRIwEAYDVQQDDAloZWFkc2NhbGUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDqcfpToLZUF0rlNwXkkt3lbyw4Cl4TJdx36o2PKaOK +U+tze/IjRsCWeMwrcR1o9TNZcxsD+c2J48D1WATuQJlMeg+2UJXGaTGRKkkbPMy3 +5m7AFf/Q16UEOgm2NYjZaQ8faRGIMYURG/6sXmNeETJvBixpBev9yKJuVXgqHNS4 +NpEkNwdOCuAZXrmw0HCbiusawJOay4tFvhH14rav8Uimonl8UTNVXufMzyUOuoaQ +TGflmzYX3hIoswRnTPlIWFoqObvx2Q8H+of3uQJXy0m8I6OrIoXLNxnqYMfFls79 +9SYgVc2jPsCbh5fwyRbx2Hof7sIZ1K/mNgxJRG1E3ZiLAgMBAAGjOjA4MBQGA1Ud +EQQNMAuCCWhlYWRzY2FsZTALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUH +AwEwDQYJKoZIhvcNAQELBQADggEBANGlVN7NCsJaKz0k0nhlRGK+tcxn2p1PXN/i +Iy+JX8ahixPC4ocRwOhrXgb390ZXLLwq08HrWYRB/Wi1VUzCp5d8dVxvrR43dJ+v +L2EOBiIKgcu2C3pWW1qRR46/EoXUU9kSH2VNBvIhNufi32kEOidoDzxtQf6qVCoF +guUt1JkAqrynv1UvR/2ZRM/WzM/oJ8qfECwrwDxyYhkqU5Z5jCWg0C6kPIBvNdzt +B0eheWS+ZxVwkePTR4e17kIafwknth3lo+orxVrq/xC+OVM1bGrt2ZyD64ZvEqQl +w6kgbzBdLScAQptWOFThwhnJsg0UbYKimZsnYmjVEuN59TJv92M= +-----END CERTIFICATE----- From 992efbd84adc8adbb3259476983876f87b552cc8 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sat, 5 Mar 2022 19:35:15 +0100 Subject: [PATCH 179/204] Added missing private TLS key --- .../etc_embedded_derp/tls/server.key | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 integration_test/etc_embedded_derp/tls/server.key diff --git a/integration_test/etc_embedded_derp/tls/server.key b/integration_test/etc_embedded_derp/tls/server.key new file mode 100644 index 0000000..8a2df34 --- /dev/null +++ b/integration_test/etc_embedded_derp/tls/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDqcfpToLZUF0rl +NwXkkt3lbyw4Cl4TJdx36o2PKaOKU+tze/IjRsCWeMwrcR1o9TNZcxsD+c2J48D1 +WATuQJlMeg+2UJXGaTGRKkkbPMy35m7AFf/Q16UEOgm2NYjZaQ8faRGIMYURG/6s +XmNeETJvBixpBev9yKJuVXgqHNS4NpEkNwdOCuAZXrmw0HCbiusawJOay4tFvhH1 +4rav8Uimonl8UTNVXufMzyUOuoaQTGflmzYX3hIoswRnTPlIWFoqObvx2Q8H+of3 +uQJXy0m8I6OrIoXLNxnqYMfFls799SYgVc2jPsCbh5fwyRbx2Hof7sIZ1K/mNgxJ +RG1E3ZiLAgMBAAECggEBALu1Ni/u5Qy++YA8ZcN0s6UXNdhItLmv/q0kZuLQ+9et +CT8VZfFInLndTdsaXenDKLHdryunviFA8SV+q7P2lMbek+Xs735EiyMnMBFWxLIZ +FWNGOeQERGL19QCmLEOmEi2b+iWJQHlKaMWpbPXL3w11a+lKjIBNO4ALfoJ5QveZ +cGMKsJdm/mpqBvLeNeh2eAFk3Gp6sT1g80Ge8NkgyzFBNIqnut0eerM15kPTc6Qz +12JLaOXUuV3PrcB4PN4nOwrTDg88GDNOQtc1Pc9r4nOHyLfr8X7QEtj1wXSwmOuK +d6ynMnAmoxVA9wEnupLbil1bzohRzpsTpkmDruYaBEECgYEA/Z09I8D6mt2NVqIE +KyvLjBK39ijSV9r3/lvB2Ple2OOL5YQEd+yTrIFy+3zdUnDgD1zmNnXjmjvHZ9Lc +IFf2o06AF84QLNB5gLPdDQkGNFdDqUxljBrfAfE3oANmPS/B0SijMGOOOiDO2FtO +xl1nfRr78mswuRs9awoUWCdNRKUCgYEA7KaTYKIQW/FEjw9lshp74q5vbn6zoXF5 +7N8VkwI+bBVNvRbM9XZ8qhfgRdu9eXs5oL/N4mSYY54I8fA//pJ0Z2vpmureMm1V +mL5WBUmSD9DIbAchoK+sRiQhVmNMBQC6cHMABA7RfXvBeGvWrm9pKCS6ZLgLjkjp +PsmAcaXQcW8CgYEA2inAxljjOwUK6FNGsrxhxIT1qtNC3kCGxE+6WSNq67gSR8Vg +8qiX//T7LEslOB3RIGYRwxd2St7RkgZZRZllmOWWWuPwFhzf6E7RAL2akLvggGov +kG4tGEagSw2hjVDfsUT73ExHtMk0Jfmlsg33UC8+PDLpHtLH6qQpDAwC8+ECgYEA +o+AqOIWhvHmT11l7O915Ip1WzvZwYADbxLsrDnVEUsZh4epTHjvh0kvcY6PqTqCV +ZIrOANNWb811Nkz/k8NJVoD08PFp0xPBbZeIq/qpachTsfMyRzq/mobUiyUR9Hjv +ooUQYr78NOApNsG+lWbTNBhS9wI4BlzZIECbcJe5g4MCgYEAndRoy8S+S0Hx/S8a +O3hzXeDmivmgWqn8NVD4AKOovpkz4PaIVVQbAQkiNfAx8/DavPvjEKAbDezJ4ECV +j7IsOWtDVI7pd6eF9fTcECwisrda8aUoiOap8AQb48153Vx+g2N4Vy3uH0xJs4cz +TDALZPOBg8VlV+HEFDP43sp9Bf0= +-----END PRIVATE KEY----- From e78c002f5a0c4e941d6a7b822b3b926f5c6922b4 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sat, 5 Mar 2022 19:48:30 +0100 Subject: [PATCH 180/204] Fix minor issue --- derp_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/derp_server.go b/derp_server.go index d8abbc8..e900986 100644 --- a/derp_server.go +++ b/derp_server.go @@ -166,7 +166,7 @@ func refreshBootstrapDNS() { for _, name := range names { addrs, err := r.LookupIP(ctx, "ip", name) if err != nil { - log.Trace().Caller().Err(err).Msgf("bootstrap DNS lookup %q: %v", name) + log.Trace().Caller().Err(err).Msgf("bootstrap DNS lookup %q", name) continue } dnsEntries[name] = addrs From 54c3e00a1ffb89d2b96d988f8fe21b3280a577f6 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sat, 5 Mar 2022 20:04:31 +0100 Subject: [PATCH 181/204] Merge local DERP server region with other configured DERP sources --- app.go | 60 ++++++++------------------------------------------ derp.go | 1 + derp_server.go | 49 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 52 deletions(-) diff --git a/app.go b/app.go index 4568558..8cb987a 100644 --- a/app.go +++ b/app.go @@ -13,7 +13,6 @@ import ( "os" "os/signal" "sort" - "strconv" "strings" "sync" "syscall" @@ -247,48 +246,6 @@ func NewHeadscale(cfg Config) (*Headscale, error) { return nil, err } app.DERPServer = embeddedDERPServer - - serverURL, err := url.Parse(app.cfg.ServerURL) - if err != nil { - return nil, err - } - var host string - var port int - host, portStr, err := net.SplitHostPort(serverURL.Host) - if err != nil { - if serverURL.Scheme == "https" { - host = serverURL.Host - port = 443 - } else { - host = serverURL.Host - port = 80 - } - } else { - port, err = strconv.Atoi(portStr) - if err != nil { - return nil, err - } - } - - app.DERPMap = &tailcfg.DERPMap{ - Regions: map[int]*tailcfg.DERPRegion{ - 999: { - RegionID: 999, - RegionCode: "headscale", - RegionName: "Headscale Embedded DERP", - Avoid: false, - Nodes: []*tailcfg.DERPNode{ - { - Name: "999a", - RegionID: 999, - HostName: host, - DERPPort: port, - }, - }, - }, - }, - OmitDefaultRegions: false, - } } return &app, nil @@ -536,17 +493,18 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine { func (h *Headscale) Serve() error { var err error + // Fetch an initial DERP Map before we start serving + h.DERPMap = GetDERPMap(h.cfg.DERP) + if h.cfg.DERP.ServerEnabled { go h.ServeSTUN() - } else { - // Fetch an initial DERP Map before we start serving - h.DERPMap = GetDERPMap(h.cfg.DERP) + h.DERPMap.Regions[h.DERPServer.region.RegionID] = &h.DERPServer.region + } - if h.cfg.DERP.AutoUpdate { - derpMapCancelChannel := make(chan struct{}) - defer func() { derpMapCancelChannel <- struct{}{} }() - go h.scheduledDERPMapUpdateWorker(derpMapCancelChannel) - } + if h.cfg.DERP.AutoUpdate { + derpMapCancelChannel := make(chan struct{}) + defer func() { derpMapCancelChannel <- struct{}{} }() + go h.scheduledDERPMapUpdateWorker(derpMapCancelChannel) } go h.expireEphemeralNodes(updateInterval) diff --git a/derp.go b/derp.go index 63e448d..7a9b236 100644 --- a/derp.go +++ b/derp.go @@ -148,6 +148,7 @@ func (h *Headscale) scheduledDERPMapUpdateWorker(cancelChan <-chan struct{}) { case <-ticker.C: log.Info().Msg("Fetching DERPMap updates") h.DERPMap = GetDERPMap(h.cfg.DERP) + h.DERPMap.Regions[h.DERPServer.region.RegionID] = &h.DERPServer.region namespaces, err := h.ListNamespaces() if err != nil { diff --git a/derp_server.go b/derp_server.go index e900986..81cb1e2 100644 --- a/derp_server.go +++ b/derp_server.go @@ -6,6 +6,8 @@ import ( "fmt" "net" "net/http" + "net/url" + "strconv" "strings" "sync/atomic" "time" @@ -14,6 +16,7 @@ import ( "github.com/rs/zerolog/log" "tailscale.com/derp" "tailscale.com/net/stun" + "tailscale.com/tailcfg" "tailscale.com/types/key" ) @@ -30,12 +33,56 @@ var ( type DERPServer struct { tailscaleDERP *derp.Server + region tailcfg.DERPRegion } func (h *Headscale) NewDERPServer() (*DERPServer, error) { s := derp.NewServer(key.NodePrivate(*h.privateKey), log.Info().Msgf) - return &DERPServer{s}, nil + region, err := h.generateRegionLocalDERP() + if err != nil { + return nil, err + } + return &DERPServer{s, region}, nil +} +func (h *Headscale) generateRegionLocalDERP() (tailcfg.DERPRegion, error) { + serverURL, err := url.Parse(h.cfg.ServerURL) + if err != nil { + return tailcfg.DERPRegion{}, err + } + var host string + var port int + host, portStr, err := net.SplitHostPort(serverURL.Host) + if err != nil { + if serverURL.Scheme == "https" { + host = serverURL.Host + port = 443 + } else { + host = serverURL.Host + port = 80 + } + } else { + port, err = strconv.Atoi(portStr) + if err != nil { + return tailcfg.DERPRegion{}, err + } + } + + localDERPregion := tailcfg.DERPRegion{ + RegionID: 999, + RegionCode: "headscale", + RegionName: "Headscale Embedded DERP", + Avoid: false, + Nodes: []*tailcfg.DERPNode{ + { + Name: "999a", + RegionID: 999, + HostName: host, + DERPPort: port, + }, + }, + } + return localDERPregion, nil } func (h *Headscale) DERPHandler(ctx *gin.Context) { From 70910c459548304d00b5520525455910920dd353 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 6 Mar 2022 01:23:35 +0100 Subject: [PATCH 182/204] Working /bootstrap-dns DERP helper --- derp_server.go | 73 +++++++++++++++----------------------------------- 1 file changed, 22 insertions(+), 51 deletions(-) diff --git a/derp_server.go b/derp_server.go index 81cb1e2..dcda63e 100644 --- a/derp_server.go +++ b/derp_server.go @@ -2,14 +2,12 @@ package headscale import ( "context" - "encoding/json" "fmt" "net" "net/http" "net/url" "strconv" "strings" - "sync/atomic" "time" "github.com/gin-gonic/gin" @@ -26,11 +24,6 @@ import ( // following its HTTP request. const fastStartHeader = "Derp-Fast-Start" -var ( - dnsCache atomic.Value // of []byte - bootstrapDNS = "derp.tailscale.com" -) - type DERPServer struct { tailscaleDERP *derp.Server region tailcfg.DERPRegion @@ -137,14 +130,29 @@ func (h *Headscale) DERPProbeHandler(ctx *gin.Context) { } } +// DERPBootstrapDNSHandler implements the /bootsrap-dns endpoint +// Described in https://github.com/tailscale/tailscale/issues/1405, +// this endpoint provides a way to help a client when it fails to start up +// because its DNS are broken. +// The initial implementation is here https://github.com/tailscale/tailscale/pull/1406 +// They have a cache, but not clear if that is really necessary at Headscale, uh, scale. func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) { - ctx.Header("Content-Type", "application/json") - j, _ := dnsCache.Load().([]byte) - // Bootstrap DNS requests occur cross-regions, - // and are randomized per request, - // so keeping a connection open is pointlessly expensive. - ctx.Header("Connection", "close") - ctx.Writer.Write(j) + dnsEntries := make(map[string][]net.IP) + + resolvCtx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + var r net.Resolver + for _, region := range h.DERPMap.Regions { + for _, node := range region.Nodes { // we don't care if we override some nodes + addrs, err := r.LookupIP(resolvCtx, "ip", node.HostName) + if err != nil { + log.Trace().Caller().Err(err).Msgf("bootstrap DNS lookup failed %q", node.HostName) + continue + } + dnsEntries[node.HostName] = addrs + } + } + ctx.JSON(http.StatusOK, dnsEntries) } // ServeSTUN starts a STUN server on udp/3478 @@ -188,40 +196,3 @@ func serverSTUNListener(ctx context.Context, pc *net.UDPConn) { pc.WriteTo(res, ua) } } - -// Shamelessly taken from -// https://github.com/tailscale/tailscale/blob/main/cmd/derper/bootstrap_dns.go -func refreshBootstrapDNSLoop() { - if bootstrapDNS == "" { - return - } - for { - refreshBootstrapDNS() - time.Sleep(10 * time.Minute) - } -} - -func refreshBootstrapDNS() { - if bootstrapDNS == "" { - return - } - dnsEntries := make(map[string][]net.IP) - ctx, cancel := context.WithTimeout(context.Background(), time.Minute) - defer cancel() - names := strings.Split(bootstrapDNS, ",") - var r net.Resolver - for _, name := range names { - addrs, err := r.LookupIP(ctx, "ip", name) - if err != nil { - log.Trace().Caller().Err(err).Msgf("bootstrap DNS lookup %q", name) - continue - } - dnsEntries[name] = addrs - } - j, err := json.MarshalIndent(dnsEntries, "", "\t") - if err != nil { - // leave the old values in place - return - } - dnsCache.Store(j) -} From dc909ba6d7ce48e0ed3d6f6415f301ef2653a903 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 6 Mar 2022 16:54:19 +0100 Subject: [PATCH 183/204] Improved logging on startup --- cmd/headscale/cli/server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/headscale/cli/server.go b/cmd/headscale/cli/server.go index 6d9ad19..b741f29 100644 --- a/cmd/headscale/cli/server.go +++ b/cmd/headscale/cli/server.go @@ -1,7 +1,7 @@ package cli import ( - "log" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) @@ -19,12 +19,12 @@ var serveCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { h, err := getHeadscaleApp() if err != nil { - log.Fatalf("Error initializing: %s", err) + log.Fatal().Caller().Err(err).Msg("Error initializing") } err = h.Serve() if err != nil { - log.Fatalf("Error initializing: %s", err) + log.Fatal().Caller().Err(err).Msg("Error starting server") } }, } From eb500155e84847774d79b8454c0327e37c23c0ff Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 6 Mar 2022 17:00:56 +0100 Subject: [PATCH 184/204] Make STUN server configurable --- app.go | 6 +++++- cmd/headscale/cli/utils.go | 4 ++++ config-example.yaml | 6 ++++++ derp_server.go | 22 ++++++++++++++++++---- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/app.go b/app.go index 8cb987a..82e87cf 100644 --- a/app.go +++ b/app.go @@ -121,6 +121,8 @@ type OIDCConfig struct { type DERPConfig struct { ServerEnabled bool + STUNEnabled bool + STUNAddr string URLs []url.URL Paths []string AutoUpdate bool @@ -497,8 +499,10 @@ func (h *Headscale) Serve() error { h.DERPMap = GetDERPMap(h.cfg.DERP) if h.cfg.DERP.ServerEnabled { - go h.ServeSTUN() h.DERPMap.Regions[h.DERPServer.region.RegionID] = &h.DERPServer.region + if h.cfg.DERP.STUNEnabled { + go h.ServeSTUN() + } } if h.cfg.DERP.AutoUpdate { diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 7277723..e6dce3a 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -118,6 +118,8 @@ func LoadConfig(path string) error { func GetDERPConfig() headscale.DERPConfig { enabled := viper.GetBool("derp.server.enabled") + stunEnabled := viper.GetBool("derp.server.stun.enabled") + stunAddr := viper.GetString("derp.server.stun.listen_addr") urlStrs := viper.GetStringSlice("derp.urls") @@ -141,6 +143,8 @@ func GetDERPConfig() headscale.DERPConfig { return headscale.DERPConfig{ ServerEnabled: enabled, + STUNEnabled: stunEnabled, + STUNAddr: stunAddr, URLs: urls, Paths: paths, AutoUpdate: autoUpdate, diff --git a/config-example.yaml b/config-example.yaml index 6f4060a..57b43fd 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -60,6 +60,12 @@ derp: # The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place enabled: false + # If enabled, also listens in the configured address for STUN connections to help on NAT traversal + # For more details on how this works, check this great article: https://tailscale.com/blog/how-tailscale-works/ + stun: + enabled: false + listen_addr: "0.0.0.0:3478" + # List of externally available DERP maps encoded in JSON urls: - https://controlplane.tailscale.com/derpmap/default diff --git a/derp_server.go b/derp_server.go index dcda63e..aeb4877 100644 --- a/derp_server.go +++ b/derp_server.go @@ -75,6 +75,19 @@ func (h *Headscale) generateRegionLocalDERP() (tailcfg.DERPRegion, error) { }, }, } + + if h.cfg.DERP.STUNEnabled { + _, portStr, err := net.SplitHostPort(h.cfg.DERP.STUNAddr) + if err != nil { + return tailcfg.DERPRegion{}, err + } + port, err := strconv.Atoi(portStr) + if err != nil { + return tailcfg.DERPRegion{}, err + } + localDERPregion.Nodes[0].STUNPort = port + } + return localDERPregion, nil } @@ -136,6 +149,7 @@ func (h *Headscale) DERPProbeHandler(ctx *gin.Context) { // because its DNS are broken. // The initial implementation is here https://github.com/tailscale/tailscale/pull/1406 // They have a cache, but not clear if that is really necessary at Headscale, uh, scale. +// An example implementation is found here https://derp.tailscale.com/bootstrap-dns func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) { dnsEntries := make(map[string][]net.IP) @@ -155,14 +169,14 @@ func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) { ctx.JSON(http.StatusOK, dnsEntries) } -// ServeSTUN starts a STUN server on udp/3478 +// ServeSTUN starts a STUN server on the configured addr func (h *Headscale) ServeSTUN() { - pc, err := net.ListenPacket("udp", "0.0.0.0:3478") + packetConn, err := net.ListenPacket("udp", h.cfg.DERP.STUNAddr) if err != nil { log.Fatal().Msgf("failed to open STUN listener: %v", err) } - log.Trace().Msgf("STUN server started at %s", pc.LocalAddr()) - serverSTUNListener(context.Background(), pc.(*net.UDPConn)) + log.Info().Msgf("STUN server started at %s", packetConn.LocalAddr()) + serverSTUNListener(context.Background(), packetConn.(*net.UDPConn)) } func serverSTUNListener(ctx context.Context, pc *net.UDPConn) { From eb06054a7b1e9d429b69d1c205ea81058468f60d Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 6 Mar 2022 17:25:21 +0100 Subject: [PATCH 185/204] Make DERP Region configurable --- app.go | 17 ++++++++++------- cmd/headscale/cli/utils.go | 22 ++++++++++++++-------- config-example.yaml | 9 +++++++++ derp_server.go | 14 ++++++++------ 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/app.go b/app.go index 82e87cf..f1426bb 100644 --- a/app.go +++ b/app.go @@ -120,13 +120,16 @@ type OIDCConfig struct { } type DERPConfig struct { - ServerEnabled bool - STUNEnabled bool - STUNAddr string - URLs []url.URL - Paths []string - AutoUpdate bool - UpdateFrequency time.Duration + ServerEnabled bool + ServerRegionID int + ServerRegionCode string + ServerRegionName string + STUNEnabled bool + STUNAddr string + URLs []url.URL + Paths []string + AutoUpdate bool + UpdateFrequency time.Duration } type CLIConfig struct { diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index e6dce3a..dc7a4e9 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -117,7 +117,10 @@ func LoadConfig(path string) error { } func GetDERPConfig() headscale.DERPConfig { - enabled := viper.GetBool("derp.server.enabled") + serverEnabled := viper.GetBool("derp.server.enabled") + serverRegionID := viper.GetInt("derp.server.region_id") + serverRegionCode := viper.GetString("derp.server.region_code") + serverRegionName := viper.GetString("derp.server.region_name") stunEnabled := viper.GetBool("derp.server.stun.enabled") stunAddr := viper.GetString("derp.server.stun.listen_addr") @@ -142,13 +145,16 @@ func GetDERPConfig() headscale.DERPConfig { updateFrequency := viper.GetDuration("derp.update_frequency") return headscale.DERPConfig{ - ServerEnabled: enabled, - STUNEnabled: stunEnabled, - STUNAddr: stunAddr, - URLs: urls, - Paths: paths, - AutoUpdate: autoUpdate, - UpdateFrequency: updateFrequency, + ServerEnabled: serverEnabled, + ServerRegionID: serverRegionID, + ServerRegionCode: serverRegionCode, + ServerRegionName: serverRegionName, + STUNEnabled: stunEnabled, + STUNAddr: stunAddr, + URLs: urls, + Paths: paths, + AutoUpdate: autoUpdate, + UpdateFrequency: updateFrequency, } } diff --git a/config-example.yaml b/config-example.yaml index 57b43fd..1ab92dc 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -60,6 +60,15 @@ derp: # The Headscale server_url defined above MUST be using https, DERP requires TLS to be in place enabled: false + # Region ID to use for the embedded DERP server. + # The local DERP prevails if the region ID collides with other region ID coming from + # the regular DERP config. + region_id: 999 + + # Region code and name are displayed in the Tailscale UI to identify a DERP region + region_code: "headscale" + region_name: "Headscale Embedded DERP" + # If enabled, also listens in the configured address for STUN connections to help on NAT traversal # For more details on how this works, check this great article: https://tailscale.com/blog/how-tailscale-works/ stun: diff --git a/derp_server.go b/derp_server.go index aeb4877..8995ca8 100644 --- a/derp_server.go +++ b/derp_server.go @@ -62,14 +62,14 @@ func (h *Headscale) generateRegionLocalDERP() (tailcfg.DERPRegion, error) { } localDERPregion := tailcfg.DERPRegion{ - RegionID: 999, - RegionCode: "headscale", - RegionName: "Headscale Embedded DERP", + RegionID: h.cfg.DERP.ServerRegionID, + RegionCode: h.cfg.DERP.ServerRegionCode, + RegionName: h.cfg.DERP.ServerRegionName, Avoid: false, Nodes: []*tailcfg.DERPNode{ { - Name: "999a", - RegionID: 999, + Name: fmt.Sprintf("%d", h.cfg.DERP.ServerRegionID), + RegionID: h.cfg.DERP.ServerRegionID, HostName: host, DERPPort: port, }, @@ -108,6 +108,7 @@ func (h *Headscale) DERPHandler(ctx *gin.Context) { if !ok { log.Error().Caller().Msg("DERP requires Hijacker interface from Gin") ctx.String(http.StatusInternalServerError, "HTTP does not support general TCP support") + return } @@ -115,6 +116,7 @@ func (h *Headscale) DERPHandler(ctx *gin.Context) { if err != nil { log.Error().Caller().Err(err).Msgf("Hijack failed") ctx.String(http.StatusInternalServerError, "HTTP does not support general TCP support") + return } @@ -169,7 +171,7 @@ func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) { ctx.JSON(http.StatusOK, dnsEntries) } -// ServeSTUN starts a STUN server on the configured addr +// ServeSTUN starts a STUN server on the configured addr. func (h *Headscale) ServeSTUN() { packetConn, err := net.ListenPacket("udp", h.cfg.DERP.STUNAddr) if err != nil { From de2ea83b3b87c0d043f8dec45d788159722198f2 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 6 Mar 2022 17:35:54 +0100 Subject: [PATCH 186/204] Linting here and there --- acls.go | 11 +++++------ cmd/headscale/cli/server.go | 1 - derp_server.go | 39 ++++++++++++++++++++++++------------- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/acls.go b/acls.go index 24aadf5..9548480 100644 --- a/acls.go +++ b/acls.go @@ -17,12 +17,11 @@ import ( ) const ( - errEmptyPolicy = Error("empty policy") - errInvalidAction = Error("invalid action") - errInvalidUserSection = Error("invalid user section") - errInvalidGroup = Error("invalid group") - errInvalidTag = Error("invalid tag") - errInvalidPortFormat = Error("invalid port format") + errEmptyPolicy = Error("empty policy") + errInvalidAction = Error("invalid action") + errInvalidGroup = Error("invalid group") + errInvalidTag = Error("invalid tag") + errInvalidPortFormat = Error("invalid port format") ) const ( diff --git a/cmd/headscale/cli/server.go b/cmd/headscale/cli/server.go index b741f29..c19580b 100644 --- a/cmd/headscale/cli/server.go +++ b/cmd/headscale/cli/server.go @@ -2,7 +2,6 @@ package cli import ( "github.com/rs/zerolog/log" - "github.com/spf13/cobra" ) diff --git a/derp_server.go b/derp_server.go index 8995ca8..9e1b7e5 100644 --- a/derp_server.go +++ b/derp_server.go @@ -30,12 +30,13 @@ type DERPServer struct { } func (h *Headscale) NewDERPServer() (*DERPServer, error) { - s := derp.NewServer(key.NodePrivate(*h.privateKey), log.Info().Msgf) + server := derp.NewServer(key.NodePrivate(*h.privateKey), log.Info().Msgf) region, err := h.generateRegionLocalDERP() if err != nil { return nil, err } - return &DERPServer{s, region}, nil + + return &DERPServer{server, region}, nil } func (h *Headscale) generateRegionLocalDERP() (tailcfg.DERPRegion, error) { @@ -99,6 +100,7 @@ func (h *Headscale) DERPHandler(ctx *gin.Context) { log.Warn().Caller().Msgf("Weird websockets connection upgrade: %q", up) } ctx.String(http.StatusUpgradeRequired, "DERP requires connection upgrade") + return } @@ -122,13 +124,14 @@ func (h *Headscale) DERPHandler(ctx *gin.Context) { if !fastStart { pubKey := h.privateKey.Public() + pubKeyStr := pubKey.UntypedHexString() // nolint fmt.Fprintf(conn, "HTTP/1.1 101 Switching Protocols\r\n"+ "Upgrade: DERP\r\n"+ "Connection: Upgrade\r\n"+ "Derp-Version: %v\r\n"+ "Derp-Public-Key: %s\r\n\r\n", derp.ProtocolVersion, - pubKey.UntypedHexString()) + pubKeyStr) } h.DERPServer.tailscaleDERP.Accept(netConn, conn, netConn.RemoteAddr().String()) @@ -163,6 +166,7 @@ func (h *Headscale) DERPBootstrapDNSHandler(ctx *gin.Context) { addrs, err := r.LookupIP(resolvCtx, "ip", node.HostName) if err != nil { log.Trace().Caller().Err(err).Msgf("bootstrap DNS lookup failed %q", node.HostName) + continue } dnsEntries[node.HostName] = addrs @@ -178,28 +182,34 @@ func (h *Headscale) ServeSTUN() { log.Fatal().Msgf("failed to open STUN listener: %v", err) } log.Info().Msgf("STUN server started at %s", packetConn.LocalAddr()) - serverSTUNListener(context.Background(), packetConn.(*net.UDPConn)) + + udpConn, ok := packetConn.(*net.UDPConn) + if !ok { + log.Fatal().Msg("STUN listener is not a UDP listener") + } + serverSTUNListener(context.Background(), udpConn) } -func serverSTUNListener(ctx context.Context, pc *net.UDPConn) { +func serverSTUNListener(ctx context.Context, packetConn *net.UDPConn) { var buf [64 << 10]byte var ( - n int - ua *net.UDPAddr - err error + bytesRead int + udpAddr *net.UDPAddr + err error ) for { - n, ua, err = pc.ReadFromUDP(buf[:]) + bytesRead, udpAddr, err = packetConn.ReadFromUDP(buf[:]) if err != nil { if ctx.Err() != nil { return } log.Error().Caller().Err(err).Msgf("STUN ReadFrom") time.Sleep(time.Second) + continue } - log.Trace().Caller().Msgf("STUN request from %v", ua) - pkt := buf[:n] + log.Trace().Caller().Msgf("STUN request from %v", udpAddr) + pkt := buf[:bytesRead] if !stun.Is(pkt) { continue } @@ -208,7 +218,10 @@ func serverSTUNListener(ctx context.Context, pc *net.UDPConn) { continue } - res := stun.Response(txid, ua.IP, uint16(ua.Port)) - pc.WriteTo(res, ua) + res := stun.Response(txid, udpAddr.IP, uint16(udpAddr.Port)) + _, err = packetConn.WriteTo(res, udpAddr) + if err != nil { + continue + } } } From e1fcf0da262244ccde3f6c9117acf50bd326c532 Mon Sep 17 00:00:00 2001 From: Juan Font Date: Sun, 6 Mar 2022 20:40:55 +0100 Subject: [PATCH 187/204] Added more version Co-authored-by: Kristoffer Dalby --- integration_common_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_common_test.go b/integration_common_test.go index a341712..70285fc 100644 --- a/integration_common_test.go +++ b/integration_common_test.go @@ -20,7 +20,7 @@ var ( IpPrefix4 = netaddr.MustParseIPPrefix("100.64.0.0/10") IpPrefix6 = netaddr.MustParseIPPrefix("fd7a:115c:a1e0::/48") - tailscaleVersions = []string{"1.20.4", "1.18.2", "1.16.2", "1.14.3", "1.12.3"} + tailscaleVersions = []string{"1.22.0", "1.20.4", "1.18.2", "1.16.2", "1.14.3", "1.12.3"} ) type TestNamespace struct { From b47de07eea7bf0ec637f24bb5ad0c1aad9ab2961 Mon Sep 17 00:00:00 2001 From: Juan Font Date: Sun, 6 Mar 2022 20:42:27 +0100 Subject: [PATCH 188/204] Update Dockerfile.tailscale Co-authored-by: Kristoffer Dalby --- Dockerfile.tailscale | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.tailscale b/Dockerfile.tailscale index fded837..32a8ce7 100644 --- a/Dockerfile.tailscale +++ b/Dockerfile.tailscale @@ -13,4 +13,4 @@ RUN apt-get update \ ADD integration_test/etc_embedded_derp/tls/server.crt /usr/local/share/ca-certificates/ RUN chmod 644 /usr/local/share/ca-certificates/server.crt -RUN update-ca-certificates \ No newline at end of file +RUN update-ca-certificates From 11144496015a2ee6dfd80046aace3c5e68c3d12b Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 6 Mar 2022 20:46:17 +0100 Subject: [PATCH 189/204] change: update name of method to check and normalize Domain name --- acls.go | 2 +- namespaces.go | 14 +++++++------- namespaces_test.go | 8 ++++---- oidc.go | 2 +- poll.go | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/acls.go b/acls.go index 9548480..e542a0f 100644 --- a/acls.go +++ b/acls.go @@ -444,7 +444,7 @@ func expandGroup( errInvalidGroup, ) } - grp, err := NormalizeNamespaceName(group, stripEmailDomain) + grp, err := NormalizeName(group, stripEmailDomain) if err != nil { return []string{}, fmt.Errorf( "failed to normalize group %q, err: %w", diff --git a/namespaces.go b/namespaces.go index 3151784..74b125d 100644 --- a/namespaces.go +++ b/namespaces.go @@ -41,7 +41,7 @@ type Namespace struct { // CreateNamespace creates a new Namespace. Returns error if could not be created // or another namespace already exists. func (h *Headscale) CreateNamespace(name string) (*Namespace, error) { - err := CheckNamespaceName(name) + err := CheckName(name) if err != nil { return nil, err } @@ -104,7 +104,7 @@ func (h *Headscale) RenameNamespace(oldName, newName string) error { if err != nil { return err } - err = CheckNamespaceName(newName) + err = CheckName(newName) if err != nil { return err } @@ -150,7 +150,7 @@ func (h *Headscale) ListNamespaces() ([]Namespace, error) { // ListMachinesInNamespace gets all the nodes in a given namespace. func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { - err := CheckNamespaceName(name) + err := CheckName(name) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { // SetMachineNamespace assigns a Machine to a namespace. func (h *Headscale) SetMachineNamespace(machine *Machine, namespaceName string) error { - err := CheckNamespaceName(namespaceName) + err := CheckName(namespaceName) if err != nil { return err } @@ -237,9 +237,9 @@ func (n *Namespace) toProto() *v1.Namespace { } } -// NormalizeNamespaceName will replace forbidden chars in namespace +// NormalizeName will replace forbidden chars in namespace // it can also return an error if the namespace doesn't respect RFC 952 and 1123. -func NormalizeNamespaceName(name string, stripEmailDomain bool) (string, error) { +func NormalizeName(name string, stripEmailDomain bool) (string, error) { name = strings.ToLower(name) name = strings.ReplaceAll(name, "'", "") atIdx := strings.Index(name, "@") @@ -263,7 +263,7 @@ func NormalizeNamespaceName(name string, stripEmailDomain bool) (string, error) return name, nil } -func CheckNamespaceName(name string) error { +func CheckName(name string) error { if len(name) > labelHostnameLength { return fmt.Errorf( "Namespace must not be over 63 chars. %v doesn't comply with this rule: %w", diff --git a/namespaces_test.go b/namespaces_test.go index 1710f7d..406dccf 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -233,7 +233,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { c.Assert(found, check.Equals, true) } -func TestNormalizeNamespaceName(t *testing.T) { +func TestNormalizeName(t *testing.T) { type args struct { name string stripEmailDomain bool @@ -310,7 +310,7 @@ func TestNormalizeNamespaceName(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NormalizeNamespaceName(tt.args.name, tt.args.stripEmailDomain) + got, err := NormalizeName(tt.args.name, tt.args.stripEmailDomain) if (err != nil) != tt.wantErr { t.Errorf( "NormalizeNamespaceName() error = %v, wantErr %v", @@ -327,7 +327,7 @@ func TestNormalizeNamespaceName(t *testing.T) { } } -func TestCheckNamespaceName(t *testing.T) { +func TestCheckName(t *testing.T) { type args struct { name string } @@ -366,7 +366,7 @@ func TestCheckNamespaceName(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CheckNamespaceName(tt.args.name); (err != nil) != tt.wantErr { + if err := CheckName(tt.args.name); (err != nil) != tt.wantErr { t.Errorf("CheckNamespaceName() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/oidc.go b/oidc.go index 987bc8b..a81c4b5 100644 --- a/oidc.go +++ b/oidc.go @@ -253,7 +253,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - namespaceName, err := NormalizeNamespaceName( + namespaceName, err := NormalizeName( claims.Email, h.cfg.OIDC.StripEmaildomain, ) diff --git a/poll.go b/poll.go index 5723a3d..0bdd80c 100644 --- a/poll.go +++ b/poll.go @@ -83,7 +83,7 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { Str("machine", machine.Name). Msg("Found machine in database") - hname, err := NormalizeNamespaceName( + hname, err := NormalizeName( req.Hostinfo.Hostname, h.cfg.OIDC.StripEmaildomain, ) From 580db9b58fe786fc23d1506ab3907dc8d4f5235d Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 6 Mar 2022 23:19:21 +0100 Subject: [PATCH 190/204] Mention that STUN is UDP --- config-example.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-example.yaml b/config-example.yaml index 1ab92dc..2075e69 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -69,7 +69,7 @@ derp: region_code: "headscale" region_name: "Headscale Embedded DERP" - # If enabled, also listens in the configured address for STUN connections to help on NAT traversal + # If enabled, also listens in UDP at the configured address for STUN connections to help on NAT traversal # For more details on how this works, check this great article: https://tailscale.com/blog/how-tailscale-works/ stun: enabled: false From a27b386123a815f9841b7109e01349e55f91c723 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 6 Mar 2022 23:45:01 +0100 Subject: [PATCH 191/204] Clarified expiration dates --- integration_test/etc_embedded_derp/tls/server.crt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/integration_test/etc_embedded_derp/tls/server.crt b/integration_test/etc_embedded_derp/tls/server.crt index 4895388..9555649 100644 --- a/integration_test/etc_embedded_derp/tls/server.crt +++ b/integration_test/etc_embedded_derp/tls/server.crt @@ -1,3 +1,4 @@ + -----BEGIN CERTIFICATE----- MIIC8jCCAdqgAwIBAgIULbu+UbSTMG/LtxooLLh7BgSEyqEwDQYJKoZIhvcNAQEL BQAwFDESMBAGA1UEAwwJaGVhZHNjYWxlMCAXDTIyMDMwNTE2NDgwM1oYDzI1MjEx @@ -16,3 +17,6 @@ guUt1JkAqrynv1UvR/2ZRM/WzM/oJ8qfECwrwDxyYhkqU5Z5jCWg0C6kPIBvNdzt B0eheWS+ZxVwkePTR4e17kIafwknth3lo+orxVrq/xC+OVM1bGrt2ZyD64ZvEqQl w6kgbzBdLScAQptWOFThwhnJsg0UbYKimZsnYmjVEuN59TJv92M= -----END CERTIFICATE----- + +(Expires on Nov 4 16:48:03 2521 GMT) + From b3fa66dbd2aebf4faf048bab563e1a5dad952ad7 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 6 Mar 2022 23:46:16 +0100 Subject: [PATCH 192/204] Check for DERP in test --- integration_embedded_derp_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_embedded_derp_test.go b/integration_embedded_derp_test.go index d95c460..e68da01 100644 --- a/integration_embedded_derp_test.go +++ b/integration_embedded_derp_test.go @@ -377,7 +377,7 @@ func (s *IntegrationDERPTestSuite) TestPingAllPeersByHostname() { ) assert.Nil(t, err) log.Printf("Result for %s: %s\n", hostname, result) - assert.Contains(t, result, "via DERP") + assert.Contains(t, result, "via DERP(headscale)") }) } } From 05df8e947aa61a87d9e49086a0b2d44fb47d3ccd Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 6 Mar 2022 23:47:14 +0100 Subject: [PATCH 193/204] Added missing file --- .../etc_embedded_derp/config.yaml | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 integration_test/etc_embedded_derp/config.yaml diff --git a/integration_test/etc_embedded_derp/config.yaml b/integration_test/etc_embedded_derp/config.yaml new file mode 100644 index 0000000..00f6332 --- /dev/null +++ b/integration_test/etc_embedded_derp/config.yaml @@ -0,0 +1,30 @@ +log_level: trace +acl_policy_path: "" +db_type: sqlite3 +ephemeral_node_inactivity_timeout: 30m +ip_prefixes: + - fd7a:115c:a1e0::/48 + - 100.64.0.0/10 +dns_config: + base_domain: headscale.net + magic_dns: true + domains: [] + nameservers: + - 1.1.1.1 +db_path: /tmp/integration_test_db.sqlite3 +private_key_path: private.key +listen_addr: 0.0.0.0:8443 +server_url: https://headscale:8443 +tls_cert_path: "/etc/headscale/tls/server.crt" +tls_key_path: "/etc/headscale/tls/server.key" +tls_client_auth_mode: disabled + +derp: + server: + enabled: true + region_id: 999 + region_code: "headscale" + region_name: "Headscale Embedded DERP" + stun: + enabled: true + listen_addr: "0.0.0.0:3478" \ No newline at end of file From 03452a8dca9a4b6d956cd319b8d07c216bcb64db Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Mon, 7 Mar 2022 00:29:40 +0100 Subject: [PATCH 194/204] Prettied --- integration_test/etc_embedded_derp/config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/integration_test/etc_embedded_derp/config.yaml b/integration_test/etc_embedded_derp/config.yaml index 00f6332..6e5291f 100644 --- a/integration_test/etc_embedded_derp/config.yaml +++ b/integration_test/etc_embedded_derp/config.yaml @@ -18,7 +18,6 @@ server_url: https://headscale:8443 tls_cert_path: "/etc/headscale/tls/server.crt" tls_key_path: "/etc/headscale/tls/server.key" tls_client_auth_mode: disabled - derp: server: enabled: true From 6cc8bbc24fb0666b68d3ea9ba44dab83ec0d69a8 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 7 Mar 2022 22:46:29 +0100 Subject: [PATCH 195/204] feat(api): add normalisation at machine register step --- api.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/api.go b/api.go index 3b3b675..b4ad92f 100644 --- a/api.go +++ b/api.go @@ -134,6 +134,18 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { return } + hname, err := NormalizeName( + req.Hostinfo.Hostname, + h.cfg.OIDC.StripEmaildomain, + ) + if err != nil { + log.Error(). + Caller(). + Str("func", "RegistrationHandler"). + Str("hostinfo.name", req.Hostinfo.Hostname). + Err(err) + return + } // The machine did not have a key to authenticate, which means // that we rely on a method that calls back some how (OpenID or CLI) @@ -141,7 +153,7 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { // happens newMachine := Machine{ MachineKey: machineKeyStr, - Name: req.Hostinfo.Hostname, + Name: hname, NodeKey: NodePublicKeyStripPrefix(req.NodeKey), LastSeen: &now, Expiry: &time.Time{}, From f19c0485698b6e7a2131c7f4534e79a796962a62 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 7 Mar 2022 22:55:54 +0100 Subject: [PATCH 196/204] fix: change normalization function name --- api.go | 2 +- namespaces.go | 14 +++++++------- namespaces_test.go | 14 +++++++------- oidc.go | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/api.go b/api.go index b4ad92f..fec79a2 100644 --- a/api.go +++ b/api.go @@ -134,7 +134,7 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { return } - hname, err := NormalizeName( + hname, err := NormalizeToFQDNRules( req.Hostinfo.Hostname, h.cfg.OIDC.StripEmaildomain, ) diff --git a/namespaces.go b/namespaces.go index 74b125d..bb32795 100644 --- a/namespaces.go +++ b/namespaces.go @@ -41,7 +41,7 @@ type Namespace struct { // CreateNamespace creates a new Namespace. Returns error if could not be created // or another namespace already exists. func (h *Headscale) CreateNamespace(name string) (*Namespace, error) { - err := CheckName(name) + err := CheckForFQDNRules(name) if err != nil { return nil, err } @@ -104,7 +104,7 @@ func (h *Headscale) RenameNamespace(oldName, newName string) error { if err != nil { return err } - err = CheckName(newName) + err = CheckForFQDNRules(newName) if err != nil { return err } @@ -150,7 +150,7 @@ func (h *Headscale) ListNamespaces() ([]Namespace, error) { // ListMachinesInNamespace gets all the nodes in a given namespace. func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { - err := CheckName(name) + err := CheckForFQDNRules(name) if err != nil { return nil, err } @@ -169,7 +169,7 @@ func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) { // SetMachineNamespace assigns a Machine to a namespace. func (h *Headscale) SetMachineNamespace(machine *Machine, namespaceName string) error { - err := CheckName(namespaceName) + err := CheckForFQDNRules(namespaceName) if err != nil { return err } @@ -237,9 +237,9 @@ func (n *Namespace) toProto() *v1.Namespace { } } -// NormalizeName will replace forbidden chars in namespace +// NormalizeToFQDNRules will replace forbidden chars in namespace // it can also return an error if the namespace doesn't respect RFC 952 and 1123. -func NormalizeName(name string, stripEmailDomain bool) (string, error) { +func NormalizeToFQDNRules(name string, stripEmailDomain bool) (string, error) { name = strings.ToLower(name) name = strings.ReplaceAll(name, "'", "") atIdx := strings.Index(name, "@") @@ -263,7 +263,7 @@ func NormalizeName(name string, stripEmailDomain bool) (string, error) { return name, nil } -func CheckName(name string) error { +func CheckForFQDNRules(name string) error { if len(name) > labelHostnameLength { return fmt.Errorf( "Namespace must not be over 63 chars. %v doesn't comply with this rule: %w", diff --git a/namespaces_test.go b/namespaces_test.go index 406dccf..5d873bd 100644 --- a/namespaces_test.go +++ b/namespaces_test.go @@ -233,7 +233,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { c.Assert(found, check.Equals, true) } -func TestNormalizeName(t *testing.T) { +func TestNormalizeToFQDNRules(t *testing.T) { type args struct { name string stripEmailDomain bool @@ -310,10 +310,10 @@ func TestNormalizeName(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := NormalizeName(tt.args.name, tt.args.stripEmailDomain) + got, err := NormalizeToFQDNRules(tt.args.name, tt.args.stripEmailDomain) if (err != nil) != tt.wantErr { t.Errorf( - "NormalizeNamespaceName() error = %v, wantErr %v", + "NormalizeToFQDNRules() error = %v, wantErr %v", err, tt.wantErr, ) @@ -321,13 +321,13 @@ func TestNormalizeName(t *testing.T) { return } if got != tt.want { - t.Errorf("NormalizeNamespaceName() = %v, want %v", got, tt.want) + t.Errorf("NormalizeToFQDNRules() = %v, want %v", got, tt.want) } }) } } -func TestCheckName(t *testing.T) { +func TestCheckForFQDNRules(t *testing.T) { type args struct { name string } @@ -366,8 +366,8 @@ func TestCheckName(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := CheckName(tt.args.name); (err != nil) != tt.wantErr { - t.Errorf("CheckNamespaceName() error = %v, wantErr %v", err, tt.wantErr) + if err := CheckForFQDNRules(tt.args.name); (err != nil) != tt.wantErr { + t.Errorf("CheckForFQDNRules() error = %v, wantErr %v", err, tt.wantErr) } }) } diff --git a/oidc.go b/oidc.go index a81c4b5..29ce351 100644 --- a/oidc.go +++ b/oidc.go @@ -253,7 +253,7 @@ func (h *Headscale) OIDCCallback(ctx *gin.Context) { return } - namespaceName, err := NormalizeName( + namespaceName, err := NormalizeToFQDNRules( claims.Email, h.cfg.OIDC.StripEmaildomain, ) From 2b68c90778c89335bef35eb355aff432da9592db Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 7 Mar 2022 23:14:39 +0100 Subject: [PATCH 197/204] chore: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc34ab9..8535b45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - Nodes are now only written to database if they are registrated successfully - Fix a limitation in the ACLs that prevented users to write rules with `*` as source [#374](https://github.com/juanfont/headscale/issues/374) - Reduce the overhead of marshal/unmarshal for Hostinfo, routes and endpoints by using specific types in Machine [#371](https://github.com/juanfont/headscale/pull/371) +- Apply normalization function to FQDN on hostnames when hosts registers and retrieve informations [#363](https://github.com/juanfont/headscale/issues/363) ## 0.14.0 (2022-02-24) From 41efe98953388f62120f7ea3f7d94d1cccb3de32 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 7 Mar 2022 23:20:30 +0100 Subject: [PATCH 198/204] fix: apply fmt and fix missing name changes --- acls.go | 2 +- api.go | 1 + poll.go | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/acls.go b/acls.go index e542a0f..63c3955 100644 --- a/acls.go +++ b/acls.go @@ -444,7 +444,7 @@ func expandGroup( errInvalidGroup, ) } - grp, err := NormalizeName(group, stripEmailDomain) + grp, err := NormalizeToFQDNRules(group, stripEmailDomain) if err != nil { return []string{}, fmt.Errorf( "failed to normalize group %q, err: %w", diff --git a/api.go b/api.go index fec79a2..b5e885a 100644 --- a/api.go +++ b/api.go @@ -144,6 +144,7 @@ func (h *Headscale) RegistrationHandler(ctx *gin.Context) { Str("func", "RegistrationHandler"). Str("hostinfo.name", req.Hostinfo.Hostname). Err(err) + return } diff --git a/poll.go b/poll.go index 0bdd80c..15945a9 100644 --- a/poll.go +++ b/poll.go @@ -83,7 +83,7 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { Str("machine", machine.Name). Msg("Found machine in database") - hname, err := NormalizeName( + hname, err := NormalizeToFQDNRules( req.Hostinfo.Hostname, h.cfg.OIDC.StripEmaildomain, ) From 6aeaff43aa1cbb9f9eadcff975e21e01414b9d5e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 8 Mar 2022 07:21:04 +0000 Subject: [PATCH 199/204] Fix checkboxes in PR template --- .github/pull_request_template.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c701580..abd3b18 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,10 +1,10 @@ -- [] read the [CONTRIBUTING guidelines](README.md#user-content-contributing) -- [] raised a GitHub issue or discussed it on the projects chat beforehand -- [] added unit tests -- [] added integration tests -- [] updated documentation if needed -- [] updated CHANGELOG.md +- [ ] read the [CONTRIBUTING guidelines](README.md#user-content-contributing) +- [ ] raised a GitHub issue or discussed it on the projects chat beforehand +- [ ] added unit tests +- [ ] added integration tests +- [ ] updated documentation if needed +- [ ] updated CHANGELOG.md From c06689dec15cf2642b30c38e7f661aafe8e02889 Mon Sep 17 00:00:00 2001 From: e-zk Date: Tue, 8 Mar 2022 18:34:46 +1000 Subject: [PATCH 200/204] fix: make register html/template consistent with other html - makes the html/template for /register follow the same formatting as /apple and /windows - adds a element - minor change for consistency's sake --- api.go | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/api.go b/api.go index b5e885a..1023e6f 100644 --- a/api.go +++ b/api.go @@ -45,22 +45,21 @@ type registerWebAPITemplateConfig struct { } var registerWebAPITemplate = template.Must( - template.New("registerweb").Parse(`<html> + template.New("registerweb").Parse(` +<html> + <head> + <title>Registration - Headscale + -

headscale

-

- Run the command below in the headscale server to add this machine to your network: -

- -

- - headscale -n NAMESPACE nodes register --key {{.Key}} - -

- +

headscale

+

Machine registration

+

+ Run the command below in the headscale server to add this machine to your network: +

+
headscale -n NAMESPACE nodes register --key {{.Key}}
- `), -) + +`)) // RegisterWebAPI shows a simple message in the browser to point to the CLI // Listens in /register. From cc0c88a63ab193dc075bf0cac4962025bfccab04 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Tue, 8 Mar 2022 12:11:51 +0100 Subject: [PATCH 201/204] Added small integration test for stun --- derp_server.go | 6 ++++++ go.mod | 1 + go.sum | 2 ++ integration_embedded_derp_test.go | 12 ++++++++++++ 4 files changed, 21 insertions(+) diff --git a/derp_server.go b/derp_server.go index 9e1b7e5..11e3eb1 100644 --- a/derp_server.go +++ b/derp_server.go @@ -211,16 +211,22 @@ func serverSTUNListener(ctx context.Context, packetConn *net.UDPConn) { log.Trace().Caller().Msgf("STUN request from %v", udpAddr) pkt := buf[:bytesRead] if !stun.Is(pkt) { + log.Trace().Caller().Msgf("UDP packet is not STUN") + continue } txid, err := stun.ParseBindingRequest(pkt) if err != nil { + log.Trace().Caller().Err(err).Msgf("STUN parse error") + continue } res := stun.Response(txid, udpAddr.IP, uint16(udpAddr.Port)) _, err = packetConn.WriteTo(res, udpAddr) if err != nil { + log.Trace().Caller().Err(err).Msgf("Issue writing to UDP") + continue } } diff --git a/go.mod b/go.mod index d6754f9..1ec291c 100644 --- a/go.mod +++ b/go.mod @@ -49,6 +49,7 @@ require ( github.com/akutz/memconn v0.1.0 // indirect github.com/atomicgo/cursor v0.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/ccding/go-stun/stun v0.0.0-20200514191101-4dc67bcdb029 // indirect github.com/cenkalti/backoff/v4 v4.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/containerd/continuity v0.2.2 // indirect diff --git a/go.sum b/go.sum index c23db38..6d254a2 100644 --- a/go.sum +++ b/go.sum @@ -108,6 +108,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bufbuild/buf v0.37.0/go.mod h1:lQ1m2HkIaGOFba6w/aC3KYBHhKEOESP3gaAEpS3dAFM= +github.com/ccding/go-stun/stun v0.0.0-20200514191101-4dc67bcdb029 h1:POmUHfxXdeyM8Aomg4tKDcwATCFuW+cYLkj6pwsw9pc= +github.com/ccding/go-stun/stun v0.0.0-20200514191101-4dc67bcdb029/go.mod h1:Rpr5n9cGHYdM3S3IK8ROSUUUYjQOu+MSUCZDcJbYWi8= github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= diff --git a/integration_embedded_derp_test.go b/integration_embedded_derp_test.go index e68da01..a173717 100644 --- a/integration_embedded_derp_test.go +++ b/integration_embedded_derp_test.go @@ -23,6 +23,8 @@ import ( "github.com/ory/dockertest/v3/docker" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" + + "github.com/ccding/go-stun/stun" ) const ( @@ -382,3 +384,13 @@ func (s *IntegrationDERPTestSuite) TestPingAllPeersByHostname() { } } } + +func (s *IntegrationDERPTestSuite) TestDERPSTUN() { + headscaleSTUNAddr := fmt.Sprintf("localhost:%s", s.headscale.GetPort("3478/udp")) + client := stun.NewClient() + client.SetVerbose(true) + client.SetVVerbose(true) + client.SetServerAddr(headscaleSTUNAddr) + _, _, err := client.Discover() + assert.Nil(s.T(), err) +} From 05c5e2280b5e6fbe801195c3d1f1575d9f63b434 Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Tue, 8 Mar 2022 12:15:05 +0100 Subject: [PATCH 202/204] Updated CHANGELOG and README --- CHANGELOG.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8535b45..6ce0c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Users can now use emails in ACL's groups [#372](https://github.com/juanfont/headscale/issues/372) - Add shorthand aliases for commands and subcommands [#376](https://github.com/juanfont/headscale/pull/376) - Add `/windows` endpoint for Windows configuration instructions + registry file download [#392](https://github.com/juanfont/headscale/pull/392) +- Added embedded DERP server into Headscale [#388](https://github.com/juanfont/headscale/pull/388) ### Changes diff --git a/README.md b/README.md index 1b97b1a..ec66b08 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ one of the maintainers. - Dual stack (IPv4 and IPv6) - Routing advertising (including exit nodes) - Ephemeral nodes +- Embedded [DERP server](https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp) ## Client OS support From b803240dc1045e16da2bc79337c1bd33f8941bbb Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Tue, 8 Mar 2022 12:21:08 +0100 Subject: [PATCH 203/204] Added new line for prettier --- integration_test/etc_embedded_derp/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_test/etc_embedded_derp/config.yaml b/integration_test/etc_embedded_derp/config.yaml index 6e5291f..1531d34 100644 --- a/integration_test/etc_embedded_derp/config.yaml +++ b/integration_test/etc_embedded_derp/config.yaml @@ -26,4 +26,4 @@ derp: region_name: "Headscale Embedded DERP" stun: enabled: true - listen_addr: "0.0.0.0:3478" \ No newline at end of file + listen_addr: "0.0.0.0:3478" From c47fb1ae5445581fa1babe0eeeddfbf41b22b7a1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:50:11 +0000 Subject: [PATCH 204/204] docs(README): update contributors --- README.md | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index ec66b08..d74b19f 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,15 @@ make build ohdearaugustin
+ + e-zk/ +
+ e-zk +
+
Justin @@ -190,8 +199,6 @@ make build Justin Angel
Alessandro @@ -199,13 +206,6 @@ make build Alessandro (Ale) Segala - - e-zk/ -
- e-zk -
-
unreality/ @@ -382,6 +382,13 @@ make build rcursaru + + WhiteSource +
+ WhiteSource Renovate +
+
Ryan @@ -403,6 +410,8 @@ make build Tanner
Teteros/ @@ -410,8 +419,6 @@ make build Teteros
The @@ -447,6 +454,8 @@ make build ZiYuan
derelm/ @@ -454,8 +463,6 @@ make build derelm
ignoramous/