diff --git a/.github/workflows/golang-test-darwin.yml b/.github/workflows/golang-test-darwin.yml index 654048934..2311c54ff 100644 --- a/.github/workflows/golang-test-darwin.yml +++ b/.github/workflows/golang-test-darwin.yml @@ -26,4 +26,4 @@ jobs: run: go mod tidy - name: Test - run: go test -exec sudo -timeout 5m -p 1 ./... \ No newline at end of file + run: go test -exec 'sudo --preserve-env=CI' -timeout 5m -p 1 ./... \ No newline at end of file diff --git a/.github/workflows/golang-test-linux.yml b/.github/workflows/golang-test-linux.yml index 9f20682a4..f94696105 100644 --- a/.github/workflows/golang-test-linux.yml +++ b/.github/workflows/golang-test-linux.yml @@ -11,18 +11,7 @@ jobs: uses: actions/setup-go@v2 with: go-version: ${{ matrix.go-version }} -# - name: update limits.d -# run: | -# cat <<'EOF' | sudo tee -a /etc/security/limits.d/wt.conf -# root soft nproc 65535 -# root hard nproc 65535 -# root soft nofile 65535 -# root hard nofile 65535 -# $(whoami) soft nproc 65535 -# $(whoami) hard nproc 65535 -# $(whoami) soft nofile 65535 -# $(whoami) hard nofile 65535 -# EOF + - name: Cache Go modules uses: actions/cache@v2 @@ -42,4 +31,4 @@ jobs: run: go mod tidy - name: Test - run: go test -exec sudo -timeout 5m -p 1 ./... + run: go test -exec 'sudo --preserve-env=CI' -timeout 5m -p 1 ./... diff --git a/client/internal/oauth/auth0.go b/client/internal/oauth/auth0.go index 3370994bd..2f24f0979 100644 --- a/client/internal/oauth/auth0.go +++ b/client/internal/oauth/auth0.go @@ -12,7 +12,10 @@ import ( ) // auth0GrantType grant type for device flow on Auth0 -const auth0GrantType = "urn:ietf:params:oauth:grant-type:device_code" +const ( + auth0GrantType = "urn:ietf:params:oauth:grant-type:device_code" + auth0RefreshGrant = "refresh_token" +) // Auth0 client type Auth0 struct { @@ -34,9 +37,10 @@ type RequestDeviceCodePayload struct { // TokenRequestPayload used for requesting the auth0 token type TokenRequestPayload struct { - GrantType string `json:"grant_type"` - DeviceCode string `json:"device_code"` - ClientID string `json:"client_id"` + GrantType string `json:"grant_type"` + DeviceCode string `json:"device_code,omitempty"` + ClientID string `json:"client_id"` + RefreshToken string `json:"refresh_token,omitempty"` } // TokenRequestResponse used for parsing Auth0 token's response @@ -48,7 +52,7 @@ type TokenRequestResponse struct { // Claims used when validating the access token type Claims struct { - Audiance string `json:"aud"` + Audience string `json:"aud"` } // NewAuth0DeviceFlow returns an Auth0 OAuth client @@ -127,30 +131,13 @@ func (a *Auth0) WaitToken(ctx context.Context, info DeviceAuthInfo) (TokenInfo, DeviceCode: info.DeviceCode, ClientID: a.ClientID, } - p, err := json.Marshal(tokenReqPayload) + + body, statusCode, err := requestToken(a.HTTPClient, url, tokenReqPayload) if err != nil { - return TokenInfo{}, fmt.Errorf("parsing token payload failed with error: %v", err) - } - payload := strings.NewReader(string(p)) - req, err := http.NewRequest("POST", url, payload) - if err != nil { - return TokenInfo{}, fmt.Errorf("creating wait token request failed with error: %v", err) + return TokenInfo{}, fmt.Errorf("wait for token: %v", err) } - req.Header.Add("content-type", "application/json") - - res, err := a.HTTPClient.Do(req) - if err != nil { - return TokenInfo{}, fmt.Errorf("doing wiat request failed with error: %v", err) - } - - defer res.Body.Close() - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return TokenInfo{}, fmt.Errorf("reading toekn body failed with error: %v", err) - } - - if res.StatusCode > 499 { + if statusCode > 499 { return TokenInfo{}, fmt.Errorf("wait token code returned error: %s", string(body)) } @@ -184,6 +171,71 @@ func (a *Auth0) WaitToken(ctx context.Context, info DeviceAuthInfo) (TokenInfo, } } +// RotateAccessToken requests a new token using an existing refresh token +func (a *Auth0) RotateAccessToken(ctx context.Context, refreshToken string) (TokenInfo, error) { + url := "https://" + a.Domain + "/oauth/token" + tokenReqPayload := TokenRequestPayload{ + GrantType: auth0RefreshGrant, + ClientID: a.ClientID, + RefreshToken: refreshToken, + } + + body, statusCode, err := requestToken(a.HTTPClient, url, tokenReqPayload) + if err != nil { + return TokenInfo{}, fmt.Errorf("rotate access token: %v", err) + } + + if statusCode != 200 { + return TokenInfo{}, fmt.Errorf("rotating token returned error: %s", string(body)) + } + + tokenResponse := TokenRequestResponse{} + err = json.Unmarshal(body, &tokenResponse) + if err != nil { + return TokenInfo{}, fmt.Errorf("parsing token response failed with error: %v", err) + } + + err = isValidAccessToken(tokenResponse.AccessToken, a.Audience) + if err != nil { + return TokenInfo{}, fmt.Errorf("validate access token failed with error: %v", err) + } + + tokenInfo := TokenInfo{ + AccessToken: tokenResponse.AccessToken, + TokenType: tokenResponse.TokenType, + RefreshToken: tokenResponse.RefreshToken, + IDToken: tokenResponse.IDToken, + ExpiresIn: tokenResponse.ExpiresIn, + } + return tokenInfo, err +} + +func requestToken(client HTTPClient, url string, tokenReqPayload TokenRequestPayload) ([]byte, int, error) { + p, err := json.Marshal(tokenReqPayload) + if err != nil { + return nil, 0, fmt.Errorf("parsing token payload failed with error: %v", err) + } + payload := strings.NewReader(string(p)) + req, err := http.NewRequest("POST", url, payload) + if err != nil { + return nil, 0, fmt.Errorf("creating token request failed with error: %v", err) + } + + req.Header.Add("content-type", "application/json") + + res, err := client.Do(req) + if err != nil { + return nil, 0, fmt.Errorf("doing token request failed with error: %v", err) + } + + defer res.Body.Close() + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return nil, 0, fmt.Errorf("reading token body failed with error: %v", err) + } + return body, res.StatusCode, nil +} + // isValidAccessToken is a simple validation of the access token func isValidAccessToken(token string, audience string) error { if token == "" { @@ -202,7 +254,7 @@ func isValidAccessToken(token string, audience string) error { return err } - if claims.Audiance != audience { + if claims.Audience != audience { return fmt.Errorf("invalid audience") } diff --git a/client/internal/oauth/auth0_test.go b/client/internal/oauth/auth0_test.go index 2246b166e..6fac44fa3 100644 --- a/client/internal/oauth/auth0_test.go +++ b/client/internal/oauth/auth0_test.go @@ -152,7 +152,6 @@ func TestAuth0_WaitToken(t *testing.T) { Interval: 1, } - // payload,timeout,error 500,error conn,error response, invalid token,good req tokenReqPayload := TokenRequestPayload{ GrantType: auth0GrantType, DeviceCode: defaultInfo.DeviceCode, @@ -294,3 +293,123 @@ func TestAuth0_WaitToken(t *testing.T) { }) } } + +func TestAuth0_RotateAccessToken(t *testing.T) { + type test struct { + name string + inputResBody string + inputReqCode int + inputReqError error + inputMaxReqs int + inputInfo DeviceAuthInfo + inputAudience string + testingErrFunc require.ErrorAssertionFunc + expectedErrorMSG string + testingFunc require.ComparisonAssertionFunc + expectedOut TokenInfo + expectedMSG string + expectPayload TokenRequestPayload + } + + defaultInfo := DeviceAuthInfo{ + DeviceCode: "test", + ExpiresIn: 10, + Interval: 1, + } + + tokenReqPayload := TokenRequestPayload{ + GrantType: auth0RefreshGrant, + ClientID: "test", + RefreshToken: "refresh_test", + } + + testCase1 := test{ + name: "Payload Is Valid", + inputInfo: defaultInfo, + inputReqCode: 200, + testingErrFunc: require.Error, + testingFunc: require.EqualValues, + expectPayload: tokenReqPayload, + } + + testCase2 := test{ + name: "Exit On Network Error", + inputInfo: defaultInfo, + expectPayload: tokenReqPayload, + inputReqError: fmt.Errorf("error"), + testingErrFunc: require.Error, + expectedErrorMSG: "should return error", + testingFunc: require.EqualValues, + } + + testCase3 := test{ + name: "Exit On Non 200 Status Code", + inputInfo: defaultInfo, + inputReqCode: 401, + expectPayload: tokenReqPayload, + testingErrFunc: require.Error, + expectedErrorMSG: "should return error", + testingFunc: require.EqualValues, + } + + audience := "test" + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{"aud": audience}) + var hmacSampleSecret []byte + tokenString, _ := token.SignedString(hmacSampleSecret) + + testCase4 := test{ + name: "Exit On Invalid Audience", + inputInfo: defaultInfo, + inputResBody: fmt.Sprintf("{\"access_token\":\"%s\"}", tokenString), + inputReqCode: 200, + inputAudience: "super test", + testingErrFunc: require.Error, + testingFunc: require.EqualValues, + expectPayload: tokenReqPayload, + } + + testCase5 := test{ + name: "Received Token Info", + inputInfo: defaultInfo, + inputResBody: fmt.Sprintf("{\"access_token\":\"%s\"}", tokenString), + inputReqCode: 200, + inputAudience: audience, + testingErrFunc: require.NoError, + testingFunc: require.EqualValues, + expectPayload: tokenReqPayload, + expectedOut: TokenInfo{AccessToken: tokenString}, + } + + for _, testCase := range []test{testCase1, testCase2, testCase3, testCase4, testCase5} { + t.Run(testCase.name, func(t *testing.T) { + + httpClient := mockHTTPClient{ + resBody: testCase.inputResBody, + code: testCase.inputReqCode, + err: testCase.inputReqError, + MaxReqs: testCase.inputMaxReqs, + } + + auth0 := Auth0{ + Audience: testCase.inputAudience, + ClientID: testCase.expectPayload.ClientID, + Domain: "test.auth0.com", + HTTPClient: &httpClient, + } + + tokenInfo, err := auth0.RotateAccessToken(context.TODO(), testCase.expectPayload.RefreshToken) + testCase.testingErrFunc(t, err, testCase.expectedErrorMSG) + + var payload []byte + var emptyPayload TokenRequestPayload + if testCase.expectPayload != emptyPayload { + payload, _ = json.Marshal(testCase.expectPayload) + } + require.EqualValues(t, string(payload), httpClient.reqBody, "payload should match") + + testCase.testingFunc(t, testCase.expectedOut, tokenInfo, testCase.expectedMSG) + + }) + } +} diff --git a/client/internal/oauth/oauth.go b/client/internal/oauth/oauth.go index 07e6005f7..5fe9a9a96 100644 --- a/client/internal/oauth/oauth.go +++ b/client/internal/oauth/oauth.go @@ -32,5 +32,6 @@ type TokenInfo struct { // Client is a OAuth client interface for various idp providers type Client interface { RequestDeviceCode(ctx context.Context) (DeviceAuthInfo, error) + RotateAccessToken(ctx context.Context, refreshToken string) (TokenInfo, error) WaitToken(ctx context.Context, info DeviceAuthInfo) (TokenInfo, error) } diff --git a/client/internal/oauth/secret.go b/client/internal/oauth/secret.go new file mode 100644 index 000000000..c4a7a5cdb --- /dev/null +++ b/client/internal/oauth/secret.go @@ -0,0 +1,66 @@ +package oauth + +import ( + "fmt" + "github.com/99designs/keyring" +) + +// ServiceName default service name for saving the secret +const ServiceName = "Wiretrustee" + +func newSecretAPI() (keyring.Keyring, error) { + return keyring.Open(keyring.Config{ + ServiceName: ServiceName, + //KeychainName: ServiceName, + }) +} + +// SetSecret stores the secret in the system's available backend +func SetSecret(key string, value string) error { + storeAPI, err := newSecretAPI() + if err != nil { + return fmt.Errorf("failed to create secret API for setting a secret, error: %v", err) + } + + item := keyring.Item{ + Key: key, + Data: []byte(value), + } + + err = storeAPI.Set(item) + if err != nil { + return fmt.Errorf("failed to set the secret, error: %v", err) + } + + return nil +} + +// GetSecret retrieves a secret from the system's available backend +func GetSecret(key string) (string, error) { + storeAPI, err := newSecretAPI() + if err != nil { + return "", fmt.Errorf("failed to create secret API for getting a secret, error: %v", err) + } + + item, err := storeAPI.Get(key) + if err != nil { + return "", fmt.Errorf("failed to get secret, error: %v", err) + } + + return string(item.Data), nil +} + +// DeleteSecret deletes a secret from the system's available backend +func DeleteSecret(key string) error { + storeAPI, err := newSecretAPI() + if err != nil { + return fmt.Errorf("failed to create secret API for deleting a secret, error: %v", err) + } + + err = storeAPI.Remove(key) + if err != nil { + return fmt.Errorf("failed to delete secret, error: %v", err) + } + + return nil +} diff --git a/client/internal/oauth/secret_test.go b/client/internal/oauth/secret_test.go new file mode 100644 index 000000000..fedbee13c --- /dev/null +++ b/client/internal/oauth/secret_test.go @@ -0,0 +1,27 @@ +package oauth + +import ( + "github.com/stretchr/testify/require" + "os" + "testing" +) + +func TestSecret(t *testing.T) { + // this test is not ready to run as part of our ci/cd + // todo fix testing + if os.Getenv("CI") == "true" { + t.Skip("skipping testing in github actions") + } + + key := "testing" + value := "1234" + err := SetSecret(key, value) + require.NoError(t, err, "should set secret") + + v, err := GetSecret(key) + require.NoError(t, err, "should retrieve secret") + require.Equal(t, value, v, "values should match") + + err = DeleteSecret(key) + require.NoError(t, err, "should delete secret") +} diff --git a/go.mod b/go.mod index 4d3210f78..303753083 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/vishvananda/netlink v1.1.0 golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 - golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e + golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a golang.zx2c4.com/wireguard v0.0.0-20211209221555-9c9e7e272434 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20211215182854-7a385b3431de golang.zx2c4.com/wireguard/windows v0.5.1 @@ -28,6 +28,7 @@ require ( ) require ( + github.com/99designs/keyring v1.2.1 github.com/getlantern/systray v1.2.1 github.com/magiconair/properties v1.8.5 github.com/rs/xid v1.3.0 @@ -36,8 +37,11 @@ require ( ) require ( + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/BurntSushi/toml v0.4.1 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect github.com/getlantern/errors v0.0.0-20190325191628-abdb3e3e36f7 // indirect @@ -46,12 +50,15 @@ require ( github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 // indirect github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f // indirect github.com/go-stack/stack v1.8.0 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/google/go-cmp v0.5.6 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect github.com/mdlayher/genetlink v1.1.0 // indirect github.com/mdlayher/netlink v1.4.2 // indirect github.com/mdlayher/socket v0.0.0-20211102153432-57e3fa563ecb // indirect + github.com/mtibben/percent v0.2.1 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect github.com/pion/dtls/v2 v2.1.2 // indirect @@ -66,6 +73,7 @@ require ( github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect golang.org/x/mod v0.5.1 // indirect golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect golang.org/x/tools v0.1.8 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect diff --git a/go.sum b/go.sum index 5a007a7f8..d3e02498c 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,10 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= +github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -94,9 +98,13 @@ github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWH github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= +github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= 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= @@ -145,6 +153,8 @@ github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEK github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -228,6 +238,8 @@ github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0 github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= 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= @@ -293,7 +305,6 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -355,7 +366,11 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -437,6 +452,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= 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.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= +github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -696,6 +713,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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-20210819135213-f52c844e1c1c/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-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -708,9 +726,11 @@ golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBc 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-20211214234402-4825e8c3871d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a h1:ppl5mZgokTT8uPkmYOyEUmPTr3ypaKkg5eFOGrAmxxE= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -951,8 +971,9 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=