Compare commits

...

348 Commits

Author SHA1 Message Date
Mayur Waghmode
b43161531d Added ppc64le support (#799)
Signed-off-by: mayurwaghmode <waghmodemayur17@gmail.com>

Signed-off-by: mayurwaghmode <waghmodemayur17@gmail.com>
2022-09-12 18:49:03 +09:00
renovate[bot]
43c5283b3b fix(deps): update golang.org/x/net digest to bea034e (#797)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-09 20:37:10 +00:00
renovate[bot]
0a9a6a81f3 fix(deps): update module github.com/google/go-cmp to v0.5.9 (#795)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-09 08:38:06 +00:00
renovate[bot]
ec070a46f3 fix(deps): update golang.org/x/oauth2 digest to f213421 (#796)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-09 05:51:00 +00:00
renovate[bot]
0632078b7d fix(deps): update golang.org/x/sync digest to f12130a (#794)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-08 01:56:15 +00:00
renovate[bot]
44d0740937 fix(deps): update golang.org/x/net digest to 1e95f45 (#793)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-07 21:48:21 +00:00
renovate[bot]
523d07e83b fix(deps): update golang.org/x/net digest to f3363e0 (#792)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-09-06 21:30:45 +00:00
renovate[bot]
ffcb64ba74 fix(deps): update module github.com/chromedp/chromedp to v0.8.5 (#789)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-27 12:48:37 +00:00
renovate[bot]
a684112dd5 fix(deps): update golang.org/x/net digest to 83b083e (#788)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-26 19:52:41 +00:00
renovate[bot]
017b1b9fba fix(deps): update golang.org/x/oauth2 digest to 0ebed06 (#784)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-23 11:00:44 +00:00
renovate[bot]
5290ca9474 fix(deps): update golang.org/x/net digest to b0a4917 (#785)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-23 05:01:06 +00:00
renovate[bot]
542b454d1c fix(deps): update golang.org/x/sync digest to 7fc1605 (#783)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-19 06:06:49 +00:00
renovate[bot]
ba1beb0b10 fix(deps): update kubernetes packages to v0.24.4 (#782)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-18 09:31:51 +00:00
renovate[bot]
8a2837d0ff fix(deps): update module github.com/chromedp/chromedp to v0.8.4 (#779)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-14 10:38:20 +00:00
renovate[bot]
a04131280e fix(deps): update golang.org/x/net digest to 3211cb9 (#778)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-12 21:57:19 +00:00
renovate[bot]
ccaf76f370 fix(deps): update golang.org/x/net digest to 13a9a73 (#777)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-11 21:54:48 +00:00
renovate[bot]
7537256308 fix(deps): update golang.org/x/net digest to 07c6da5 (#776)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-09 22:44:49 +00:00
renovate[bot]
cd68981c75 fix(deps): update golang.org/x/net digest to f428fae (#775)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-09 05:54:24 +00:00
renovate[bot]
e3934f5e3b fix(deps): update golang.org/x/oauth2 digest to 8227340 (#774)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-08 22:08:06 +00:00
renovate[bot]
1bd1fc9079 chore(deps): update dependency golangci/golangci-lint to v1.48.0 (#772) 2022-08-06 11:23:20 +09:00
renovate[bot]
63c9018faa fix(deps): update golang.org/x/net digest to a33c5aa (#773)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-05 04:48:31 +00:00
renovate[bot]
d6f30063bd fix(deps): update golang.org/x/net digest to 0bcc04d (#770)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-03 02:29:18 +00:00
renovate[bot]
572eaed609 chore(deps): update dependency golangci/golangci-lint to v1.47.3 (#768)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-02 01:57:48 +00:00
renovate[bot]
2757feda35 chore(deps): update dependency golang-version to v1.18.5 (#767)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-01 21:35:30 +00:00
Marko Mikulicic
7bcc15827a Use cgo when cross-compiling macos arm64 (#763) 2022-07-29 12:56:36 +09:00
renovate[bot]
0b53136d12 fix(deps): update golang.org/x/net digest to c7608f3 (#766)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-29 01:05:14 +00:00
renovate[bot]
4642e559d4 fix(deps): update golang.org/x/net digest to 1f511ac (#765)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-28 17:38:34 +00:00
renovate[bot]
de66e882b3 fix(deps): update golang.org/x/net digest to 41545e8 (#764)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-28 05:53:33 +00:00
renovate[bot]
4055aeaaa4 fix(deps): update golang.org/x/net digest to 0699458 (#761)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-27 04:04:47 +00:00
renovate[bot]
51d38d6937 fix(deps): update module github.com/chromedp/chromedp to v0.8.3 (#760)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-26 03:00:46 +00:00
renovate[bot]
88729027f1 fix(deps): update golang.org/x/net digest to 46097bf (#759)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-26 00:51:33 +00:00
renovate[bot]
96354ebfb9 fix(deps): update golang.org/x/term digest to a9ba230 (#758)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-23 02:08:15 +00:00
renovate[bot]
c01bbe3110 fix(deps): update golang.org/x/sync digest to 886fb93 (#730)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-22 23:52:26 +00:00
renovate[bot]
75c24e8a25 fix(deps): update golang.org/x/oauth2 digest to 128564f (#756)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-22 21:33:03 +00:00
renovate[bot]
7b824e6e20 fix(deps): update golang.org/x/net digest to a158d28 (#755)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-22 19:40:46 +00:00
renovate[bot]
fda2fe3775 chore(deps): update dependency golangci/golangci-lint to v1.47.2 (#752)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-21 16:12:08 +00:00
renovate[bot]
a13e6ecf5d chore(deps): update dependency golangci/golangci-lint to v1.47.1 (#750)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-19 17:09:16 +00:00
renovate[bot]
cbc4a5a4c6 fix(deps): update golang.org/x/oauth2 digest to c8730f7 (#749)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 22:44:53 +00:00
renovate[bot]
696b630950 fix(deps): update kubernetes packages to v0.24.3 (#675)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 21:09:11 +00:00
renovate[bot]
55af8ab1d1 chore(deps): update dependency golangci/golangci-lint to v1.47.0 (#748)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 18:41:37 +00:00
renovate[bot]
7b1597de54 fix(deps): update golang.org/x/term digest to 065cf7b (#721)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 15:53:33 +00:00
renovate[bot]
6510482278 fix(deps): update golang.org/x/net digest to 1185a90 (#670)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 12:22:08 +00:00
renovate[bot]
da6d8f9467 chore(deps): update docker/setup-buildx-action action to v2 (#746) 2022-07-18 16:11:53 +09:00
renovate[bot]
37c602fc73 chore(deps): update docker/setup-qemu-action action to v2 (#747) 2022-07-18 16:06:21 +09:00
renovate[bot]
78808eed97 chore(deps): update docker/metadata-action action to v4 (#745) 2022-07-18 15:57:23 +09:00
renovate[bot]
66592b5831 fix(deps): update module github.com/alexflint/go-filemutex to v1.2.0 (#712)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 14:17:34 +09:00
renovate[bot]
cc323d2fae chore(deps): update docker/build-push-action action to v3 (#743)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 14:17:16 +09:00
renovate[bot]
1829e2caaa chore(deps): update docker/login-action action to v2 (#744)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 14:17:06 +09:00
renovate[bot]
cc30f40e58 fix(deps): update module k8s.io/klog/v2 to v2.70.1 (#742)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 13:58:12 +09:00
renovate[bot]
6037d5706a fix(deps): update golang.org/x/oauth2 digest to 2104d58 (#693)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 13:57:41 +09:00
renovate[bot]
d67e2663c9 fix(deps): update module github.com/spf13/cobra to v1.5.0 (#741)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 13:57:19 +09:00
renovate[bot]
1fe770939a fix(deps): update module github.com/golang-jwt/jwt/v4 to v4.4.2 (#715)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-18 13:05:24 +09:00
Hidetake Iwata
5ba7f551cf Refactor tests (#740)
* refactor: use t.Setenv()

* refactor: use t.TempDir()

* refactor: use t.Cleanup()
2022-07-16 22:08:55 +09:00
renovate[bot]
5ea4d3648a chore(deps): update dependency golang-version to v1.18.4 (#720)
* chore(deps): update dependency golang-version to v1.18.4

* Bump github.com/json-iterator/go to v1.1.12

https://github.com/json-iterator/go/releases/tag/v1.1.12

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Hidetake Iwata <int128@gmail.com>
2022-07-16 21:05:23 +09:00
renovate[bot]
41f31cd056 fix(deps): update module github.com/coreos/go-oidc/v3 to v3.2.0 (#738)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-16 20:41:08 +09:00
Hidetake Iwata
7152bccd21 refactor: migrate to Testify Mock (#739) 2022-07-16 16:55:51 +09:00
renovate[bot]
e27b5723da fix(deps): update module github.com/chromedp/chromedp to v0.8.2 (#726)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-07-16 13:10:42 +09:00
renovate[bot]
5499a35916 chore(deps): update dependency golangci/golangci-lint to v1.46.2 (#735)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-07-16 13:10:02 +09:00
Hidetake Iwata
86341c82fb Use int128/go-actions/setup (#731) 2022-05-21 16:40:56 +09:00
renovate[bot]
a028255661 fix(deps): update module github.com/google/go-cmp to v0.5.8 (#724) 2022-05-21 16:27:07 +09:00
Hidetake Iwata
3679e5e436 Update runner of system-test to ubuntu-latest (#509) 2022-05-21 14:28:30 +09:00
Hidetake Iwata
ed723fed2a Fix authentication error in system-test (#729)
* Show log of kube-apiserver

* Fix kubeadmConfigPatches
2022-05-21 13:57:06 +09:00
renovate[bot]
98b1fb92f1 chore(deps): update actions/cache action to v3 (#710)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-07 17:28:16 +09:00
Hidetake Iwata
d28cecd756 Use int128/renovate-base (#725) 2022-05-07 17:27:04 +09:00
renovate[bot]
4ba848019a chore(deps): update rajatjindal/krew-release-bot action to v0.0.43 (#723)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-17 05:18:25 +00:00
renovate[bot]
03a1b10c3c chore(deps): update rajatjindal/krew-release-bot action to v0.0.42 (#716)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-29 11:03:58 +00:00
renovate[bot]
03322d0cad chore(deps): update dependency golangci/golangci-lint to v1.45.2 (#714)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-24 16:18:40 +00:00
renovate[bot]
58ee2725e9 chore(deps): update dependency golangci/golangci-lint to v1.45.1 (#713)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-24 11:23:43 +00:00
renovate[bot]
8572c8db95 fix(deps): update module github.com/chromedp/chromedp to v0.8.0 (#709)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-21 12:15:04 +00:00
renovate[bot]
ff6e770818 fix(deps): update module k8s.io/klog/v2 to v2.60.1 (#708)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-20 18:27:45 +00:00
renovate[bot]
1a58259fc0 chore(deps): update dependency golangci/golangci-lint to v1.45.0 (#707)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-18 19:59:14 +00:00
renovate[bot]
1c37d7a8b7 fix(deps): update module k8s.io/klog/v2 to v2.60.0 (#705)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-17 17:27:21 +00:00
renovate[bot]
4be2ac025a fix(deps): update module github.com/golang-jwt/jwt/v4 to v4.4.0 (#704)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-17 05:22:31 +00:00
renovate[bot]
adb57bdb36 fix(deps): update module k8s.io/klog/v2 to v2.50.2 (#703)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-17 02:35:59 +00:00
renovate[bot]
1166672b92 fix(deps): update module k8s.io/klog/v2 to v2.50.1 (#702)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-16 17:29:05 +00:00
renovate[bot]
c08bedfcbd chore(deps): update dependency golang to v1.18 (#700)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-16 03:50:28 +00:00
renovate[bot]
72237142c8 fix(deps): update module k8s.io/klog/v2 to v2.50.0 (#699)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-16 01:32:13 +00:00
renovate[bot]
aa727c424a chore(deps): update golangci/golangci-lint-action action to v3 (#695)
* chore(deps): update golangci/golangci-lint-action action to v3

* Update go.yaml

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Hidetake Iwata <int128@gmail.com>
2022-03-12 16:36:09 +09:00
renovate[bot]
92cb984154 chore(deps): update actions/setup-go action to v3 (#696)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-12 16:29:56 +09:00
renovate[bot]
86fc4df483 fix(deps): update module github.com/spf13/cobra to v1.4.0 (#698)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-11 17:42:17 +00:00
renovate[bot]
c931677964 chore(deps): update actions/checkout action to v3 (#697)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-04 19:12:00 +09:00
renovate[bot]
8b0a087e14 fix(deps): update module github.com/chromedp/chromedp to v0.7.8 (#691)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-19 05:01:48 +00:00
renovate[bot]
713696ce12 chore(deps): update dependency golangci/golangci-lint to v1.44.2 (#690)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-18 00:42:56 +00:00
renovate[bot]
0f281e8bb6 chore(deps): update dependency golangci/golangci-lint to v1.44.1 (#689)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-17 15:00:53 +00:00
renovate[bot]
64c0f56480 fix(deps): update module github.com/golang-jwt/jwt/v4 to v4.3.0 (#687)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-10 08:28:01 +00:00
renovate[bot]
71076214ce fix(deps): update module github.com/chromedp/chromedp to v0.7.7 (#686)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-02-04 11:39:14 +00:00
renovate[bot]
46b5961742 chore(deps): update dependency golangci/golangci-lint to v1.44.0 (#684)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-25 13:16:01 +00:00
renovate[bot]
2675df15d4 fix(deps): update module github.com/google/go-cmp to v0.5.7 (#682)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-01-22 15:25:59 +00:00
Hidetake Iwata
b17843ce7b Update README.md 2022-01-22 22:03:43 +09:00
Hidetake Iwata
775841a72b Remove deprecation of standalone mode (#680)
* Remove deprecation of standalone mode

* Update standalone-mode.md
2022-01-08 17:48:00 +09:00
renovate[bot]
564177cd18 fix(deps): update module k8s.io/klog/v2 to v2.40.1 (#679)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-19 04:11:07 +00:00
renovate[bot]
3f5514573d fix(deps): update module k8s.io/klog/v2 to v2.40.0 (#678)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-17 16:41:23 +00:00
renovate[bot]
a70c0e21b9 fix(deps): update module github.com/spf13/cobra to v1.3.0 (#677)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-14 23:53:29 +00:00
renovate[bot]
6a8dd65a1a fix(deps): update module github.com/golang-jwt/jwt/v4 to v4.2.0 (#672)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-12-03 20:38:18 +00:00
renovate[bot]
6b5947b174 chore(deps): update dependency golangci/golangci-lint to v1.43.0 (#669)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-28 07:10:52 +00:00
Hidetake Iwata
6ff75291d7 Use Renovate config in int128/go-actions 2021-11-28 15:44:45 +09:00
Hidetake Iwata
3cb6988b8b Refactor workflows (#668)
* Refactor workflows

* Fix runs-on

* Fix Dockerfile
2021-11-28 15:10:23 +09:00
renovate[bot]
2a14902541 fix(deps): update module github.com/chromedp/chromedp to v0.7.6 (#667)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-27 04:25:47 +00:00
renovate[bot]
78d9d1f913 fix(deps): update golang.org/x/net commit hash to d83791d (#666)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-23 23:03:26 +00:00
renovate[bot]
9f39c00cc8 fix(deps): update module k8s.io/client-go to v0.22.4 (#663)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 21:14:24 +00:00
renovate[bot]
6c767e8545 fix(deps): update golang.org/x/net commit hash to 6a13c67 (#664)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 18:27:01 +00:00
renovate[bot]
ccb00b7b58 fix(deps): update module k8s.io/apimachinery to v0.22.4 (#662)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-18 04:48:38 +00:00
renovate[bot]
cf8b89d6ae fix(deps): update golang.org/x/oauth2 commit hash to d3ed0bb (#661)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-17 03:58:13 +00:00
renovate[bot]
86a8721cac fix(deps): update golang.org/x/net commit hash to 47ca1ff (#660)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-11-17 01:37:59 +00:00
renovate[bot]
5f2ae5497f Merge pull request #657 from int128/renovate/k8s.io-client-go-0.x
fix(deps): update module k8s.io/client-go to v0.22.3
2021-10-28 10:29:01 +00:00
Renovate Bot
e89de7de0f fix(deps): update module k8s.io/client-go to v0.22.3 2021-10-28 10:28:26 +00:00
renovate[bot]
fd5580861f Merge pull request #656 from int128/renovate/k8s.io-apimachinery-0.x
fix(deps): update module k8s.io/apimachinery to v0.22.3
2021-10-28 10:26:21 +00:00
Renovate Bot
4382333ac9 fix(deps): update module k8s.io/apimachinery to v0.22.3 2021-10-28 10:26:17 +00:00
renovate[bot]
821265c912 fix(deps): update module k8s.io/klog/v2 to v2.30.0 (#654)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-22 15:17:05 +00:00
renovate[bot]
f5f0c7eadd fix(deps): update golang.org/x/net commit hash to d418f37 (#653)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-20 09:47:35 +00:00
Hidetake Iwata
b1af578679 Fix docker push error 2021-10-20 12:20:53 +09:00
renovate[bot]
5737f96665 fix(deps): update golang.org/x/net commit hash to c6ed85c (#652)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-20 02:08:53 +00:00
renovate[bot]
07129f8c77 fix(deps): update golang.org/x/net commit hash to 4f30a5c (#651)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-15 22:57:15 +00:00
renovate[bot]
931d4f3a89 fix(deps): update golang.org/x/net commit hash to fd004c5 (#650)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-15 01:31:08 +00:00
renovate[bot]
f76e186d72 fix(deps): update golang.org/x/net commit hash to 2b766c0 (#649)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-14 20:01:03 +00:00
renovate[bot]
3e44d7655f fix(deps): update golang.org/x/net commit hash to e13a265 (#648)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-13 20:13:11 +00:00
renovate[bot]
14f57e7232 fix(deps): update golang.org/x/net commit hash to ee2e9a0 (#647)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-13 16:48:16 +00:00
renovate[bot]
af8ae6f2f6 fix(deps): update module github.com/int128/oauth2cli to v1.14.0 (#646)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-12 02:40:53 +00:00
renovate[bot]
83a4524487 fix(deps): update golang.org/x/net commit hash to caeb26a (#645)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-11 18:40:20 +00:00
renovate[bot]
aeda430a1f fix(deps): update golang.org/x/net commit hash to 3b03d30 (#644)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-08 21:53:21 +00:00
renovate[bot]
10fdb63be3 fix(deps): update golang.org/x/net commit hash to 59d4e92 (#643)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-07 17:24:54 +00:00
renovate[bot]
fb439187d3 fix(deps): update golang.org/x/net commit hash to 62292e8 (#642)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-06 21:05:48 +00:00
renovate[bot]
73359e62db fix(deps): update golang.org/x/net commit hash to d2e5035 (#641)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-06 00:05:56 +00:00
renovate[bot]
c38b41cf85 fix(deps): update golang.org/x/oauth2 commit hash to 6b3c2da (#640)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-05 19:59:18 +00:00
renovate[bot]
e149f6443f fix(deps): update module github.com/golang-jwt/jwt/v4 to v4.1.0 (#636)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-05 13:35:11 +00:00
renovate[bot]
3c0bca7dee fix(deps): update golang.org/x/term commit hash to 03fcf44 (#637)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-05 11:33:50 +00:00
renovate[bot]
43497466f9 fix(deps): update golang.org/x/net commit hash to d4b1ae0 (#635)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-10-05 09:25:27 +00:00
Hidetake Iwata
0075043866 Use int128/docker-build-cache-config-action (#639) 2021-10-05 16:33:30 +09:00
renovate[bot]
b160aea35e fix(deps): update golang.org/x/net commit hash to 3c21e5b (#634)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-17 19:13:50 +00:00
renovate[bot]
52311525fe fix(deps): update module k8s.io/client-go to v0.22.2 (#632)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-17 17:31:25 +00:00
renovate[bot]
ab923d0d49 fix(deps): update module k8s.io/apimachinery to v0.22.2 (#631)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-17 16:05:50 +00:00
renovate[bot]
97908c775f fix(deps): update module github.com/coreos/go-oidc/v3 to v3.1.0 (#630)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-17 10:16:07 +00:00
renovate[bot]
c6662f32fb fix(deps): update golang.org/x/term commit hash to 140adaa (#629)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-17 00:08:20 +00:00
renovate[bot]
a07a1eb7e8 fix(deps): update golang.org/x/net commit hash to 12bc252 (#626)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-16 04:35:33 +00:00
renovate[bot]
f5f73df697 fix(deps): update github.com/pkg/browser commit hash to 681adbf (#625)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-11 10:11:49 +00:00
renovate[bot]
ae3a001dd2 fix(deps): update golang.org/x/net commit hash to a5e0955 (#624)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-08 21:19:10 +00:00
renovate[bot]
eb8f211e67 fix(deps): update golang.org/x/net commit hash to ff17edf (#623)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-08 00:40:24 +00:00
Hidetake Iwata
237e53313d Add flag to set custom browser command (#622)
* Add flag to set custom browser command

* Use --browser-command in system_test

* Add --browser-command= to setup message
2021-09-05 11:35:03 +09:00
renovate[bot]
8cce70c302 fix(deps): update github.com/pkg/browser commit hash to 6d279e1 (#621)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-04 02:44:53 +00:00
renovate[bot]
751b62b418 fix(deps): update golang.org/x/net commit hash to ad29c8a (#620)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-03 19:31:19 +00:00
renovate[bot]
1aeb6b0c0d fix(deps): update golang.org/x/net commit hash to 8d99171 (#619)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-02 19:08:13 +00:00
renovate[bot]
58d354f6bc fix(deps): update module k8s.io/klog/v2 to v2.20.0 (#618)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-02 07:32:31 +00:00
Hidetake Iwata
077d9ab90c Use docker/metadata-action@v3 (#616) 2021-08-28 22:10:41 +09:00
Joel Kaasinen
50bc986085 update README.md (#615) 2021-08-28 08:03:20 +09:00
renovate[bot]
75698aee0c fix(deps): update golang.org/x/net commit hash to e898025 (#613)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-25 19:59:14 +00:00
renovate[bot]
a17137b4e9 fix(deps): update module k8s.io/client-go to v0.22.1 (#612)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-20 00:16:31 +00:00
renovate[bot]
395a36eb53 fix(deps): update module k8s.io/apimachinery to v0.22.1 (#611)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-19 22:44:00 +00:00
renovate[bot]
b86118034f fix(deps): update golang.org/x/oauth2 commit hash to 2bc19b1 (#610)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-19 21:04:49 +00:00
renovate[bot]
a4b63da790 fix(deps): update golang.org/x/oauth2 commit hash to 7df4dd6 (#609)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-18 02:05:49 +00:00
renovate[bot]
b0d9ff907b chore(deps): update golang docker tag to v1.17 (#608)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-17 04:36:40 +00:00
renovate[bot]
c8d7fa5009 fix(deps): update golang.org/x/oauth2 commit hash to faf39c7 (#606)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-13 20:13:09 +00:00
renovate[bot]
99fc66e205 fix(deps): update golang.org/x/net commit hash to 60bc85c (#607)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-13 18:16:01 +00:00
Hidetake Iwata
33275b0a30 Export BuildKit cache to GHCR (#605) 2021-08-09 22:53:48 +09:00
Hidetake Iwata
9a850d7072 Migrate to github.com/golang-jwt/jwt/v4 (#604) 2021-08-08 11:39:45 +09:00
renovate[bot]
e5981c49c8 chore(deps): update codecov/codecov-action action to v2 (#595) 2021-08-08 10:51:03 +09:00
renovate[bot]
226683c051 fix(deps): update golang.org/x/oauth2 commit hash to 6f1e639 (#602)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-05 20:23:53 +00:00
renovate[bot]
3d6cfe5054 fix(deps): update golang.org/x/net commit hash to aaa1db6 (#603)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-05 19:35:51 +00:00
renovate[bot]
8cba4b4647 fix(deps): update module k8s.io/client-go to v0.22.0 (#601)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-04 23:32:41 +00:00
renovate[bot]
f1b17d2fc1 fix(deps): update module k8s.io/apimachinery to v0.22.0 (#600)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-04 22:57:35 +00:00
Pedro Kiefer
a0cfde7198 refactor: add --oidc-use-pkce flag to force PKCE authorization flow (#599) 2021-08-04 06:38:26 +09:00
renovate[bot]
680dfeea68 fix(deps): update golang.org/x/net commit hash to c6fcb2d (#598)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-26 23:54:50 +00:00
renovate[bot]
103451e68d fix(deps): update golang.org/x/net commit hash to 853a461 (#594)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-16 21:48:03 +00:00
renovate[bot]
480c8305b1 fix(deps): update module k8s.io/client-go to v0.21.3 (#593)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-16 09:00:36 +00:00
renovate[bot]
e472a4b261 fix(deps): update module k8s.io/apimachinery to v0.21.3 (#592)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-16 07:51:53 +00:00
renovate[bot]
849bf27c09 fix(deps): update module k8s.io/klog/v2 to v2.10.0 (#591)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-15 11:13:45 +00:00
renovate[bot]
b5462d49ad fix(deps): update module github.com/chromedp/chromedp to v0.7.4 (#589)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-13 08:52:17 +00:00
renovate[bot]
08fdfa8a61 fix(deps): update github.com/pkg/browser commit hash to 7d21f8c (#588)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-06 15:47:15 +00:00
renovate[bot]
d10adc61cf fix(deps): update module github.com/spf13/cobra to v1.2.1 (#587)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-02 16:36:21 +00:00
renovate[bot]
9ecf09d7bc fix(deps): update module github.com/spf13/cobra to v1.2.0 (#586)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-07-01 19:22:49 +00:00
renovate[bot]
d92802565d chore(deps): update rajatjindal/krew-release-bot action to v0.0.40 (#583)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-28 21:25:12 +00:00
renovate[bot]
14c55a1312 fix(deps): update golang.org/x/oauth2 commit hash to a41e5a7 (#585)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-28 20:09:04 +00:00
renovate[bot]
aa912cf6d0 fix(deps): update golang.org/x/oauth2 commit hash to a8dc77f (#582)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-22 22:26:23 +00:00
renovate[bot]
7e15541455 fix(deps): update golang.org/x/oauth2 commit hash to bce0382 (#581)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-22 20:21:24 +00:00
renovate[bot]
eb205ebbe8 fix(deps): update golang.org/x/oauth2 commit hash to 14747e6 (#580)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-22 18:49:24 +00:00
renovate[bot]
dc5cc7e7ad fix(deps): update github.com/pkg/browser commit hash to c198bc9 (#579)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-21 11:06:17 +00:00
renovate[bot]
06fa24bcee fix(deps): update module k8s.io/client-go to v0.21.2 (#578)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-18 02:31:09 +00:00
renovate[bot]
e5469925f5 fix(deps): update module k8s.io/apimachinery to v0.21.2 (#577)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-18 01:14:34 +00:00
renovate[bot]
6dbd197e8c fix(deps): update golang.org/x/oauth2 commit hash to d040287 (#576)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-15 20:28:06 +00:00
renovate[bot]
0e10951907 fix(deps): update golang.org/x/term commit hash to 6886f2d (#575)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-15 18:15:51 +00:00
renovate[bot]
b23f036445 fix(deps): update golang.org/x/net commit hash to 04defd4 (#573)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-14 20:00:31 +00:00
renovate[bot]
63f08f2f7a fix(deps): update module github.com/golang/mock to v1.6.0 (#572)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-11 23:01:45 +00:00
renovate[bot]
2006d13375 fix(deps): update golang.org/x/net commit hash to 84b48f8 (#571)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-10 15:28:35 +00:00
renovate[bot]
fb4d9663d5 fix(deps): update golang.org/x/net commit hash to 52da8fb (#570)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-10 13:26:15 +00:00
Hidetake Iwata
82e96fba84 Explicitly set CGO_ENABLED on build (#569) 2021-06-07 13:04:39 +09:00
renovate[bot]
8a725104e1 fix(deps): update github.com/pkg/browser commit hash to a7b7a61 (#568)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-07 01:18:44 +00:00
renovate[bot]
96d6492825 fix(deps): update module github.com/chromedp/chromedp to v0.7.3 (#566)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-27 08:08:35 +00:00
renovate[bot]
f40dc4c409 fix(deps): update module k8s.io/klog/v2 to v2.9.0 (#565)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-26 13:11:29 +00:00
renovate[bot]
7b9bb9e479 fix(deps): update golang.org/x/net commit hash to abc4532 (#564)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-25 09:34:54 +00:00
renovate[bot]
f0cb7ec1eb fix(deps): update module github.com/google/go-cmp to v0.5.6 (#563)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-25 04:58:38 +00:00
renovate[bot]
973674300e fix(deps): update golang.org/x/net commit hash to fe42d45 (#560)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-21 21:42:14 +00:00
renovate[bot]
0479bf6c68 fix(deps): update module k8s.io/client-go to v0.21.1 (#557)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-19 12:46:40 +00:00
renovate[bot]
93f2c88644 fix(deps): update module k8s.io/apimachinery to v0.21.1 (#556)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-19 11:05:03 +00:00
Suraj Banakar(बानकर) | スラジ
966e612b14 Update README.md (#558) 2021-05-19 17:50:48 +09:00
renovate[bot]
7a4099ed65 fix(deps): update golang.org/x/net commit hash to 4163338 (#554)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-14 19:23:02 +00:00
renovate[bot]
62e3d07d18 fix(deps): update golang.org/x/oauth2 commit hash to f6687ab (#555)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-14 18:13:42 +00:00
renovate[bot]
92fe0f1c3f fix(deps): update golang.org/x/net commit hash to 81045d8 (#553)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-10 11:37:56 +00:00
renovate[bot]
0903aa5636 fix(deps): update golang.org/x/net commit hash to 16afe75 (#551)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-09 01:03:58 +00:00
renovate[bot]
3338116bfb fix(deps): update module github.com/chromedp/chromedp to v0.7.2 (#552)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-08 23:22:53 +00:00
Hidetake Iwata
d0364f0942 Fix "~" is not expanded on Windows (#550)
* Run tests on macOS and Windows

* Use filepath and client-go/util/homedir package
2021-05-04 11:12:10 +09:00
renovate[bot]
ea78452b52 fix(deps): update golang.org/x/term commit hash to a79de54 (#549)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-03 10:11:02 +00:00
renovate[bot]
2d52355a37 fix(deps): update golang.org/x/net commit hash to 7fd8e65 (#548)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-03 08:49:41 +00:00
renovate[bot]
98895d12e9 fix(deps): update module github.com/chromedp/chromedp to v0.7.1 (#544)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-02 03:06:10 +00:00
renovate[bot]
bfac26d6d6 fix(deps): update golang.org/x/term commit hash to c04ba85 (#547)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-02 01:52:59 +00:00
renovate[bot]
a784b7a60b fix(deps): update golang.org/x/oauth2 commit hash to 81ed05c (#545)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-02 01:00:41 +00:00
renovate[bot]
2702f9259e fix(deps): update golang.org/x/net commit hash to f8dd838 (#546)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-02 00:05:03 +00:00
renovate[bot]
edf1bd705b fix(deps): update golang.org/x/net commit hash to 5f58ad6 (#542)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-23 22:23:22 +00:00
renovate[bot]
d8ab06b0a4 fix(deps): update golang.org/x/term commit hash to f5beecf (#541)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-22 15:16:49 +00:00
renovate[bot]
e1bb47bad2 fix(deps): update golang.org/x/net commit hash to 4e50805 (#540)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-22 02:21:55 +00:00
renovate[bot]
8dce91cc2d fix(deps): update golang.org/x/term commit hash to b80969c (#539)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-22 00:12:49 +00:00
renovate[bot]
415a52bc68 fix(deps): update golang.org/x/net commit hash to 798c215 (#538)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-20 23:01:52 +00:00
renovate[bot]
d20ceb5262 fix(deps): update golang.org/x/net commit hash to d25e304 (#537)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-20 11:31:08 +00:00
Hidetake Iwata
4ca11f13ac Add .exe extension to Windows distribution (#534) 2021-04-17 14:50:58 +09:00
Peter Holko (Ping Identity)
0b6d34e1a2 Update setup.md (#532)
Adding Ping Identity section to the setup guide
2021-04-17 14:05:28 +09:00
renovate[bot]
79882f6e3a fix(deps): update module k8s.io/client-go to v0.21.0 (#529)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-16 14:56:09 +00:00
renovate[bot]
f66835b04e fix(deps): update module k8s.io/apimachinery to v0.21.0 (#528)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-16 11:07:26 +00:00
renovate[bot]
487bbe7c9c fix(deps): update golang.org/x/term commit hash to 72f3dc4 (#527)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-16 09:01:43 +00:00
renovate[bot]
30a961dbd1 fix(deps): update golang.org/x/oauth2 commit hash to 5e61552 (#531)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-16 04:48:12 +00:00
renovate[bot]
1460c8158f fix(deps): update golang.org/x/net commit hash to e915ea6 (#530)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-16 02:45:13 +00:00
renovate[bot]
33f62ff368 fix(deps): update golang.org/x/net commit hash to a5a99cb (#525)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-05 20:18:16 +00:00
renovate[bot]
9668d0f057 fix(deps): update golang.org/x/oauth2 commit hash to 2e8d934 (#526)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-04-02 18:25:01 +00:00
renovate[bot]
5532f16f42 fix(deps): update golang.org/x/net commit hash to cb1fcc7 (#524)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-31 09:06:10 +00:00
renovate[bot]
add68e27e5 fix(deps): update golang.org/x/oauth2 commit hash to 22b0ada (#520)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-31 02:08:50 +00:00
renovate[bot]
bddce9d830 fix(deps): update golang.org/x/net commit hash to e572328 (#523)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-31 00:24:08 +00:00
renovate[bot]
7c2b049e5d fix(deps): update golang.org/x/net commit hash to cd0ac97 (#521)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-30 21:50:37 +00:00
Hidetake Iwata
9e354b4fe5 Build image on pull request (#522) 2021-03-28 12:52:12 +09:00
renovate[bot]
835ad7ad55 fix(deps): update module github.com/chromedp/chromedp to v0.6.10 (#518)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-24 12:26:07 +00:00
renovate[bot]
1e0b070f57 fix(deps): update golang.org/x/net commit hash to 2c4c8ec (#519)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-24 10:57:43 +00:00
Hidetake Iwata
0ccccbcb36 Do not build image on pull request (#516) 2021-03-22 14:07:08 +09:00
Hidetake Iwata
02ad24e6fe Update README.md 2021-03-22 13:49:27 +09:00
Hidetake Iwata
c011fef38c Delete .circleci directory 2021-03-22 13:48:04 +09:00
Hidetake Iwata
822ea91d21 Delete dist directory 2021-03-22 13:47:04 +09:00
Hidetake Iwata
6322b6e1fb Fix krew release (#515)
* Fix .krew.yaml

time="2021-03-22T04:06:39Z" level=fatal msg="template: .krew.yaml:28:9: executing \".krew.yaml\" at <addURIAndSha \"https://github.com/int128/kubelogin/releases/download/{{ TagName }}/kubelogin_linux_amd64.zip\" .TagName>: error calling addURIAndSha: template: url:1: function \"TagName\" not defined"

* Fix indent error
2021-03-22 13:39:51 +09:00
renovate[bot]
fa0633f8c5 fix(deps): update module k8s.io/client-go to v0.20.5 (#508)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-22 13:02:02 +09:00
Hidetake Iwata
74c9404e69 Fix multi-platform images (#514) 2021-03-22 12:10:22 +09:00
Hidetake Iwata
037d26b01f Publish multi-platform image to GHCR (#513) 2021-03-22 10:53:50 +09:00
Hidetake Iwata
256ce07e1f Migrate to krew-release-bot (#512) 2021-03-22 09:31:33 +09:00
Hidetake Iwata
23e85f8689 Migrate release to GitHub Actions (#511) 2021-03-21 22:36:25 +09:00
renovate[bot]
eb9a4121fb fix(deps): update golang.org/x/net commit hash to d523dce (#504)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-21 11:10:44 +00:00
renovate[bot]
7e24925248 fix(deps): update module k8s.io/apimachinery to v0.20.5 (#507)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-21 09:52:28 +00:00
renovate[bot]
b4f0f7feef fix(deps): update module github.com/chromedp/chromedp to v0.6.9 (#510)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-21 05:30:37 +00:00
renovate[bot]
fdff33f3df fix(deps): update golang.org/x/term commit hash to de623e6 (#506)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-17 17:40:54 +00:00
renovate[bot]
64294b9fa0 fix(deps): update golang.org/x/net commit hash to 34ac3e1 (#503)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-15 20:08:27 +00:00
Hidetake Iwata
9dcfb3a42c Migrate go test to GitHub Actions (#502) 2021-03-15 22:20:16 +09:00
Hidetake Iwata
644a7b0120 Fix trigger of system-test workflow (#501) 2021-03-15 19:28:10 +09:00
Hidetake Iwata
5f07f72889 Update get-token flags (#500) 2021-03-15 19:27:35 +09:00
Hidetake Iwata
d8af534b0b Update to Go 1.16 in system-test (#499) 2021-03-15 19:11:32 +09:00
Hidetake Iwata
eb7ce56909 Expand homedir paths in get-token options (#498)
* Expand homedir paths in get-token options

* Replace go-homedir with Go 1.16 os.UserHomeDir()
2021-03-15 19:03:11 +09:00
Mattias Appelgren
97cc85d079 repository: Expand ~ in homedir (#489)
Fixes: https://github.com/int128/kubelogin/issues/488
2021-03-14 09:07:29 +09:00
renovate[bot]
f849094c58 Update golang.org/x/oauth2 commit hash to cd4f82c (#496)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-13 20:03:37 +00:00
renovate[bot]
ebdda69c29 Update module k8s.io/klog/v2 to v2.8.0 (#495)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-13 03:56:56 +00:00
renovate[bot]
4d59503ebc Update cimg/go Docker tag to v1.16.2 (#494)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-13 01:02:56 +00:00
renovate[bot]
1a0e6ca973 Update module k8s.io/klog/v2 to v2.7.0 (#492)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-12 04:27:02 +00:00
renovate[bot]
c0d389588b Update golang.org/x/oauth2 commit hash to 5366d9d (#491)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-11 18:33:43 +00:00
renovate[bot]
ca9d3fad89 Update module github.com/chromedp/chromedp to v0.6.8 (#490)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-06 03:25:51 +00:00
renovate[bot]
6a6548c79a Update module github.com/google/go-cmp to v0.5.5 (#487)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-04 19:02:07 +00:00
renovate[bot]
bcaea01da7 Update module k8s.io/klog/v2 to v2.6.0 (#486)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-03-03 13:52:19 +00:00
renovate[bot]
3bf92a9ac1 Update golang.org/x/net commit hash to e18ecbb (#485)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-26 20:12:10 +00:00
renovate[bot]
78ece2f513 Update golang.org/x/net commit hash to 39120d0 (#484)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-26 13:40:01 +00:00
renovate[bot]
a9bf7a019a Update golang.org/x/net commit hash to 3d97a24 (#483)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-24 10:29:16 +00:00
renovate[bot]
03da20fe4d Update golang.org/x/net commit hash to 9060382 (#482)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-22 22:27:26 +00:00
renovate[bot]
1150aa45f8 Update module github.com/chromedp/chromedp to v0.6.6 (#481)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-22 09:53:39 +00:00
renovate[bot]
2513c3ce2c Update module github.com/golang/mock to v1.5.0 (#480)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-20 09:53:52 +00:00
renovate[bot]
f2e0a79817 Update golang.org/x/term commit hash to 6a3ed07 (#478)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-20 08:46:56 +00:00
renovate[bot]
3a59aad12a Update golang.org/x/sync commit hash to 036812b (#479)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-20 07:22:51 +00:00
renovate[bot]
21a5729719 Update golang.org/x/net commit hash to 5f55cee (#477)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-20 05:13:53 +00:00
renovate[bot]
60ae1f9d4b Update golang.org/x/oauth2 commit hash to 9bb9049 (#475)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-20 03:34:53 +00:00
renovate[bot]
b9f0f4b5b0 Update module k8s.io/client-go to v0.20.4 (#474)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-19 07:16:37 +00:00
renovate[bot]
5d0cbfeee5 Update module k8s.io/apimachinery to v0.20.4 (#473)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-19 03:51:33 +00:00
renovate[bot]
5818363cfd Update golang.org/x/oauth2 commit hash to ba52d33 (#472)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-18 23:11:11 +00:00
renovate[bot]
3cc4811a8c Update module k8s.io/client-go to v0.20.3 (#471)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-18 05:43:27 +00:00
renovate[bot]
a0c798ebfe Update module k8s.io/apimachinery to v0.20.3 (#470)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-18 03:38:31 +00:00
renovate[bot]
4e0d73e7b2 Update golang.org/x/oauth2 commit hash to 16ff188 (#469)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-16 21:42:37 +00:00
Hidetake Iwata
86681b82c5 Refactor homebrew formula (#468) 2021-02-11 20:27:52 +09:00
Hidetake Iwata
cc231f7f81 Create question.md 2021-02-11 17:55:57 +09:00
renovate[bot]
44ffd69cbf Update module coreos/go-oidc to v3 (#463)
* Update module coreos/go-oidc to v3

* Update import path to github.com/coreos/go-oidc/v3/oidc

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Hidetake Iwata <int128@gmail.com>
2021-02-11 17:23:22 +09:00
Hidetake Iwata
c3f636300e Update to golangci-lint v1.36.0 (#460)
* Update golangci-lint.yaml

* Use golang.org/x/term

SA1019: package golang.org/x/crypto/ssh/terminal is deprecated: this package moved to golang.org/x/term.  (staticcheck)

* Add workflow name
2021-02-11 17:14:32 +09:00
renovate[bot]
f1a2539262 Update module spf13/cobra to v1.1.3 (#466)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-10 22:00:51 +00:00
renovate[bot]
5e7cb2aff1 Update golang.org/x/oauth2 commit hash to 6667018 (#465)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-10 21:23:31 +00:00
renovate[bot]
e47054ccdb Update module spf13/cobra to v1.1.2 (#464)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-10 03:26:03 +00:00
renovate[bot]
51d5af57cc Update cimg/go Docker tag to v1.15.8 (#462)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-05 00:42:53 +00:00
renovate[bot]
f29ea3a1c7 Update golang.org/x/oauth2 commit hash to 0101308 (#461)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-02-01 18:00:27 +00:00
renovate[bot]
1bb8fb2dc9 Update module k8s.io/klog/v2 to v2.5.0 (#459)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-27 19:33:47 +00:00
renovate[bot]
3e5c3e5918 Update golang.org/x/oauth2 commit hash to f9ce19e (#458)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-26 20:48:53 +00:00
renovate[bot]
cf85625b56 Update module google/wire to v0.5.0 (#457)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-26 03:37:13 +00:00
renovate[bot]
6987910fe6 Update golang.org/x/oauth2 commit hash to af13f52 (#456)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-25 21:04:32 +00:00
renovate[bot]
d89c2dc961 Update module coreos/go-oidc to v3 (#442)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-23 15:19:17 +09:00
renovate[bot]
4e2a99ba8e Update module chromedp/chromedp to v0.6.5 (#455)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-22 14:56:36 +00:00
renovate[bot]
3e915d0811 Update cimg/go Docker tag to v1.15.7 (#454)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-20 17:15:53 +00:00
renovate[bot]
1ca272f61a Update golang.org/x/net commit hash to 5f4716e (#453)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-19 21:31:20 +00:00
renovate[bot]
5b1cc1c994 Update module chromedp/chromedp to v0.6.4 (#452)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-17 02:49:01 +00:00
renovate[bot]
fa416f2910 Update github.com/pkg/browser commit hash to ce105d0 (#450)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-15 05:13:23 +00:00
renovate[bot]
ad65baa624 Update alpine Docker tag to v3.13 (#449)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-15 03:19:59 +00:00
renovate[bot]
25b8d29a44 Update module k8s.io/client-go to v0.20.2 (#448)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-14 03:06:18 +00:00
renovate[bot]
92b09e3e6f Update module k8s.io/apimachinery to v0.20.2 (#447)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-14 00:44:36 +00:00
renovate[bot]
10f904adbb Update golang.org/x/oauth2 commit hash to d3ed898 (#446)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-13 22:33:17 +00:00
renovate[bot]
55d2498dae Update golang.org/x/oauth2 commit hash to 8b1d76f (#445)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-13 17:31:48 +00:00
renovate[bot]
eaf5658d45 Update module chromedp/chromedp to v0.6.1 (#444)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-13 06:34:34 +00:00
renovate[bot]
5608c76764 Update golang.org/x/oauth2 commit hash to 01de73c (#443)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-12 21:18:59 +00:00
Hidetake Iwata
4915ce165f Delete CODEOWNERS 2021-01-11 11:55:00 +09:00
renovate[bot]
bd186d6cfc Update golang.org/x/sync commit hash to 09787c9 (#390)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-10 18:45:47 +00:00
renovate[bot]
411b42b6af Update golang.org/x/oauth2 commit hash to 08078c5 (#415)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-10 17:28:10 +00:00
renovate[bot]
671ee8ecf1 Update golang.org/x/net commit hash to 6772e93 (#407)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-10 16:36:05 +00:00
renovate[bot]
e5b179dfec Update golang.org/x/crypto commit hash to eec23a3 (#391)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-10 15:42:21 +00:00
renovate[bot]
435cdf4a78 Update github.com/pkg/browser commit hash to 0426ae3 (#416)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-10 14:12:42 +00:00
Hidetake Iwata
f94ff640d6 Update renovate.json 2021-01-10 22:49:33 +09:00
renovate[bot]
9be8740f45 Update cimg/go Docker tag to v1.15.6 (#434)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-10 13:16:22 +00:00
Hidetake Iwata
637d091b40 Enable renovate-approve 2021-01-10 21:36:03 +09:00
Hidetake Iwata
637fc746fd Enable automerge 2021-01-10 21:32:24 +09:00
renovate[bot]
7e063b5dda Update module yaml to v2.4.0 (#433)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-10 17:45:49 +09:00
renovate[bot]
202a8616c6 Update module chromedp/chromedp to v0.6.0 (#435)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-09 21:44:56 +09:00
renovate[bot]
21b88cf037 Update module k8s.io/klog/v2 to v2.4.0 (#441)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-01-09 20:17:26 +09:00
Yuri V
38772898fc Switch klog to v2 (#439)
Co-authored-by: Hidetake Iwata <int128@gmail.com>
2021-01-09 18:51:04 +09:00
Hidetake Iwata
58d1839f3e Create CODEOWNERS 2021-01-09 18:13:47 +09:00
renovate[bot]
c7606e8151 Update module google/go-cmp to v0.5.4 (#432)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-12-19 22:26:34 +09:00
renovate[bot]
eb0f2009e2 Update module k8s.io/client-go to v0.20.1 (#438)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-12-19 21:14:06 +09:00
Hidetake Iwata
cffb00f386 Refactor: extract tests into authentication_test.go (#431) 2020-11-23 18:20:47 +09:00
Hidetake Iwata
8e1a63b1a2 Change mutex scope to bind address port (#430) 2020-11-23 17:41:07 +09:00
Hidetake Iwata
ebf81debe1 Refactor: credentialplugin/get_token_test.go (#429)
* Refactor: extract const vars

* Refactor: extract ROPC test case
2020-11-22 20:01:45 +09:00
Hidetake Iwata
2f271b5870 Refactor: replace Input fields with oidc.Provider (#428) 2020-11-21 12:35:23 +09:00
Hidetake Iwata
b1d8e8f7e1 Refactor: rewrite with Go errors package (#427) 2020-11-21 12:10:42 +09:00
Hidetake Iwata
5a3227409c Refactor: rename to infrastructure package (#426) 2020-11-21 07:56:52 +09:00
Hidetake Iwata
13d232ec21 Refactor: move oidc/client package (#425) 2020-11-21 07:27:34 +09:00
Hidetake Iwata
9bab6b2ccd Refactor: extract tokencache and repository package (#424) 2020-11-20 07:01:16 +09:00
Hidetake Iwata
93fc548544 Refactor: extract kubeconfig package (#423)
* Refactor: extract kubeconfig package

* Refactor: use pass by value instead of reference
2020-11-18 10:36:42 +09:00
Hidetake Iwata
4773b67abd Refactor: extract credentialplugin package (#422) 2020-11-18 10:00:39 +09:00
renovate[bot]
009d03cb69 Update module google/go-cmp to v0.5.3 (#417)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-11-14 21:24:05 +09:00
renovate[bot]
417c556e8f Update module k8s.io/client-go to v0.19.4 (#420)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-11-14 20:51:43 +09:00
renovate[bot]
2542d6456c Update cimg/go Docker tag to v1.15.5 (#418)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-11-14 17:54:11 +09:00
renovate[bot]
e3af16ca8f Update cimg/go Docker tag to v1.15.4 (#410)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-11-10 21:30:26 +09:00
Hidetake Iwata
8926e8940a Fix TLS error if CA certificate is not set (#412) 2020-11-08 15:56:41 +09:00
Hidetake Iwata
ce7784b8a0 Add TLS renegotiation flags (#411) 2020-11-07 13:08:29 +09:00
Hidetake Iwata
34762216c1 Refactor: extract tlsclientconfig.Config (#409) 2020-11-03 14:37:24 +09:00
Eric Poitras
878847f937 feat(389): Prevent concurrent authentication using a lockfile. (#397)
* feat(389): Prevent concurrent authentication using a lockfile to protect the local port allocation.

* Fix test

* Refactor: inline values

Co-authored-by: Hidetake Iwata <int128@gmail.com>
2020-10-25 14:32:53 +09:00
Hidetake Iwata
8a392ba25a Refactor: use gotestsum for CircleCI (#377) 2020-10-25 12:47:32 +09:00
Hidetake Iwata
b701a6f0aa Refactor: aggregate test cases to lease and full options (#406) 2020-10-25 12:24:35 +09:00
Hidetake Iwata
10091a3238 go mod tidy 2020-10-25 11:35:58 +09:00
Christoph Stäbler
d1b89e3d38 Add username in token cache key (#404) 2020-10-24 20:44:29 +09:00
renovate[bot]
e862ac7eac Update module spf13/cobra to v1.1.1 (#400)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-10-24 09:26:08 +09:00
renovate[bot]
d051d80435 Update module k8s.io/client-go to v0.19.3 (#403)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-10-24 09:25:29 +09:00
Hidetake Iwata
14e58ac4c2 Update README.md 2020-10-18 08:51:09 +09:00
renovate[bot]
748eb12fc0 Update module spf13/cobra to v1.1.0 (#398)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Hidetake Iwata <int128@gmail.com>
2020-10-18 08:43:36 +09:00
renovate[bot]
8b232eeb3e Update cimg/go Docker tag to v1.15.3 (#399)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2020-10-18 08:37:40 +09:00
Hidetake Iwata
0694a1cd0b Update system-test.yaml 2020-10-18 08:37:17 +09:00
Hidetake Iwata
9ddeb33d27 Update golangci-lint.yaml 2020-10-18 08:35:13 +09:00
Hidetake Iwata
64bfc5a465 Refactor authentication use-cases (#395) 2020-10-03 20:01:26 +09:00
Hidetake Iwata
5b2c82fc33 Refactor: replace DTO with oidc.TokenSet type (#394)
* Refactor: remove IDTokenClaims from TokenSet and decode in use-cases

* Refactor: use oidc.TokenSet for cache repository
2020-10-03 17:49:21 +09:00
Hidetake Iwata
1dee4a354e Refactor: extract oidc.Provider (#393) 2020-10-03 08:35:35 +09:00
Hidetake Iwata
336f2b83d5 go mod tidy 2020-10-03 08:06:47 +09:00
139 changed files with 5147 additions and 3129 deletions

View File

@@ -1,16 +0,0 @@
.PHONY: all
all:
.PHONY: install-test-deps
install-test-deps:
go get -v github.com/int128/goxzst
.PHONY: install-release-deps
install-release-deps: go
go get -v github.com/int128/goxzst github.com/int128/ghcp
go:
curl -sSfL -o go.tgz "https://golang.org/dl/go`ruby go_version_from_config.rb < config.yml`.darwin-amd64.tar.gz"
tar -xf go.tgz
rm go.tgz
./go/bin/go version

View File

@@ -1,60 +0,0 @@
version: 2.1
jobs:
test:
docker:
- image: cimg/go:1.15.2
steps:
- checkout
- restore_cache:
keys:
- go-sum-{{ checksum "go.sum" }}
- run: make -C .circleci install-test-deps
- run: make check
- run: bash <(curl -s https://codecov.io/bash)
- run: make dist
- save_cache:
key: go-sum-{{ checksum "go.sum" }}
paths:
- ~/go/pkg
- store_artifacts:
path: gotest.log
release:
macos:
# https://circleci.com/docs/2.0/testing-ios/
xcode: 11.5.0
steps:
- run: echo 'export PATH="$HOME/go/bin:$PWD/.circleci/go/bin:$PATH"' >> $BASH_ENV
- checkout
- restore_cache:
keys:
- go-macos-{{ checksum "go.sum" }}
- run: make -C .circleci install-release-deps
- run: make dist
- run: |
if [ "$CIRCLE_TAG" ]; then
make release
fi
- save_cache:
key: go-macos-{{ checksum "go.sum" }}
paths:
- ~/go/pkg
workflows:
version: 2
build:
jobs:
- test:
filters:
tags:
only: /^v.*/
- release:
context: open-source
requires:
- test
filters:
branches:
only: /^release-feature.*/
tags:
only: /^v.*/

View File

@@ -1,3 +0,0 @@
module github.com/int128/kubelogin/.circleci
go 1.13

View File

@@ -1,11 +0,0 @@
require 'yaml'
config = YAML.load(STDIN)
image = config["jobs"]["test"]["docker"][0]["image"]
if !image.start_with?("cimg/go:")
raise "unknown image #{image} in #{configPath}"
end
goVersion = image.delete_prefix("cimg/go:")
print(goVersion)

20
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@@ -0,0 +1,20 @@
---
name: Question
about: Feel free to ask a question
title: ''
labels: question
assignees: ''
---
## Describe the question
A clear and concise description of what the issue is.
## To reproduce
A console log or steps to reproduce the issue.
## Your environment
- OS: e.g. macOS
- kubelogin version: e.g. v1.19
- kubectl version: e.g. v1.19
- OpenID Connect provider: e.g. Google

View File

@@ -1,8 +0,0 @@
{
"extends": [
"config:base"
],
"postUpdateOptions": [
"gomodTidy"
]
}

6
.github/renovate.json5 vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": [
"github>int128/renovate-base",
"github>int128/go-actions",
],
}

52
.github/workflows/docker.yaml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: docker
on:
pull_request:
branches:
- master
paths:
- .github/workflows/docker.yaml
- pkg/**
- go.*
- Dockerfile
- Makefile
push:
branches:
- master
paths:
- .github/workflows/docker.yaml
- pkg/**
- go.*
- Dockerfile
- Makefile
tags:
- v*
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: docker/metadata-action@v4
id: metadata
with:
images: ghcr.io/${{ github.repository }}
- uses: int128/docker-build-cache-config-action@v1
id: cache
with:
image: ghcr.io/${{ github.repository }}/cache
- uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/build-push-action@v3
with:
push: ${{ github.event_name == 'push' }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: ${{ steps.cache.outputs.cache-from }}
cache-to: ${{ steps.cache.outputs.cache-to }}
platforms: linux/amd64,linux/arm64,linux/ppc64le

42
.github/workflows/go.yaml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: go
on:
push:
branches:
- master
paths:
- .github/workflows/go.yaml
- pkg/**
- go.*
tags:
- v*
pull_request:
branches:
- master
paths:
- .github/workflows/go.yaml
- pkg/**
- go.*
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: int128/go-actions/setup@v1
with:
go-version: 1.18.5
- uses: golangci/golangci-lint-action@v3
with:
version: v1.48.0
test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: int128/go-actions/setup@v1
with:
go-version: 1.18.5
- run: go test -v -race ./...

View File

@@ -1,14 +0,0 @@
on:
push:
paths:
- .github/workflows/golangci-lint.yaml
- '**.go'
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: golangci/golangci-lint-action@v2
with:
version: v1.30

74
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,74 @@
name: release
on:
push:
branches:
- master
paths:
- .github/workflows/release.yaml
- pkg/**
- go.*
tags:
- v*
pull_request:
branches:
- master
paths:
- .github/workflows/release.yaml
- pkg/**
- go.*
jobs:
build:
strategy:
matrix:
platform:
- runs-on: ubuntu-latest
GOOS: linux
GOARCH: amd64
CGO_ENABLED: 0 # https://github.com/int128/kubelogin/issues/567
- runs-on: ubuntu-latest
GOOS: linux
GOARCH: arm64
- runs-on: ubuntu-latest
GOOS: linux
GOARCH: arm
- runs-on: ubuntu-latest
GOOS: linux
GOARCH: ppc64le
- runs-on: macos-latest
GOOS: darwin
GOARCH: amd64
CGO_ENABLED: 1 # https://github.com/int128/kubelogin/issues/249
- runs-on: macos-latest
GOOS: darwin
GOARCH: arm64
CGO_ENABLED: 1 # https://github.com/int128/kubelogin/issues/762
- runs-on: windows-latest
GOOS: windows
GOARCH: amd64
runs-on: ${{ matrix.platform.runs-on }}
env:
GOOS: ${{ matrix.platform.GOOS }}
GOARCH: ${{ matrix.platform.GOARCH }}
CGO_ENABLED: ${{ matrix.platform.CGO_ENABLED }}
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: int128/go-actions/setup@v1
with:
go-version: 1.18.5
- run: go build -ldflags "-X main.version=${GITHUB_REF##*/}"
- uses: int128/go-actions/release@v1
with:
binary: kubelogin
publish:
if: startswith(github.ref, 'refs/tags/')
needs:
- build
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v3
- uses: rajatjindal/krew-release-bot@v0.0.43

View File

@@ -1,29 +1,41 @@
name: system-test
on:
push:
paths:
pull_request:
branches:
- master
paths:
- .github/workflows/system-test.yaml
- system_test/**
- pkg/**
- go.*
push:
branches:
- master
paths:
- .github/workflows/system-test.yaml
- system_test/**
- pkg/**
- go.*
jobs:
system-test:
# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners#ubuntu-1804-lts
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v2
- uses: actions/checkout@v3
- uses: int128/go-actions/setup@v1
with:
go-version: 1.15
id: go
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: go-${{ hashFiles('**/go.sum') }}
restore-keys: |
go-
go-version: 1.18.5
# for certutil
# https://packages.ubuntu.com/xenial/libnss3-tools
- run: sudo apt update
- run: sudo apt install -y libnss3-tools
- run: mkdir -p ~/.pki/nssdb
- run: echo '127.0.0.1 dex-server' | sudo tee -a /etc/hosts
- run: make -C system_test -j3
- run: make -C system_test logs
if: always()

6
.gitignore vendored
View File

@@ -2,11 +2,9 @@
/acceptance_test/output/
/dist/output
/coverage.out
/gotest.log
/kubelogin
/kubectl-oidc_login
/.circleci/go/
/kubelogin_*.zip
/kubelogin_*.zip.sha256

62
.krew.yaml Normal file
View File

@@ -0,0 +1,62 @@
apiVersion: krew.googlecontainertools.github.com/v1alpha2
kind: Plugin
metadata:
name: oidc-login
spec:
homepage: https://github.com/int128/kubelogin
shortDescription: Log in to the OpenID Connect provider
description: |
This is a kubectl plugin for Kubernetes OpenID Connect (OIDC) authentication.
## Credential plugin mode
kubectl executes oidc-login before calling the Kubernetes APIs.
oidc-login automatically opens the browser and you can log in to the provider.
After authentication, kubectl gets the token from oidc-login and you can access the cluster.
See https://github.com/int128/kubelogin#credential-plugin-mode for more.
## Standalone mode
Run `kubectl oidc-login`.
It automatically opens the browser and you can log in to the provider.
After authentication, it writes the token to the kubeconfig and you can access the cluster.
See https://github.com/int128/kubelogin#standalone-mode for more.
caveats: |
You need to setup the OIDC provider, Kubernetes API server, role binding and kubeconfig.
version: {{ .TagName }}
platforms:
- bin: kubelogin
{{ addURIAndSha "https://github.com/int128/kubelogin/releases/download/{{ .TagName }}/kubelogin_linux_amd64.zip" .TagName }}
selector:
matchLabels:
os: linux
arch: amd64
- bin: kubelogin
{{ addURIAndSha "https://github.com/int128/kubelogin/releases/download/{{ .TagName }}/kubelogin_linux_arm64.zip" .TagName }}
selector:
matchLabels:
os: linux
arch: arm64
- bin: kubelogin
{{ addURIAndSha "https://github.com/int128/kubelogin/releases/download/{{ .TagName }}/kubelogin_linux_arm.zip" .TagName }}
selector:
matchLabels:
os: linux
arch: arm
- bin: kubelogin
{{ addURIAndSha "https://github.com/int128/kubelogin/releases/download/{{ .TagName }}/kubelogin_darwin_amd64.zip" .TagName }}
selector:
matchLabels:
os: darwin
arch: amd64
- bin: kubelogin
{{ addURIAndSha "https://github.com/int128/kubelogin/releases/download/{{ .TagName }}/kubelogin_darwin_arm64.zip" .TagName }}
selector:
matchLabels:
os: darwin
arch: arm64
- bin: kubelogin.exe
{{ addURIAndSha "https://github.com/int128/kubelogin/releases/download/{{ .TagName }}/kubelogin_windows_amd64.zip" .TagName }}
selector:
matchLabels:
os: windows
arch: amd64

12
Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM golang:1.18 as builder
WORKDIR /builder
COPY go.* .
RUN go mod download
COPY main.go .
COPY pkg pkg
RUN go build
FROM gcr.io/distroless/base-debian10
COPY --from=builder /builder/kubelogin /
ENTRYPOINT ["/kubelogin"]

View File

@@ -1,48 +0,0 @@
# CircleCI specific variables
CIRCLE_TAG ?= latest
GITHUB_USERNAME := $(CIRCLE_PROJECT_USERNAME)
GITHUB_REPONAME := $(CIRCLE_PROJECT_REPONAME)
TARGET := kubelogin
TARGET_OSARCH := linux_amd64 darwin_amd64 windows_amd64 linux_arm linux_arm64
VERSION ?= $(CIRCLE_TAG)
LDFLAGS := -X main.version=$(VERSION)
all: $(TARGET)
$(TARGET): $(wildcard **/*.go)
go build -o $@ -ldflags "$(LDFLAGS)"
.PHONY: check
check:
go test -v -race -cover -coverprofile=coverage.out ./... > gotest.log
.PHONY: dist
dist: dist/output
dist/output:
# make the zip files for GitHub Releases
VERSION=$(VERSION) goxzst -d dist/output -i "LICENSE" -o "$(TARGET)" -osarch "$(TARGET_OSARCH)" -t "dist/kubelogin.rb dist/oidc-login.yaml dist/Dockerfile" -- -ldflags "$(LDFLAGS)"
# test the zip file
zipinfo dist/output/kubelogin_linux_amd64.zip
# make the krew yaml structure
mkdir -p dist/output/plugins
mv dist/output/oidc-login.yaml dist/output/plugins/oidc-login.yaml
.PHONY: release
release: dist
# publish the binaries
ghcp release -u "$(GITHUB_USERNAME)" -r "$(GITHUB_REPONAME)" -t "$(VERSION)" dist/output/
# publish the Homebrew formula
ghcp commit -u "$(GITHUB_USERNAME)" -r "homebrew-$(GITHUB_REPONAME)" -b "bump-$(VERSION)" -m "Bump the version to $(VERSION)" -C dist/output/ kubelogin.rb
ghcp pull-request -u "$(GITHUB_USERNAME)" -r "homebrew-$(GITHUB_REPONAME)" -b "bump-$(VERSION)" --title "Bump the version to $(VERSION)"
# publish the Dockerfile
ghcp commit -u "$(GITHUB_USERNAME)" -r "$(GITHUB_REPONAME)-docker" -b "bump-$(VERSION)" -m "Bump the version to $(VERSION)" -C dist/output/ Dockerfile
ghcp pull-request -u "$(GITHUB_USERNAME)" -r "$(GITHUB_REPONAME)-docker" -b "bump-$(VERSION)" --title "Bump the version to $(VERSION)"
# publish the Krew manifest
ghcp fork-commit -u kubernetes-sigs -r krew-index -b "oidc-login-$(VERSION)" -m "Bump oidc-login to $(VERSION)" -C dist/output/ plugins/oidc-login.yaml
.PHONY: clean
clean:
-rm $(TARGET)
-rm -r dist/output/
-rm coverage.out gotest.log

View File

@@ -1,4 +1,4 @@
# kubelogin [![CircleCI](https://circleci.com/gh/int128/kubelogin.svg?style=shield)](https://circleci.com/gh/int128/kubelogin) [![Go Report Card](https://goreportcard.com/badge/github.com/int128/kubelogin)](https://goreportcard.com/report/github.com/int128/kubelogin)
# kubelogin [![go](https://github.com/int128/kubelogin/actions/workflows/go.yaml/badge.svg)](https://github.com/int128/kubelogin/actions/workflows/go.yaml) [![Go Report Card](https://goreportcard.com/badge/github.com/int128/kubelogin)](https://goreportcard.com/report/github.com/int128/kubelogin)
This is a kubectl plugin for [Kubernetes OpenID Connect (OIDC) authentication](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens), also known as `kubectl oidc-login`.
@@ -31,6 +31,8 @@ kubectl krew install oidc-login
choco install kubelogin
```
If you install via GitHub releases, you need to put the `kubelogin` binary on your path under the name `kubectl-oidc_login` so that the [kubectl plugin mechanism](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/) can find it when you invoke `kubectl oidc-login`. The other install methods do this for you.
You need to set up the OIDC provider, cluster role binding, Kubernetes API server and kubeconfig.
The kubeconfig looks like:
@@ -65,7 +67,7 @@ Kubelogin automatically opens the browser, and you can log in to the provider.
<img src="docs/keycloak-login.png" alt="keycloak-login" width="455" height="329">
After authentication, kubelogin returns the credentials to kubectl and finally kubectl calls the Kubernetes APIs with the credential.
After authentication, kubelogin returns the credentials to kubectl and kubectl then calls the Kubernetes APIs with these credentials.
```
% kubectl get pods
@@ -78,13 +80,13 @@ Kubelogin writes the ID token and refresh token to the token cache file.
If the cached ID token is valid, kubelogin just returns it.
If the cached ID token has expired, kubelogin will refresh the token using the refresh token.
If the refresh token has expired, kubelogin will perform reauthentication.
If the refresh token has expired, kubelogin will perform re-authentication (you will have to login via browser again).
### Troubleshoot
You can log out by removing the token cache directory (default `~/.kube/cache/oidc-login`).
Kubelogin will perform authentication if the token cache file does not exist.
Kubelogin will ask you to login via browser again if the token cache file does not exist i.e., it starts with a clean slate
You can dump claims of an ID token by `setup` command.
@@ -101,6 +103,21 @@ You got a token with the following claims:
}
```
You can increase the log level by `-v1` option.
```yaml
users:
- name: oidc
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: kubectl
args:
- oidc-login
- get-token
- -v1
```
You can verify kubelogin works with your provider using [acceptance test](acceptance_test).
@@ -108,14 +125,9 @@ You can verify kubelogin works with your provider using [acceptance test](accept
- [Setup guide](docs/setup.md)
- [Usage and options](docs/usage.md)
- [Standalone mode](docs/standalone-mode.md) (deprecated)
## Related works
### Kubernetes Dashboard
You can access the Kubernetes Dashboard using kubelogin and [kauthproxy](https://github.com/int128/kauthproxy).
- [Standalone mode](docs/standalone-mode.md)
- [System test](system_test)
- [Acceptance_test for identity providers](acceptance_test)
## Contributions
@@ -123,19 +135,5 @@ You can access the Kubernetes Dashboard using kubelogin and [kauthproxy](https:/
This is an open source software licensed under Apache License 2.0.
Feel free to open issues and pull requests for improving code and documents.
### Development
Go 1.13 or later is required.
```sh
# Run lint and tests
make check
# Compile and run the command
make
./kubelogin
```
### System test
See [system test](system_test) for more.
This software is developed with [GoLand](https://www.jetbrains.com/go/) licensed for open source development.
Special thanks for the support.

13
dist/Dockerfile vendored
View File

@@ -1,13 +0,0 @@
FROM alpine:3.12
ARG KUBELOGIN_VERSION="{{ env "VERSION" }}"
ARG KUBELOGIN_SHA256="{{ sha256 .linux_amd64_archive }}"
# Download the release and test the checksum
RUN wget -O /kubelogin.zip "https://github.com/int128/kubelogin/releases/download/$KUBELOGIN_VERSION/kubelogin_linux_amd64.zip" && \
echo "$KUBELOGIN_SHA256 /kubelogin.zip" | sha256sum -c - && \
unzip /kubelogin.zip && \
rm /kubelogin.zip
USER daemon
ENTRYPOINT ["/kubelogin"]

27
dist/kubelogin.rb vendored
View File

@@ -1,27 +0,0 @@
class Kubelogin < Formula
desc "A kubectl plugin for Kubernetes OpenID Connect authentication"
homepage "https://github.com/int128/kubelogin"
baseurl = "https://github.com/int128/kubelogin/releases/download"
version "{{ env "VERSION" }}"
if OS.mac?
kernel = "darwin"
sha256 "{{ sha256 .darwin_amd64_archive }}"
elsif OS.linux?
kernel = "linux"
sha256 "{{ sha256 .linux_amd64_archive }}"
end
url baseurl + "/#{version}/kubelogin_#{kernel}_amd64.zip"
def install
bin.install "kubelogin" => "kubelogin"
ln_s bin/"kubelogin", bin/"kubectl-oidc_login"
end
test do
system "#{bin}/kubelogin -h"
system "#{bin}/kubectl-oidc_login -h"
end
end

86
dist/oidc-login.yaml vendored
View File

@@ -1,86 +0,0 @@
apiVersion: krew.googlecontainertools.github.com/v1alpha2
kind: Plugin
metadata:
name: oidc-login
spec:
homepage: https://github.com/int128/kubelogin
shortDescription: Log in to the OpenID Connect provider
description: |
This is a kubectl plugin for Kubernetes OpenID Connect (OIDC) authentication.
## Credential plugin mode
kubectl executes oidc-login before calling the Kubernetes APIs.
oidc-login automatically opens the browser and you can log in to the provider.
After authentication, kubectl gets the token from oidc-login and you can access the cluster.
See https://github.com/int128/kubelogin#credential-plugin-mode for more.
## Standalone mode
Run `kubectl oidc-login`.
It automatically opens the browser and you can log in to the provider.
After authentication, it writes the token to the kubeconfig and you can access the cluster.
See https://github.com/int128/kubelogin#standalone-mode for more.
caveats: |
You need to setup the OIDC provider, Kubernetes API server, role binding and kubeconfig.
version: {{ env "VERSION" }}
platforms:
- uri: https://github.com/int128/kubelogin/releases/download/{{ env "VERSION" }}/kubelogin_linux_amd64.zip
sha256: "{{ sha256 .linux_amd64_archive }}"
bin: kubelogin
files:
- from: kubelogin
to: .
- from: LICENSE
to: .
selector:
matchLabels:
os: linux
arch: amd64
- uri: https://github.com/int128/kubelogin/releases/download/{{ env "VERSION" }}/kubelogin_darwin_amd64.zip
sha256: "{{ sha256 .darwin_amd64_archive }}"
bin: kubelogin
files:
- from: kubelogin
to: .
- from: LICENSE
to: .
selector:
matchLabels:
os: darwin
arch: amd64
- uri: https://github.com/int128/kubelogin/releases/download/{{ env "VERSION" }}/kubelogin_windows_amd64.zip
sha256: "{{ sha256 .windows_amd64_archive }}"
bin: kubelogin.exe
files:
- from: kubelogin.exe
to: .
- from: LICENSE
to: .
selector:
matchLabels:
os: windows
arch: amd64
- uri: https://github.com/int128/kubelogin/releases/download/{{ env "VERSION" }}/kubelogin_linux_arm.zip
sha256: "{{ sha256 .linux_arm_archive }}"
bin: kubelogin
files:
- from: kubelogin
to: .
- from: LICENSE
to: .
selector:
matchLabels:
os: linux
arch: arm
- uri: https://github.com/int128/kubelogin/releases/download/{{ env "VERSION" }}/kubelogin_linux_arm64.zip
sha256: "{{ sha256 .linux_arm64_archive }}"
bin: kubelogin
files:
- from: kubelogin
to: .
- from: LICENSE
to: .
selector:
matchLabels:
os: linux
arch: arm64

View File

@@ -129,6 +129,25 @@ You do not need to set `YOUR_CLIENT_SECRET`.
If you need `groups` claim for access control,
see [jetstack/okta-kubectl-auth](https://github.com/jetstack/okta-kubectl-auth/blob/master/docs/okta-setup.md) and [#250](https://github.com/int128/kubelogin/issues/250).
### Ping Identity
Login with an account that has permissions to create applications.
Create an OIDC application with the following configuration:
- Redirect URIs:
- `http://localhost:8000`
- `http://localhost:18000` (used if the port 8000 is already in use)
- Grant type: Authorization Code
- PKCE Enforcement: Required
Leverage the following variables in the next steps.
Variable | Value
------------------------|------
`ISSUER_URL` | `https://auth.pingone.com/<PingOne Tenant Id>/as`
`YOUR_CLIENT_ID` | random string
`YOUR_CLIENT_SECRET` is not required for this configuration.
## 2. Verify authentication

View File

@@ -1,9 +1,12 @@
# Standalone mode
You can run kubelogin as a standalone command.
In this mode, you need to manually run the command before running kubectl.
Kubelogin supports the standalone mode as well.
It writes the token to the kubeconfig (typically `~/.kube/config`) after authentication.
Configure the kubeconfig like:
## Getting started
Configure your kubeconfig like:
```yaml
- name: keycloak
@@ -31,7 +34,7 @@ It automatically opens the browser and you can log in to the provider.
After authentication, kubelogin writes the ID token and refresh token to the kubeconfig.
```
```console
% kubelogin
Open http://localhost:8000 for authentication
You got a valid token until 2019-05-18 10:28:51 +0900 JST
@@ -40,7 +43,7 @@ Updated ~/.kubeconfig
Now you can access the cluster.
```
```console
% kubectl get pods
NAME READY STATUS RESTARTS AGE
echoserver-86c78fdccd-nzmd5 1/1 Running 0 26d
@@ -64,7 +67,7 @@ users:
If the ID token is valid, kubelogin does nothing.
```
```console
% kubelogin
You already have a valid token until 2019-05-18 10:28:51 +0900 JST
```
@@ -75,8 +78,6 @@ If the refresh token has expired, kubelogin will proceed the authentication.
## Usage
### Kubeconfig
You can set path to the kubeconfig file by the option or the environment variable just like kubectl.
It defaults to `~/.kube/config`.
@@ -104,26 +105,4 @@ Key | Direction | Value
`id-token` | Write | ID token got from the provider.
`refresh-token` | Write | Refresh token got from the provider.
### Extra scopes
You can set the extra scopes to request to the provider by `extra-scopes` in the kubeconfig.
```sh
kubectl config set-credentials keycloak --auth-provider-arg extra-scopes=email
```
Currently kubectl does not accept multiple scopes, so you need to edit the kubeconfig as like:
```sh
kubectl config set-credentials keycloak --auth-provider-arg extra-scopes=SCOPES
sed -i '' -e s/SCOPES/email,profile/ $KUBECONFIG
```
### CA Certificates
You can use your self-signed certificates for the provider.
```sh
kubectl config set-credentials keycloak \
--auth-provider-arg idp-certificate-authority=$HOME/.kube/keycloak-ca.pem
```
See also [usage.md](usage.md).

View File

@@ -11,13 +11,17 @@ Flags:
--oidc-client-id string Client ID of the provider (mandatory)
--oidc-client-secret string Client secret of the provider
--oidc-extra-scope strings Scopes to request to the provider
--oidc-use-pkce Force PKCE usage
--token-cache-dir string Path to a directory for token cache (default "~/.kube/cache/oidc-login")
--certificate-authority string Path to a cert file for the certificate authority
--certificate-authority-data string Base64 encoded cert for the certificate authority
--certificate-authority stringArray Path to a cert file for the certificate authority
--certificate-authority-data stringArray Base64 encoded cert for the certificate authority
--insecure-skip-tls-verify If set, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--tls-renegotiation-once If set, allow a remote server to request renegotiation once per connection
--tls-renegotiation-freely If set, allow a remote server to repeatedly request renegotiation
--grant-type string Authorization grant type to use. One of (auto|authcode|authcode-keyboard|password) (default "auto")
--listen-address strings [authcode] Address to bind to the local server. If multiple addresses are set, it will try binding in order (default [127.0.0.1:8000,127.0.0.1:18000])
--skip-open-browser [authcode] Do not open the browser automatically
--browser-command string [authcode] Command to open the browser
--authentication-timeout-sec int [authcode] Timeout of authentication in seconds (default 180)
--local-server-cert string [authcode] Certificate path for the local server
--local-server-key string [authcode] Certificate key path for the local server
@@ -29,13 +33,14 @@ Flags:
-h, --help help for get-token
Global Flags:
--add_dir_header If true, adds the file directory to the header
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files (default true)
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level)
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
@@ -81,6 +86,16 @@ You can use your self-signed certificate for the provider.
You can set the following environment variables if you are behind a proxy: `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY`.
See also [net/http#ProxyFromEnvironment](https://golang.org/pkg/net/http/#ProxyFromEnvironment).
### Home directory expansion
If a value in the following options begins with a tilde character `~`, it is expanded to the home directory.
- `--certificate-authority`
- `--local-server-cert`
- `--local-server-key`
- `--token-cache-dir`
## Authentication flows
Kubelogin support the following flows:
@@ -205,7 +220,7 @@ Password:
## Run in Docker
You can run [the Docker image](https://quay.io/repository/int128/kubelogin) instead of the binary.
You can run [the Docker image](https://ghcr.io/int128/kubelogin) instead of the binary.
The kubeconfig looks like:
```yaml
@@ -222,7 +237,7 @@ users:
- /tmp/.token-cache:/.token-cache
- -p
- 8000:8000
- quay.io/int128/kubelogin
- ghcr.io/int128/kubelogin
- get-token
- --token-cache-dir=/.token-cache
- --listen-address=0.0.0.0:8000

40
go.mod
View File

@@ -1,27 +1,25 @@
module github.com/int128/kubelogin
go 1.12
go 1.16
require (
github.com/chromedp/chromedp v0.5.3
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/golang/mock v1.4.4
github.com/google/go-cmp v0.5.2
github.com/google/wire v0.4.0
github.com/int128/oauth2cli v1.13.0
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/spf13/cobra v1.0.0
github.com/alexflint/go-filemutex v1.2.0
github.com/chromedp/chromedp v0.8.5
github.com/coreos/go-oidc/v3 v3.2.0
github.com/golang-jwt/jwt/v4 v4.4.2
github.com/google/go-cmp v0.5.9
github.com/google/wire v0.5.0
github.com/int128/oauth2cli v1.14.0
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
github.com/spf13/cobra v1.5.0
github.com/spf13/pflag v1.0.5
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/square/go-jose.v2 v2.3.1 // indirect
gopkg.in/yaml.v2 v2.3.0
k8s.io/apimachinery v0.19.2
k8s.io/client-go v0.19.2
k8s.io/klog v1.0.0
github.com/stretchr/testify v1.8.0
golang.org/x/net v0.0.0-20220909164309-bea034e7d591
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
golang.org/x/sync v0.0.0-20220907140024-f12130a52804
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035
gopkg.in/yaml.v2 v2.4.0
k8s.io/apimachinery v0.24.4
k8s.io/client-go v0.24.4
k8s.io/klog/v2 v2.70.1
)

648
go.sum
View File

@@ -6,7 +6,6 @@ cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
@@ -14,14 +13,36 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
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/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
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=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@@ -31,108 +52,121 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
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=
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
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/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/alexflint/go-filemutex v1.2.0 h1:1v0TJPDtlhgpW4nJ+GvxCLSlUDC3+gW0CQQvlmfDR/s=
github.com/alexflint/go-filemutex v1.2.0/go.mod h1:mYyQSWvw9Tx2/H2n9qXPb52tTYfE0pZAWcBq5mK025c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chromedp/cdproto v0.0.0-20200116234248-4da64dd111ac h1:T7V5BXqnYd55Hj/g5uhDYumg9Fp3rMTS6bykYtTIFX4=
github.com/chromedp/cdproto v0.0.0-20200116234248-4da64dd111ac/go.mod h1:PfAWWKJqjlGFYJEidUM6aVIWPr0EpobeyVWEEmplX7g=
github.com/chromedp/chromedp v0.5.3 h1:F9LafxmYpsQhWQBdCs+6Sret1zzeeFyHS5LkRF//Ffg=
github.com/chromedp/chromedp v0.5.3/go.mod h1:YLdPtndaHQ4rCpSpBG+IPpy9JvX0VD+7aaLxYgYj28w=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf h1:e0oJZmGJidTRZ0FvWXNhdj9OaOMN30Yf+T3K2Tf3L+s=
github.com/chromedp/cdproto v0.0.0-20220827030233-358ed4af73cf/go.mod h1:5Y4sD/eXpwrChIuxhSr/G20n9CdbCmoerOHnuAf0Zr0=
github.com/chromedp/chromedp v0.8.5 h1:HAVg54yQFcn7sg5reVjXtoI1eQaFxhjAjflHACicUFw=
github.com/chromedp/chromedp v0.8.5/go.mod h1:xal2XY5Di7m/bzlGwtoYpmgIOfDqCakOIVg5OfdkPZ4=
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
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/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-oidc/v3 v3.2.0 h1:2eR2MGR7thBXSQ2YbODlF0fcmgtliLCfr9iX6RW11fc=
github.com/coreos/go-oidc/v3 v3.2.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+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/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
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=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
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/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
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-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/gogo/protobuf v1.1.1/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.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
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=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
@@ -143,26 +177,41 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
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.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=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -170,148 +219,139 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.4.0 h1:kXcsA/rIGzJImVqPdhfnr6q0xsS9gU0515q1EPpJ9fE=
github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
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/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
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/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
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.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
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=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/int128/listener v1.1.0 h1:2Jb41DWLpkQ3I9bIdBzO8H/tNwMvyl/OBZWtCV5Pjuw=
github.com/int128/listener v1.1.0/go.mod h1:68WkmTN8PQtLzc9DucIaagAKeGVyMnyyKIkW4Xn47UA=
github.com/int128/oauth2cli v1.13.0 h1:3wR48gSHdOPFgHmtnXzs4wEFA6p24prPqLXu6QUOujw=
github.com/int128/oauth2cli v1.13.0/go.mod h1:EUpEzcUumoVjLPHD7y2KGxwfXYqxDVqwDfqQ+u7qAwM=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/int128/oauth2cli v1.14.0 h1:r63NoO10ybUXIXUQxih8WOmt5HQpJubdTmhWh22B9VE=
github.com/int128/oauth2cli v1.14.0/go.mod h1:LIoVAzgAsS2tDDBc8yopkcgY5oZR0+MJAeECkCwtxhA=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
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/knq/sysutil v0.0.0-20191005231841-15668db23d08 h1:V0an7KRw92wmJysvFvtqtKMAPmvS5O0jtB0nYo6t+gs=
github.com/knq/sysutil v0.0.0-20191005231841-15668db23d08/go.mod h1:dFWs1zEqDjFtnBXsd1vPOZaLsESovai349994nHx3e0=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/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=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
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/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
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/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
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.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
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/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
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=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
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=
@@ -334,6 +374,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@@ -342,23 +384,23 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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-20181114220301-adae6a3d119a/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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
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=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -367,40 +409,72 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
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-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
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 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
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-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
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/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 h1:lxqLZaMad/dJHMFZH0NiNpiEZI/nhgWhe4wgzpE+MuA=
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
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 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220907140024-f12130a52804 h1:0SH2R3f1b1VmIMG7BXbEZCBUu2dKmHschSmjqGUrW8A=
golang.org/x/sync v0.0.0-20220907140024-f12130a52804/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -409,13 +483,13 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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-20190904154756-749cb33beabd/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-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -426,27 +500,67 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/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=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/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-20210908233432-aa78b53d3365/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-20211210111614-af8b64212486/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-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/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/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/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=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
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-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
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/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -481,18 +595,33 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
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-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=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
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=
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
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=
@@ -509,15 +638,37 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
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.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=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
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=
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -541,15 +692,64 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
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-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
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=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -560,6 +760,26 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
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.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -568,34 +788,38 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
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-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
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-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
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=
@@ -603,24 +827,30 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI=
k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/api v0.24.4 h1:I5Y645gJ8zWKawyr78lVfDQkZrAViSbeRXsPZWTxmXk=
k8s.io/api v0.24.4/go.mod h1:42pVfA0NRxrtJhZQOvRSyZcJihzAdU59WBtTjYcB0/M=
k8s.io/apimachinery v0.24.4 h1:S0Ur3J/PbivTcL43EdSdPhqCqKla2NIuneNwZcTDeGQ=
k8s.io/apimachinery v0.24.4/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/client-go v0.24.4 h1:hIAIJZIPyaw46AkxwyR0FRfM/pRxpUNTd3ysYu9vyRg=
k8s.io/client-go v0.24.4/go.mod h1:+AxlPWw/H6f+EJhRSjIeALaJT4tbeB/8g9BNvXGPd0Y=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg=
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU=
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
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/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -13,8 +13,8 @@ import (
"github.com/int128/kubelogin/integration_test/httpdriver"
"github.com/int128/kubelogin/integration_test/keypair"
"github.com/int128/kubelogin/integration_test/oidcserver"
"github.com/int128/kubelogin/pkg/adaptors/browser"
"github.com/int128/kubelogin/pkg/di"
"github.com/int128/kubelogin/pkg/infrastructure/browser"
"github.com/int128/kubelogin/pkg/testing/clock"
"github.com/int128/kubelogin/pkg/testing/logger"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -29,7 +29,7 @@ import (
// 4. Verify the output.
//
func TestCredentialPlugin(t *testing.T) {
timeout := 3 * time.Second
timeout := 10 * time.Second
now := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
tokenCacheDir := t.TempDir()
@@ -62,7 +62,6 @@ func TestCredentialPlugin(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
var stdout bytes.Buffer
runGetToken(t, ctx, getTokenConfig{
tokenCacheDir: tokenCacheDir,
@@ -90,7 +89,6 @@ func TestCredentialPlugin(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
var stdout bytes.Buffer
runGetToken(t, ctx, getTokenConfig{
tokenCacheDir: tokenCacheDir,
@@ -111,7 +109,6 @@ func TestCredentialPlugin(t *testing.T) {
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
defer cancel()
sv := oidcserver.New(t, tc.keyPair, oidcserver.Config{})
defer sv.Shutdown(t, ctx)
t.Run("NoCache", func(t *testing.T) {
sv.SetConfig(oidcserver.Config{
@@ -212,7 +209,6 @@ func TestCredentialPlugin(t *testing.T) {
CodeChallengeMethodsSupported: []string{"plain", "S256"},
},
})
defer sv.Shutdown(t, ctx)
var stdout bytes.Buffer
runGetToken(t, ctx, getTokenConfig{
tokenCacheDir: tokenCacheDir,
@@ -237,7 +233,6 @@ func TestCredentialPlugin(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
var stdout bytes.Buffer
runGetToken(t, ctx, getTokenConfig{
tokenCacheDir: tokenCacheDir,
@@ -263,7 +258,6 @@ func TestCredentialPlugin(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
var stdout bytes.Buffer
runGetToken(t, ctx, getTokenConfig{
tokenCacheDir: tokenCacheDir,
@@ -292,7 +286,6 @@ func TestCredentialPlugin(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
var stdout bytes.Buffer
runGetToken(t, ctx, getTokenConfig{
tokenCacheDir: tokenCacheDir,
@@ -318,7 +311,6 @@ func TestCredentialPlugin(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
var stdout bytes.Buffer
runGetToken(t, ctx, getTokenConfig{
tokenCacheDir: tokenCacheDir,
@@ -344,7 +336,6 @@ func TestCredentialPlugin(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
var stdout bytes.Buffer
runGetToken(t, ctx, getTokenConfig{
tokenCacheDir: tokenCacheDir,
@@ -380,7 +371,6 @@ func TestCredentialPlugin(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
var stdout bytes.Buffer
runGetToken(t, ctx, getTokenConfig{
tokenCacheDir: tokenCacheDir,

View File

@@ -60,6 +60,10 @@ func (c *client) Open(url string) error {
return nil
}
func (c *client) OpenCommand(_ context.Context, url, _ string) error {
return c.Open(url)
}
type zeroClient struct {
t *testing.T
}
@@ -68,3 +72,7 @@ func (c *zeroClient) Open(url string) error {
c.t.Errorf("unexpected function call Open(%s)", url)
return nil
}
func (c *zeroClient) OpenCommand(_ context.Context, url, _ string) error {
return c.Open(url)
}

View File

@@ -22,7 +22,8 @@ type Values struct {
// Create creates a kubeconfig file and returns path to it.
func Create(t *testing.T, v *Values) string {
t.Helper()
f, err := os.Create(filepath.Join(t.TempDir(), "kubeconfig"))
name := filepath.Join(t.TempDir(), "kubeconfig")
f, err := os.Create(name)
if err != nil {
t.Fatal(err)
}
@@ -34,7 +35,7 @@ func Create(t *testing.T, v *Values) string {
if err := tpl.Execute(f, v); err != nil {
t.Fatal(err)
}
return f.Name()
return name
}
type AuthProviderConfig struct {

View File

@@ -3,11 +3,10 @@ package handler
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"testing"
"golang.org/x/xerrors"
)
func New(t *testing.T, provider Provider) *Handler {
@@ -29,7 +28,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.t.Logf("%d %s %s", wr.statusCode, r.Method, r.RequestURI)
return
}
if errResp := new(ErrorResponse); xerrors.As(err, &errResp) {
if errResp := new(ErrorResponse); errors.As(err, &errResp) {
h.t.Logf("400 %s %s: %s", r.Method, r.RequestURI, err)
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(400)
@@ -62,14 +61,14 @@ func (h *Handler) serveHTTP(w http.ResponseWriter, r *http.Request) error {
w.Header().Add("Content-Type", "application/json")
e := json.NewEncoder(w)
if err := e.Encode(discoveryResponse); err != nil {
return xerrors.Errorf("could not render json: %w", err)
return fmt.Errorf("could not render json: %w", err)
}
case m == "GET" && p == "/certs":
certificatesResponse := h.provider.GetCertificates()
w.Header().Add("Content-Type", "application/json")
e := json.NewEncoder(w)
if err := e.Encode(certificatesResponse); err != nil {
return xerrors.Errorf("could not render json: %w", err)
return fmt.Errorf("could not render json: %w", err)
}
case m == "GET" && p == "/auth":
q := r.URL.Query()
@@ -84,13 +83,13 @@ func (h *Handler) serveHTTP(w http.ResponseWriter, r *http.Request) error {
RawQuery: q,
})
if err != nil {
return xerrors.Errorf("authentication error: %w", err)
return fmt.Errorf("authentication error: %w", err)
}
to := fmt.Sprintf("%s?state=%s&code=%s", redirectURI, state, code)
http.Redirect(w, r, to, 302)
case m == "POST" && p == "/token":
if err := r.ParseForm(); err != nil {
return xerrors.Errorf("could not parse the form: %w", err)
return fmt.Errorf("could not parse the form: %w", err)
}
grantType := r.Form.Get("grant_type")
switch grantType {
@@ -100,12 +99,12 @@ func (h *Handler) serveHTTP(w http.ResponseWriter, r *http.Request) error {
CodeVerifier: r.Form.Get("code_verifier"),
})
if err != nil {
return xerrors.Errorf("token request error: %w", err)
return fmt.Errorf("token request error: %w", err)
}
w.Header().Add("Content-Type", "application/json")
e := json.NewEncoder(w)
if err := e.Encode(tokenResponse); err != nil {
return xerrors.Errorf("could not render json: %w", err)
return fmt.Errorf("could not render json: %w", err)
}
case "password":
// 4.3. Resource Owner Password Credentials Grant
@@ -113,12 +112,12 @@ func (h *Handler) serveHTTP(w http.ResponseWriter, r *http.Request) error {
username, password, scope := r.Form.Get("username"), r.Form.Get("password"), r.Form.Get("scope")
tokenResponse, err := h.provider.AuthenticatePassword(username, password, scope)
if err != nil {
return xerrors.Errorf("authentication error: %w", err)
return fmt.Errorf("authentication error: %w", err)
}
w.Header().Add("Content-Type", "application/json")
e := json.NewEncoder(w)
if err := e.Encode(tokenResponse); err != nil {
return xerrors.Errorf("could not render json: %w", err)
return fmt.Errorf("could not render json: %w", err)
}
case "refresh_token":
// 12.1. Refresh Request
@@ -126,12 +125,12 @@ func (h *Handler) serveHTTP(w http.ResponseWriter, r *http.Request) error {
refreshToken := r.Form.Get("refresh_token")
tokenResponse, err := h.provider.Refresh(refreshToken)
if err != nil {
return xerrors.Errorf("token refresh error: %w", err)
return fmt.Errorf("token refresh error: %w", err)
}
w.Header().Add("Content-Type", "application/json")
e := json.NewEncoder(w)
if err := e.Encode(tokenResponse); err != nil {
return xerrors.Errorf("could not render json: %w", err)
return fmt.Errorf("could not render json: %w", err)
}
default:
// 5.2. Error Response

View File

@@ -10,28 +10,14 @@ import (
"github.com/int128/kubelogin/integration_test/keypair"
)
type Shutdowner interface {
Shutdown(t *testing.T, ctx context.Context)
}
type shutdowner struct {
s *http.Server
}
func (s *shutdowner) Shutdown(t *testing.T, ctx context.Context) {
if err := s.s.Shutdown(ctx); err != nil {
t.Errorf("could not shutdown the server: %s", err)
}
}
func Start(t *testing.T, h http.Handler, k keypair.KeyPair) (string, Shutdowner) {
func Start(t *testing.T, h http.Handler, k keypair.KeyPair) string {
if k == keypair.None {
return startNoTLS(t, h)
}
return startTLS(t, h, k)
}
func startNoTLS(t *testing.T, h http.Handler) (string, *shutdowner) {
func startNoTLS(t *testing.T, h http.Handler) string {
t.Helper()
l, port := newLocalhostListener(t)
url := "http://localhost:" + port
@@ -44,10 +30,15 @@ func startNoTLS(t *testing.T, h http.Handler) (string, *shutdowner) {
t.Error(err)
}
}()
return url, &shutdowner{s}
t.Cleanup(func() {
if err := s.Shutdown(context.TODO()); err != nil {
t.Errorf("could not shutdown the server: %s", err)
}
})
return url
}
func startTLS(t *testing.T, h http.Handler, k keypair.KeyPair) (string, *shutdowner) {
func startTLS(t *testing.T, h http.Handler, k keypair.KeyPair) string {
t.Helper()
l, port := newLocalhostListener(t)
url := "https://localhost:" + port
@@ -60,7 +51,12 @@ func startTLS(t *testing.T, h http.Handler, k keypair.KeyPair) (string, *shutdow
t.Error(err)
}
}()
return url, &shutdowner{s}
t.Cleanup(func() {
if err := s.Shutdown(context.TODO()); err != nil {
t.Errorf("could not shutdown the server: %s", err)
}
})
return url
}
func newLocalhostListener(t *testing.T) (net.Listener, string) {

View File

@@ -4,6 +4,7 @@ package oidcserver
import (
"crypto/sha256"
"encoding/base64"
"fmt"
"math/big"
"strings"
"testing"
@@ -13,11 +14,9 @@ import (
"github.com/int128/kubelogin/integration_test/oidcserver/handler"
"github.com/int128/kubelogin/integration_test/oidcserver/http"
"github.com/int128/kubelogin/pkg/testing/jwt"
"golang.org/x/xerrors"
)
type Server interface {
http.Shutdowner
IssuerURL() string
SetConfig(Config)
LastTokenResponse() *handler.TokenResponse
@@ -51,13 +50,12 @@ type Config struct {
// New starts a HTTP server for the OpenID Connect provider.
func New(t *testing.T, k keypair.KeyPair, c Config) Server {
sv := server{Config: c, t: t}
sv.issuerURL, sv.Shutdowner = http.Start(t, handler.New(t, &sv), k)
sv.issuerURL = http.Start(t, handler.New(t, &sv), k)
return &sv
}
type server struct {
Config
http.Shutdowner
t *testing.T
issuerURL string
lastAuthenticationRequest *handler.AuthenticationRequest
@@ -133,7 +131,7 @@ func (sv *server) AuthenticateCode(req handler.AuthenticationRequest) (code stri
func (sv *server) Exchange(req handler.TokenRequest) (*handler.TokenResponse, error) {
if req.Code != "YOUR_AUTH_CODE" {
return nil, xerrors.Errorf("code wants %s but was %s", "YOUR_AUTH_CODE", req.Code)
return nil, fmt.Errorf("code wants %s but was %s", "YOUR_AUTH_CODE", req.Code)
}
if sv.lastAuthenticationRequest.CodeChallengeMethod == "S256" {
// https://tools.ietf.org/html/rfc7636#section-4.6

View File

@@ -10,8 +10,8 @@ import (
"github.com/int128/kubelogin/integration_test/keypair"
"github.com/int128/kubelogin/integration_test/kubeconfig"
"github.com/int128/kubelogin/integration_test/oidcserver"
"github.com/int128/kubelogin/pkg/adaptors/browser"
"github.com/int128/kubelogin/pkg/di"
"github.com/int128/kubelogin/pkg/infrastructure/browser"
"github.com/int128/kubelogin/pkg/testing/clock"
"github.com/int128/kubelogin/pkg/testing/logger"
)
@@ -55,12 +55,10 @@ func TestStandalone(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
Issuer: sv.IssuerURL(),
IDPCertificateAuthority: tc.keyPair.CACertPath,
})
defer os.Remove(kubeConfigFilename)
runStandalone(t, ctx, standaloneConfig{
issuerURL: sv.IssuerURL(),
kubeConfigFilename: kubeConfigFilename,
@@ -88,12 +86,10 @@ func TestStandalone(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
Issuer: sv.IssuerURL(),
IDPCertificateAuthority: tc.keyPair.CACertPath,
})
defer os.Remove(kubeConfigFilename)
runStandalone(t, ctx, standaloneConfig{
issuerURL: sv.IssuerURL(),
kubeConfigFilename: kubeConfigFilename,
@@ -115,12 +111,10 @@ func TestStandalone(t *testing.T) {
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
defer cancel()
sv := oidcserver.New(t, tc.keyPair, oidcserver.Config{})
defer sv.Shutdown(t, ctx)
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
Issuer: sv.IssuerURL(),
IDPCertificateAuthority: tc.keyPair.CACertPath,
})
defer os.Remove(kubeConfigFilename)
t.Run("NoToken", func(t *testing.T) {
sv.SetConfig(oidcserver.Config{
@@ -219,12 +213,10 @@ func TestStandalone(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
Issuer: sv.IssuerURL(),
IDPCertificateAuthorityData: keypair.Server.CACertBase64,
})
defer os.Remove(kubeConfigFilename)
runStandalone(t, ctx, standaloneConfig{
issuerURL: sv.IssuerURL(),
kubeConfigFilename: kubeConfigFilename,
@@ -249,13 +241,10 @@ func TestStandalone(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
Issuer: sv.IssuerURL(),
})
defer os.Remove(kubeConfigFilename)
setenv(t, "KUBECONFIG", kubeConfigFilename+string(os.PathListSeparator)+"kubeconfig/testdata/dummy.yaml")
defer unsetenv(t, "KUBECONFIG")
t.Setenv("KUBECONFIG", kubeConfigFilename+string(os.PathListSeparator)+"kubeconfig/testdata/dummy.yaml")
runStandalone(t, ctx, standaloneConfig{
issuerURL: sv.IssuerURL(),
httpDriver: httpdriver.New(ctx, t, httpdriver.Option{}),
@@ -280,12 +269,10 @@ func TestStandalone(t *testing.T) {
IDTokenExpiry: now.Add(time.Hour),
},
})
defer sv.Shutdown(t, ctx)
kubeConfigFilename := kubeconfig.Create(t, &kubeconfig.Values{
Issuer: sv.IssuerURL(),
ExtraScopes: "profile,groups",
})
defer os.Remove(kubeConfigFilename)
runStandalone(t, ctx, standaloneConfig{
issuerURL: sv.IssuerURL(),
kubeConfigFilename: kubeConfigFilename,
@@ -318,17 +305,3 @@ func runStandalone(t *testing.T, ctx context.Context, cfg standaloneConfig) {
t.Errorf("exit status wants 0 but %d", exitCode)
}
}
func setenv(t *testing.T, key, value string) {
t.Helper()
if err := os.Setenv(key, value); err != nil {
t.Fatalf("Could not set the env var %s=%s: %s", key, value, err)
}
}
func unsetenv(t *testing.T, key string) {
t.Helper()
if err := os.Unsetenv(key); err != nil {
t.Fatalf("Could not unset the env var %s: %s", key, err)
}
}

View File

@@ -1,47 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/int128/kubelogin/pkg/adaptors/browser (interfaces: Interface)
// Package mock_browser is a generated GoMock package.
package mock_browser
import (
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
// MockInterface is a mock of Interface interface.
type MockInterface struct {
ctrl *gomock.Controller
recorder *MockInterfaceMockRecorder
}
// MockInterfaceMockRecorder is the mock recorder for MockInterface.
type MockInterfaceMockRecorder struct {
mock *MockInterface
}
// NewMockInterface creates a new mock instance.
func NewMockInterface(ctrl *gomock.Controller) *MockInterface {
mock := &MockInterface{ctrl: ctrl}
mock.recorder = &MockInterfaceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
return m.recorder
}
// Open mocks base method.
func (m *MockInterface) Open(arg0 string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Open", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Open indicates an expected call of Open.
func (mr *MockInterfaceMockRecorder) Open(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Open", reflect.TypeOf((*MockInterface)(nil).Open), arg0)
}

View File

@@ -1,71 +0,0 @@
// Package certpool provides loading certificates from files or base64 encoded string.
package certpool
import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"io/ioutil"
"github.com/google/wire"
"golang.org/x/xerrors"
)
//go:generate mockgen -destination mock_certpool/mock_certpool.go github.com/int128/kubelogin/pkg/adaptors/certpool Interface
// Set provides an implementation and interface.
var Set = wire.NewSet(
wire.Value(NewFunc(New)),
wire.Struct(new(CertPool), "*"),
wire.Bind(new(Interface), new(*CertPool)),
)
type NewFunc func() Interface
// New returns an instance which implements the Interface.
func New() Interface {
return &CertPool{pool: x509.NewCertPool()}
}
type Interface interface {
AddFile(filename string) error
AddBase64Encoded(s string) error
SetRootCAs(cfg *tls.Config)
}
// CertPool represents a pool of certificates.
type CertPool struct {
pool *x509.CertPool
}
// SetRootCAs sets cfg.RootCAs if it has any certificate.
// Otherwise do nothing.
func (p *CertPool) SetRootCAs(cfg *tls.Config) {
if len(p.pool.Subjects()) > 0 {
cfg.RootCAs = p.pool
}
}
// AddFile loads the certificate from the file.
func (p *CertPool) AddFile(filename string) error {
b, err := ioutil.ReadFile(filename)
if err != nil {
return xerrors.Errorf("could not read %s: %w", filename, err)
}
if !p.pool.AppendCertsFromPEM(b) {
return xerrors.Errorf("could not append certificate from %s", filename)
}
return nil
}
// AddBase64Encoded loads the certificate from the base64 encoded string.
func (p *CertPool) AddBase64Encoded(s string) error {
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return xerrors.Errorf("could not decode base64: %w", err)
}
if !p.pool.AppendCertsFromPEM(b) {
return xerrors.Errorf("could not append certificate")
}
return nil
}

View File

@@ -1,58 +0,0 @@
package certpool
import (
"crypto/tls"
"io/ioutil"
"testing"
)
func TestCertPool_AddFile(t *testing.T) {
t.Run("Valid", func(t *testing.T) {
p := New()
if err := p.AddFile("testdata/ca1.crt"); err != nil {
t.Errorf("AddFile error: %s", err)
}
var cfg tls.Config
p.SetRootCAs(&cfg)
if n := len(cfg.RootCAs.Subjects()); n != 1 {
t.Errorf("n wants 1 but was %d", n)
}
})
t.Run("Invalid", func(t *testing.T) {
p := New()
err := p.AddFile("testdata/Makefile")
if err == nil {
t.Errorf("AddFile wants an error but was nil")
}
})
}
func TestCertPool_AddBase64Encoded(t *testing.T) {
p := New()
if err := p.AddBase64Encoded(readFile(t, "testdata/ca2.crt.base64")); err != nil {
t.Errorf("AddBase64Encoded error: %s", err)
}
var cfg tls.Config
p.SetRootCAs(&cfg)
if n := len(cfg.RootCAs.Subjects()); n != 1 {
t.Errorf("n wants 1 but was %d", n)
}
}
func TestCertPool_SetRootCAs(t *testing.T) {
p := New()
var cfg tls.Config
p.SetRootCAs(&cfg)
if cfg.RootCAs != nil {
t.Errorf("cfg.RootCAs wants nil but was %+v", cfg.RootCAs)
}
}
func readFile(t *testing.T, filename string) string {
t.Helper()
b, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("ReadFile error: %s", err)
}
return string(b)
}

View File

@@ -1,74 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/int128/kubelogin/pkg/adaptors/certpool (interfaces: Interface)
// Package mock_certpool is a generated GoMock package.
package mock_certpool
import (
tls "crypto/tls"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
// MockInterface is a mock of Interface interface.
type MockInterface struct {
ctrl *gomock.Controller
recorder *MockInterfaceMockRecorder
}
// MockInterfaceMockRecorder is the mock recorder for MockInterface.
type MockInterfaceMockRecorder struct {
mock *MockInterface
}
// NewMockInterface creates a new mock instance.
func NewMockInterface(ctrl *gomock.Controller) *MockInterface {
mock := &MockInterface{ctrl: ctrl}
mock.recorder = &MockInterfaceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
return m.recorder
}
// AddBase64Encoded mocks base method.
func (m *MockInterface) AddBase64Encoded(arg0 string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddBase64Encoded", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// AddBase64Encoded indicates an expected call of AddBase64Encoded.
func (mr *MockInterfaceMockRecorder) AddBase64Encoded(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBase64Encoded", reflect.TypeOf((*MockInterface)(nil).AddBase64Encoded), arg0)
}
// AddFile mocks base method.
func (m *MockInterface) AddFile(arg0 string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddFile", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// AddFile indicates an expected call of AddFile.
func (mr *MockInterfaceMockRecorder) AddFile(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddFile", reflect.TypeOf((*MockInterface)(nil).AddFile), arg0)
}
// SetRootCAs mocks base method.
func (m *MockInterface) SetRootCAs(arg0 *tls.Config) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetRootCAs", arg0)
}
// SetRootCAs indicates an expected call of SetRootCAs.
func (mr *MockInterfaceMockRecorder) SetRootCAs(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetRootCAs", reflect.TypeOf((*MockInterface)(nil).SetRootCAs), arg0)
}

View File

@@ -1,399 +0,0 @@
package cmd
import (
"context"
"testing"
"time"
"github.com/golang/mock/gomock"
"github.com/int128/kubelogin/pkg/testing/logger"
"github.com/int128/kubelogin/pkg/usecases/authentication"
"github.com/int128/kubelogin/pkg/usecases/authentication/authcode"
"github.com/int128/kubelogin/pkg/usecases/authentication/ropc"
"github.com/int128/kubelogin/pkg/usecases/credentialplugin"
"github.com/int128/kubelogin/pkg/usecases/credentialplugin/mock_credentialplugin"
"github.com/int128/kubelogin/pkg/usecases/standalone"
"github.com/int128/kubelogin/pkg/usecases/standalone/mock_standalone"
)
func TestCmd_Run(t *testing.T) {
const executable = "kubelogin"
const version = "HEAD"
t.Run("root", func(t *testing.T) {
tests := map[string]struct {
args []string
in standalone.Input
}{
"Defaults": {
args: []string{executable},
in: standalone.Input{
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: defaultListenAddress,
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
},
"when --listen-port is set, it should convert the port to address": {
args: []string{
executable,
"--listen-port", "10080",
"--listen-port", "20080",
},
in: standalone.Input{
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: []string{"127.0.0.1:10080", "127.0.0.1:20080"},
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
},
"when --listen-port is set, it should ignore --listen-address flags": {
args: []string{
executable,
"--listen-port", "10080",
"--listen-port", "20080",
"--listen-address", "127.0.0.1:30080",
"--listen-address", "127.0.0.1:40080",
},
in: standalone.Input{
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: []string{"127.0.0.1:10080", "127.0.0.1:20080"},
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
},
"FullOptions": {
args: []string{executable,
"--kubeconfig", "/path/to/kubeconfig",
"--context", "hello.k8s.local",
"--user", "google",
"--certificate-authority", "/path/to/cacert",
"--certificate-authority-data", "BASE64ENCODED",
"--insecure-skip-tls-verify",
"-v1",
"--grant-type", "authcode",
"--listen-address", "127.0.0.1:10080",
"--listen-address", "127.0.0.1:20080",
"--skip-open-browser",
"--authentication-timeout-sec", "10",
"--local-server-cert", "/path/to/local-server-cert",
"--local-server-key", "/path/to/local-server-key",
"--open-url-after-authentication", "https://example.com/success.html",
"--username", "USER",
"--password", "PASS",
},
in: standalone.Input{
KubeconfigFilename: "/path/to/kubeconfig",
KubeconfigContext: "hello.k8s.local",
KubeconfigUser: "google",
CACertFilename: "/path/to/cacert",
CACertData: "BASE64ENCODED",
SkipTLSVerify: true,
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: []string{"127.0.0.1:10080", "127.0.0.1:20080"},
SkipOpenBrowser: true,
AuthenticationTimeout: 10 * time.Second,
LocalServerCertFile: "/path/to/local-server-cert",
LocalServerKeyFile: "/path/to/local-server-key",
OpenURLAfterAuthentication: "https://example.com/success.html",
RedirectURLHostname: "localhost",
},
},
},
},
"GrantType=authcode-keyboard": {
args: []string{executable,
"--grant-type", "authcode-keyboard",
},
in: standalone.Input{
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeKeyboardOption: &authcode.KeyboardOption{},
},
},
},
"GrantType=password": {
args: []string{executable,
"--grant-type", "password",
"--listen-address", "127.0.0.1:10080",
"--listen-address", "127.0.0.1:20080",
"--username", "USER",
"--password", "PASS",
},
in: standalone.Input{
GrantOptionSet: authentication.GrantOptionSet{
ROPCOption: &ropc.Option{
Username: "USER",
Password: "PASS",
},
},
},
},
"GrantType=auto": {
args: []string{executable,
"--listen-address", "127.0.0.1:10080",
"--listen-address", "127.0.0.1:20080",
"--username", "USER",
"--password", "PASS",
},
in: standalone.Input{
GrantOptionSet: authentication.GrantOptionSet{
ROPCOption: &ropc.Option{
Username: "USER",
Password: "PASS",
},
},
},
},
}
for name, c := range tests {
t.Run(name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.TODO()
mockStandalone := mock_standalone.NewMockInterface(ctrl)
mockStandalone.EXPECT().
Do(ctx, c.in)
cmd := Cmd{
Root: &Root{
Standalone: mockStandalone,
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(ctx, c.args, version)
if exitCode != 0 {
t.Errorf("exitCode wants 0 but %d", exitCode)
}
})
}
t.Run("TooManyArgs", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
cmd := Cmd{
Root: &Root{
Standalone: mock_standalone.NewMockInterface(ctrl),
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(context.TODO(), []string{executable, "some"}, version)
if exitCode != 1 {
t.Errorf("exitCode wants 1 but %d", exitCode)
}
})
})
t.Run("get-token", func(t *testing.T) {
tests := map[string]struct {
args []string
in credentialplugin.Input
}{
"Defaults": {
args: []string{executable,
"get-token",
"--oidc-issuer-url", "https://issuer.example.com",
"--oidc-client-id", "YOUR_CLIENT_ID",
},
in: credentialplugin.Input{
TokenCacheDir: defaultTokenCacheDir,
IssuerURL: "https://issuer.example.com",
ClientID: "YOUR_CLIENT_ID",
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: []string{"127.0.0.1:8000", "127.0.0.1:18000"},
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
},
"FullOptions": {
args: []string{executable,
"get-token",
"--oidc-issuer-url", "https://issuer.example.com",
"--oidc-client-id", "YOUR_CLIENT_ID",
"--oidc-client-secret", "YOUR_CLIENT_SECRET",
"--oidc-extra-scope", "email",
"--oidc-extra-scope", "profile",
"--certificate-authority", "/path/to/cacert",
"--certificate-authority-data", "BASE64ENCODED",
"--insecure-skip-tls-verify",
"-v1",
"--grant-type", "authcode",
"--listen-address", "127.0.0.1:10080",
"--listen-address", "127.0.0.1:20080",
"--skip-open-browser",
"--authentication-timeout-sec", "10",
"--local-server-cert", "/path/to/local-server-cert",
"--local-server-key", "/path/to/local-server-key",
"--open-url-after-authentication", "https://example.com/success.html",
"--oidc-auth-request-extra-params", "ttl=86400",
"--oidc-auth-request-extra-params", "reauth=true",
"--username", "USER",
"--password", "PASS",
},
in: credentialplugin.Input{
TokenCacheDir: defaultTokenCacheDir,
IssuerURL: "https://issuer.example.com",
ClientID: "YOUR_CLIENT_ID",
ClientSecret: "YOUR_CLIENT_SECRET",
ExtraScopes: []string{"email", "profile"},
CACertFilename: "/path/to/cacert",
CACertData: "BASE64ENCODED",
SkipTLSVerify: true,
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: []string{"127.0.0.1:10080", "127.0.0.1:20080"},
SkipOpenBrowser: true,
AuthenticationTimeout: 10 * time.Second,
LocalServerCertFile: "/path/to/local-server-cert",
LocalServerKeyFile: "/path/to/local-server-key",
OpenURLAfterAuthentication: "https://example.com/success.html",
RedirectURLHostname: "localhost",
AuthRequestExtraParams: map[string]string{"ttl": "86400", "reauth": "true"},
},
},
},
},
"GrantType=authcode-keyboard": {
args: []string{executable,
"get-token",
"--oidc-issuer-url", "https://issuer.example.com",
"--oidc-client-id", "YOUR_CLIENT_ID",
"--grant-type", "authcode-keyboard",
"--oidc-auth-request-extra-params", "ttl=86400",
},
in: credentialplugin.Input{
TokenCacheDir: defaultTokenCacheDir,
IssuerURL: "https://issuer.example.com",
ClientID: "YOUR_CLIENT_ID",
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeKeyboardOption: &authcode.KeyboardOption{
AuthRequestExtraParams: map[string]string{"ttl": "86400"},
},
},
},
},
"GrantType=password": {
args: []string{executable,
"get-token",
"--oidc-issuer-url", "https://issuer.example.com",
"--oidc-client-id", "YOUR_CLIENT_ID",
"--grant-type", "password",
"--listen-address", "127.0.0.1:10080",
"--listen-address", "127.0.0.1:20080",
"--username", "USER",
"--password", "PASS",
},
in: credentialplugin.Input{
TokenCacheDir: defaultTokenCacheDir,
IssuerURL: "https://issuer.example.com",
ClientID: "YOUR_CLIENT_ID",
GrantOptionSet: authentication.GrantOptionSet{
ROPCOption: &ropc.Option{
Username: "USER",
Password: "PASS",
},
},
},
},
"GrantType=auto": {
args: []string{executable,
"get-token",
"--oidc-issuer-url", "https://issuer.example.com",
"--oidc-client-id", "YOUR_CLIENT_ID",
"--listen-address", "127.0.0.1:10080",
"--listen-address", "127.0.0.1:20080",
"--username", "USER",
"--password", "PASS",
},
in: credentialplugin.Input{
TokenCacheDir: defaultTokenCacheDir,
IssuerURL: "https://issuer.example.com",
ClientID: "YOUR_CLIENT_ID",
GrantOptionSet: authentication.GrantOptionSet{
ROPCOption: &ropc.Option{
Username: "USER",
Password: "PASS",
},
},
},
},
}
for name, c := range tests {
t.Run(name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.TODO()
getToken := mock_credentialplugin.NewMockInterface(ctrl)
getToken.EXPECT().
Do(ctx, c.in)
cmd := Cmd{
Root: &Root{
Logger: logger.New(t),
},
GetToken: &GetToken{
GetToken: getToken,
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(ctx, c.args, version)
if exitCode != 0 {
t.Errorf("exitCode wants 0 but %d", exitCode)
}
})
}
t.Run("MissingMandatoryOptions", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.TODO()
cmd := Cmd{
Root: &Root{
Logger: logger.New(t),
},
GetToken: &GetToken{
GetToken: mock_credentialplugin.NewMockInterface(ctrl),
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(ctx, []string{executable, "get-token"}, version)
if exitCode != 1 {
t.Errorf("exitCode wants 1 but %d", exitCode)
}
})
t.Run("TooManyArgs", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := context.TODO()
cmd := Cmd{
Root: &Root{
Logger: logger.New(t),
},
GetToken: &GetToken{
GetToken: mock_credentialplugin.NewMockInterface(ctrl),
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(ctx, []string{executable, "get-token", "foo"}, version)
if exitCode != 1 {
t.Errorf("exitCode wants 1 but %d", exitCode)
}
})
})
}

View File

@@ -1,15 +0,0 @@
package cmd
import "github.com/spf13/pflag"
type tlsOptions struct {
CACertFilename string
CACertData string
SkipTLSVerify bool
}
func (o *tlsOptions) addFlags(f *pflag.FlagSet) {
f.StringVar(&o.CACertFilename, "certificate-authority", "", "Path to a cert file for the certificate authority")
f.StringVar(&o.CACertData, "certificate-authority-data", "", "Base64 encoded cert for the certificate authority")
f.BoolVar(&o.SkipTLSVerify, "insecure-skip-tls-verify", false, "If set, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure")
}

View File

@@ -1,48 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/int128/kubelogin/pkg/adaptors/credentialpluginwriter (interfaces: Interface)
// Package mock_credentialpluginwriter is a generated GoMock package.
package mock_credentialpluginwriter
import (
gomock "github.com/golang/mock/gomock"
credentialpluginwriter "github.com/int128/kubelogin/pkg/adaptors/credentialpluginwriter"
reflect "reflect"
)
// MockInterface is a mock of Interface interface.
type MockInterface struct {
ctrl *gomock.Controller
recorder *MockInterfaceMockRecorder
}
// MockInterfaceMockRecorder is the mock recorder for MockInterface.
type MockInterfaceMockRecorder struct {
mock *MockInterface
}
// NewMockInterface creates a new mock instance.
func NewMockInterface(ctrl *gomock.Controller) *MockInterface {
mock := &MockInterface{ctrl: ctrl}
mock.recorder = &MockInterfaceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
return m.recorder
}
// Write mocks base method.
func (m *MockInterface) Write(arg0 credentialpluginwriter.Output) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Write", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Write indicates an expected call of Write.
func (mr *MockInterfaceMockRecorder) Write(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*MockInterface)(nil).Write), arg0)
}

View File

@@ -1,63 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/int128/kubelogin/pkg/adaptors/kubeconfig (interfaces: Interface)
// Package mock_kubeconfig is a generated GoMock package.
package mock_kubeconfig
import (
gomock "github.com/golang/mock/gomock"
kubeconfig "github.com/int128/kubelogin/pkg/adaptors/kubeconfig"
reflect "reflect"
)
// MockInterface is a mock of Interface interface.
type MockInterface struct {
ctrl *gomock.Controller
recorder *MockInterfaceMockRecorder
}
// MockInterfaceMockRecorder is the mock recorder for MockInterface.
type MockInterfaceMockRecorder struct {
mock *MockInterface
}
// NewMockInterface creates a new mock instance.
func NewMockInterface(ctrl *gomock.Controller) *MockInterface {
mock := &MockInterface{ctrl: ctrl}
mock.recorder = &MockInterfaceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
return m.recorder
}
// GetCurrentAuthProvider mocks base method.
func (m *MockInterface) GetCurrentAuthProvider(arg0 string, arg1 kubeconfig.ContextName, arg2 kubeconfig.UserName) (*kubeconfig.AuthProvider, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetCurrentAuthProvider", arg0, arg1, arg2)
ret0, _ := ret[0].(*kubeconfig.AuthProvider)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetCurrentAuthProvider indicates an expected call of GetCurrentAuthProvider.
func (mr *MockInterfaceMockRecorder) GetCurrentAuthProvider(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentAuthProvider", reflect.TypeOf((*MockInterface)(nil).GetCurrentAuthProvider), arg0, arg1, arg2)
}
// UpdateAuthProvider mocks base method.
func (m *MockInterface) UpdateAuthProvider(arg0 *kubeconfig.AuthProvider) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateAuthProvider", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// UpdateAuthProvider indicates an expected call of UpdateAuthProvider.
func (mr *MockInterfaceMockRecorder) UpdateAuthProvider(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateAuthProvider", reflect.TypeOf((*MockInterface)(nil).UpdateAuthProvider), arg0)
}

View File

@@ -1,93 +0,0 @@
// Package oidcclient provides a client of OpenID Connect.
package oidcclient
import (
"context"
"crypto/tls"
"fmt"
"net/http"
"github.com/coreos/go-oidc"
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/adaptors/certpool"
"github.com/int128/kubelogin/pkg/adaptors/clock"
"github.com/int128/kubelogin/pkg/adaptors/logger"
"github.com/int128/kubelogin/pkg/adaptors/oidcclient/logging"
"golang.org/x/oauth2"
"golang.org/x/xerrors"
)
var Set = wire.NewSet(
wire.Struct(new(Factory), "*"),
wire.Bind(new(FactoryInterface), new(*Factory)),
)
type FactoryInterface interface {
New(ctx context.Context, config Config) (Interface, error)
}
// Config represents a configuration of OpenID Connect client.
type Config struct {
IssuerURL string
ClientID string
ClientSecret string
ExtraScopes []string // optional
CertPool certpool.Interface
SkipTLSVerify bool
}
type Factory struct {
Clock clock.Interface
Logger logger.Interface
}
// New returns an instance of adaptors.Interface with the given configuration.
func (f *Factory) New(ctx context.Context, config Config) (Interface, error) {
var tlsConfig tls.Config
tlsConfig.InsecureSkipVerify = config.SkipTLSVerify
config.CertPool.SetRootCAs(&tlsConfig)
baseTransport := &http.Transport{
TLSClientConfig: &tlsConfig,
Proxy: http.ProxyFromEnvironment,
}
loggingTransport := &logging.Transport{
Base: baseTransport,
Logger: f.Logger,
}
httpClient := &http.Client{
Transport: loggingTransport,
}
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
provider, err := oidc.NewProvider(ctx, config.IssuerURL)
if err != nil {
return nil, xerrors.Errorf("oidc discovery error: %w", err)
}
supportedPKCEMethods, err := extractSupportedPKCEMethods(provider)
if err != nil {
return nil, xerrors.Errorf("could not determine supported PKCE methods: %w", err)
}
return &client{
httpClient: httpClient,
provider: provider,
oauth2Config: oauth2.Config{
Endpoint: provider.Endpoint(),
ClientID: config.ClientID,
ClientSecret: config.ClientSecret,
Scopes: append(config.ExtraScopes, oidc.ScopeOpenID),
},
clock: f.Clock,
logger: f.Logger,
supportedPKCEMethods: supportedPKCEMethods,
}, nil
}
func extractSupportedPKCEMethods(provider *oidc.Provider) ([]string, error) {
var d struct {
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
}
if err := provider.Claims(&d); err != nil {
return nil, fmt.Errorf("invalid discovery document: %w", err)
}
return d.CodeChallengeMethodsSupported, nil
}

View File

@@ -1,124 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/int128/kubelogin/pkg/adaptors/oidcclient (interfaces: Interface)
// Package mock_oidcclient is a generated GoMock package.
package mock_oidcclient
import (
context "context"
gomock "github.com/golang/mock/gomock"
oidcclient "github.com/int128/kubelogin/pkg/adaptors/oidcclient"
oidc "github.com/int128/kubelogin/pkg/oidc"
reflect "reflect"
)
// MockInterface is a mock of Interface interface.
type MockInterface struct {
ctrl *gomock.Controller
recorder *MockInterfaceMockRecorder
}
// MockInterfaceMockRecorder is the mock recorder for MockInterface.
type MockInterfaceMockRecorder struct {
mock *MockInterface
}
// NewMockInterface creates a new mock instance.
func NewMockInterface(ctrl *gomock.Controller) *MockInterface {
mock := &MockInterface{ctrl: ctrl}
mock.recorder = &MockInterfaceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
return m.recorder
}
// ExchangeAuthCode mocks base method.
func (m *MockInterface) ExchangeAuthCode(arg0 context.Context, arg1 oidcclient.ExchangeAuthCodeInput) (*oidc.TokenSet, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ExchangeAuthCode", arg0, arg1)
ret0, _ := ret[0].(*oidc.TokenSet)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ExchangeAuthCode indicates an expected call of ExchangeAuthCode.
func (mr *MockInterfaceMockRecorder) ExchangeAuthCode(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExchangeAuthCode", reflect.TypeOf((*MockInterface)(nil).ExchangeAuthCode), arg0, arg1)
}
// GetAuthCodeURL mocks base method.
func (m *MockInterface) GetAuthCodeURL(arg0 oidcclient.AuthCodeURLInput) string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAuthCodeURL", arg0)
ret0, _ := ret[0].(string)
return ret0
}
// GetAuthCodeURL indicates an expected call of GetAuthCodeURL.
func (mr *MockInterfaceMockRecorder) GetAuthCodeURL(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAuthCodeURL", reflect.TypeOf((*MockInterface)(nil).GetAuthCodeURL), arg0)
}
// GetTokenByAuthCode mocks base method.
func (m *MockInterface) GetTokenByAuthCode(arg0 context.Context, arg1 oidcclient.GetTokenByAuthCodeInput, arg2 chan<- string) (*oidc.TokenSet, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetTokenByAuthCode", arg0, arg1, arg2)
ret0, _ := ret[0].(*oidc.TokenSet)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetTokenByAuthCode indicates an expected call of GetTokenByAuthCode.
func (mr *MockInterfaceMockRecorder) GetTokenByAuthCode(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTokenByAuthCode", reflect.TypeOf((*MockInterface)(nil).GetTokenByAuthCode), arg0, arg1, arg2)
}
// GetTokenByROPC mocks base method.
func (m *MockInterface) GetTokenByROPC(arg0 context.Context, arg1, arg2 string) (*oidc.TokenSet, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetTokenByROPC", arg0, arg1, arg2)
ret0, _ := ret[0].(*oidc.TokenSet)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetTokenByROPC indicates an expected call of GetTokenByROPC.
func (mr *MockInterfaceMockRecorder) GetTokenByROPC(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTokenByROPC", reflect.TypeOf((*MockInterface)(nil).GetTokenByROPC), arg0, arg1, arg2)
}
// Refresh mocks base method.
func (m *MockInterface) Refresh(arg0 context.Context, arg1 string) (*oidc.TokenSet, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Refresh", arg0, arg1)
ret0, _ := ret[0].(*oidc.TokenSet)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Refresh indicates an expected call of Refresh.
func (mr *MockInterfaceMockRecorder) Refresh(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Refresh", reflect.TypeOf((*MockInterface)(nil).Refresh), arg0, arg1)
}
// SupportedPKCEMethods mocks base method.
func (m *MockInterface) SupportedPKCEMethods() []string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SupportedPKCEMethods")
ret0, _ := ret[0].([]string)
return ret0
}
// SupportedPKCEMethods indicates an expected call of SupportedPKCEMethods.
func (mr *MockInterfaceMockRecorder) SupportedPKCEMethods() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SupportedPKCEMethods", reflect.TypeOf((*MockInterface)(nil).SupportedPKCEMethods))
}

View File

@@ -1,63 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/int128/kubelogin/pkg/adaptors/reader (interfaces: Interface)
// Package mock_reader is a generated GoMock package.
package mock_reader
import (
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
// MockInterface is a mock of Interface interface.
type MockInterface struct {
ctrl *gomock.Controller
recorder *MockInterfaceMockRecorder
}
// MockInterfaceMockRecorder is the mock recorder for MockInterface.
type MockInterfaceMockRecorder struct {
mock *MockInterface
}
// NewMockInterface creates a new mock instance.
func NewMockInterface(ctrl *gomock.Controller) *MockInterface {
mock := &MockInterface{ctrl: ctrl}
mock.recorder = &MockInterfaceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
return m.recorder
}
// ReadPassword mocks base method.
func (m *MockInterface) ReadPassword(arg0 string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ReadPassword", arg0)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ReadPassword indicates an expected call of ReadPassword.
func (mr *MockInterfaceMockRecorder) ReadPassword(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadPassword", reflect.TypeOf((*MockInterface)(nil).ReadPassword), arg0)
}
// ReadString mocks base method.
func (m *MockInterface) ReadString(arg0 string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ReadString", arg0)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ReadString indicates an expected call of ReadString.
func (mr *MockInterfaceMockRecorder) ReadString(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadString", reflect.TypeOf((*MockInterface)(nil).ReadString), arg0)
}

View File

@@ -1,63 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/int128/kubelogin/pkg/adaptors/tokencache (interfaces: Interface)
// Package mock_tokencache is a generated GoMock package.
package mock_tokencache
import (
gomock "github.com/golang/mock/gomock"
tokencache "github.com/int128/kubelogin/pkg/adaptors/tokencache"
reflect "reflect"
)
// MockInterface is a mock of Interface interface.
type MockInterface struct {
ctrl *gomock.Controller
recorder *MockInterfaceMockRecorder
}
// MockInterfaceMockRecorder is the mock recorder for MockInterface.
type MockInterfaceMockRecorder struct {
mock *MockInterface
}
// NewMockInterface creates a new mock instance.
func NewMockInterface(ctrl *gomock.Controller) *MockInterface {
mock := &MockInterface{ctrl: ctrl}
mock.recorder = &MockInterfaceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder {
return m.recorder
}
// FindByKey mocks base method.
func (m *MockInterface) FindByKey(arg0 string, arg1 tokencache.Key) (*tokencache.Value, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FindByKey", arg0, arg1)
ret0, _ := ret[0].(*tokencache.Value)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FindByKey indicates an expected call of FindByKey.
func (mr *MockInterfaceMockRecorder) FindByKey(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByKey", reflect.TypeOf((*MockInterface)(nil).FindByKey), arg0, arg1)
}
// Save mocks base method.
func (m *MockInterface) Save(arg0 string, arg1 tokencache.Key, arg2 tokencache.Value) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Save", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
return ret0
}
// Save indicates an expected call of Save.
func (mr *MockInterfaceMockRecorder) Save(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Save", reflect.TypeOf((*MockInterface)(nil).Save), arg0, arg1, arg2)
}

View File

@@ -1,97 +0,0 @@
package tokencache
import (
"crypto/sha256"
"encoding/gob"
"encoding/hex"
"encoding/json"
"os"
"path/filepath"
"github.com/google/wire"
"golang.org/x/xerrors"
)
//go:generate mockgen -destination mock_tokencache/mock_tokencache.go github.com/int128/kubelogin/pkg/adaptors/tokencache Interface
// Set provides an implementation and interface for Kubeconfig.
var Set = wire.NewSet(
wire.Struct(new(Repository), "*"),
wire.Bind(new(Interface), new(*Repository)),
)
type Interface interface {
FindByKey(dir string, key Key) (*Value, error)
Save(dir string, key Key, value Value) error
}
// Key represents a key of a token cache.
type Key struct {
IssuerURL string
ClientID string
ClientSecret string
ExtraScopes []string
CACertFilename string
CACertData string
SkipTLSVerify bool
}
// Value represents a value of a token cache.
type Value struct {
IDToken string `json:"id_token,omitempty"`
RefreshToken string `json:"refresh_token,omitempty"`
}
// Repository provides access to the token cache on the local filesystem.
// Filename of a token cache is sha256 digest of the issuer, zero-character and client ID.
type Repository struct{}
func (r *Repository) FindByKey(dir string, key Key) (*Value, error) {
filename, err := computeFilename(key)
if err != nil {
return nil, xerrors.Errorf("could not compute the key: %w", err)
}
p := filepath.Join(dir, filename)
f, err := os.Open(p)
if err != nil {
return nil, xerrors.Errorf("could not open file %s: %w", p, err)
}
defer f.Close()
d := json.NewDecoder(f)
var c Value
if err := d.Decode(&c); err != nil {
return nil, xerrors.Errorf("invalid json file %s: %w", p, err)
}
return &c, nil
}
func (r *Repository) Save(dir string, key Key, value Value) error {
if err := os.MkdirAll(dir, 0700); err != nil {
return xerrors.Errorf("could not create directory %s: %w", dir, err)
}
filename, err := computeFilename(key)
if err != nil {
return xerrors.Errorf("could not compute the key: %w", err)
}
p := filepath.Join(dir, filename)
f, err := os.OpenFile(p, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return xerrors.Errorf("could not create file %s: %w", p, err)
}
defer f.Close()
e := json.NewEncoder(f)
if err := e.Encode(&value); err != nil {
return xerrors.Errorf("json encode error: %w", err)
}
return nil
}
func computeFilename(key Key) (string, error) {
s := sha256.New()
e := gob.NewEncoder(s)
if err := e.Encode(&key); err != nil {
return "", xerrors.Errorf("could not encode the key: %w", err)
}
h := hex.EncodeToString(s.Sum(nil))
return h, nil
}

View File

@@ -9,7 +9,6 @@ import (
"github.com/int128/kubelogin/pkg/usecases/authentication/authcode"
"github.com/int128/kubelogin/pkg/usecases/authentication/ropc"
"github.com/spf13/pflag"
"golang.org/x/xerrors"
)
type authenticationOptions struct {
@@ -18,6 +17,7 @@ type authenticationOptions struct {
ListenPort []int // deprecated
AuthenticationTimeoutSec int
SkipOpenBrowser bool
BrowserCommand string
LocalServerCertFile string
LocalServerKeyFile string
OpenURLAfterAuthentication string
@@ -58,6 +58,7 @@ func (o *authenticationOptions) addFlags(f *pflag.FlagSet) {
panic(err)
}
f.BoolVar(&o.SkipOpenBrowser, "skip-open-browser", false, "[authcode] Do not open the browser automatically")
f.StringVar(&o.BrowserCommand, "browser-command", "", "[authcode] Command to open the browser")
f.IntVar(&o.AuthenticationTimeoutSec, "authentication-timeout-sec", defaultAuthenticationTimeoutSec, "[authcode] Timeout of authentication in seconds")
f.StringVar(&o.LocalServerCertFile, "local-server-cert", "", "[authcode] Certificate path for the local server")
f.StringVar(&o.LocalServerKeyFile, "local-server-key", "", "[authcode] Certificate key path for the local server")
@@ -68,12 +69,18 @@ func (o *authenticationOptions) addFlags(f *pflag.FlagSet) {
f.StringVar(&o.Password, "password", "", "[password] Password for resource owner password credentials grant")
}
func (o *authenticationOptions) expandHomedir() {
o.LocalServerCertFile = expandHomedir(o.LocalServerCertFile)
o.LocalServerKeyFile = expandHomedir(o.LocalServerKeyFile)
}
func (o *authenticationOptions) grantOptionSet() (s authentication.GrantOptionSet, err error) {
switch {
case o.GrantType == "authcode" || (o.GrantType == "auto" && o.Username == ""):
s.AuthCodeBrowserOption = &authcode.BrowserOption{
BindAddress: o.determineListenAddress(),
SkipOpenBrowser: o.SkipOpenBrowser,
BrowserCommand: o.BrowserCommand,
AuthenticationTimeout: time.Duration(o.AuthenticationTimeoutSec) * time.Second,
LocalServerCertFile: o.LocalServerCertFile,
LocalServerKeyFile: o.LocalServerKeyFile,
@@ -91,7 +98,7 @@ func (o *authenticationOptions) grantOptionSet() (s authentication.GrantOptionSe
Password: o.Password,
}
default:
err = xerrors.Errorf("grant-type must be one of (%s)", allGrantType)
err = fmt.Errorf("grant-type must be one of (%s)", allGrantType)
}
return
}

View File

@@ -0,0 +1,143 @@
package cmd
import (
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/int128/kubelogin/pkg/usecases/authentication"
"github.com/int128/kubelogin/pkg/usecases/authentication/authcode"
"github.com/int128/kubelogin/pkg/usecases/authentication/ropc"
"github.com/spf13/pflag"
)
func Test_authenticationOptions_grantOptionSet(t *testing.T) {
tests := map[string]struct {
args []string
want authentication.GrantOptionSet
}{
"NoFlag": {
want: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: defaultListenAddress,
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
"FullOptions": {
args: []string{
"--grant-type", "authcode",
"--listen-address", "127.0.0.1:10080",
"--listen-address", "127.0.0.1:20080",
"--skip-open-browser",
"--browser-command", "firefox",
"--authentication-timeout-sec", "10",
"--local-server-cert", "/path/to/local-server-cert",
"--local-server-key", "/path/to/local-server-key",
"--open-url-after-authentication", "https://example.com/success.html",
"--oidc-redirect-url-hostname", "example",
"--oidc-auth-request-extra-params", "ttl=86400",
"--oidc-auth-request-extra-params", "reauth=true",
"--username", "USER",
"--password", "PASS",
},
want: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: []string{"127.0.0.1:10080", "127.0.0.1:20080"},
SkipOpenBrowser: true,
BrowserCommand: "firefox",
AuthenticationTimeout: 10 * time.Second,
LocalServerCertFile: "/path/to/local-server-cert",
LocalServerKeyFile: "/path/to/local-server-key",
OpenURLAfterAuthentication: "https://example.com/success.html",
RedirectURLHostname: "example",
AuthRequestExtraParams: map[string]string{"ttl": "86400", "reauth": "true"},
},
},
},
"when --listen-port is set, it should convert the port to address": {
args: []string{
"--listen-port", "10080",
"--listen-port", "20080",
},
want: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: []string{"127.0.0.1:10080", "127.0.0.1:20080"},
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
"when --listen-port is set, it should ignore --listen-address flags": {
args: []string{
"--listen-port", "10080",
"--listen-port", "20080",
"--listen-address", "127.0.0.1:30080",
"--listen-address", "127.0.0.1:40080",
},
want: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: []string{"127.0.0.1:10080", "127.0.0.1:20080"},
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
"GrantType=authcode-keyboard": {
args: []string{
"--grant-type", "authcode-keyboard",
},
want: authentication.GrantOptionSet{
AuthCodeKeyboardOption: &authcode.KeyboardOption{},
},
},
"GrantType=password": {
args: []string{
"--grant-type", "password",
"--listen-address", "127.0.0.1:10080",
"--listen-address", "127.0.0.1:20080",
"--username", "USER",
"--password", "PASS",
},
want: authentication.GrantOptionSet{
ROPCOption: &ropc.Option{
Username: "USER",
Password: "PASS",
},
},
},
"GrantType=auto": {
args: []string{
"--listen-address", "127.0.0.1:10080",
"--listen-address", "127.0.0.1:20080",
"--username", "USER",
"--password", "PASS",
},
want: authentication.GrantOptionSet{
ROPCOption: &ropc.Option{
Username: "USER",
Password: "PASS",
},
},
},
}
for name, c := range tests {
t.Run(name, func(t *testing.T) {
var o authenticationOptions
f := pflag.NewFlagSet("", pflag.ContinueOnError)
o.addFlags(f)
if err := f.Parse(c.args); err != nil {
t.Fatalf("Parse error: %s", err)
}
got, err := o.grantOptionSet()
if err != nil {
t.Fatalf("grantOptionSet error: %s", err)
}
if diff := cmp.Diff(c.want, got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
})
}
}

View File

@@ -2,12 +2,12 @@ package cmd
import (
"context"
"path/filepath"
"runtime"
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/adaptors/logger"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
"github.com/spf13/cobra"
"k8s.io/client-go/util/homedir"
)
// Set provides an implementation and interface for Cmd.
@@ -24,7 +24,7 @@ type Interface interface {
}
var defaultListenAddress = []string{"127.0.0.1:8000", "127.0.0.1:18000"}
var defaultTokenCacheDir = homedir.HomeDir() + "/.kube/cache/oidc-login"
var defaultTokenCacheDir = filepath.Join("~", ".kube", "cache", "oidc-login")
const defaultAuthenticationTimeoutSec = 180

246
pkg/cmd/cmd_test.go Normal file
View File

@@ -0,0 +1,246 @@
package cmd
import (
"context"
"os"
"path/filepath"
"testing"
"time"
"github.com/int128/kubelogin/pkg/oidc"
"github.com/int128/kubelogin/pkg/testing/logger"
"github.com/int128/kubelogin/pkg/tlsclientconfig"
"github.com/int128/kubelogin/pkg/usecases/authentication"
"github.com/int128/kubelogin/pkg/usecases/authentication/authcode"
"github.com/int128/kubelogin/pkg/usecases/credentialplugin"
"github.com/int128/kubelogin/pkg/usecases/standalone"
)
func TestCmd_Run(t *testing.T) {
const executable = "kubelogin"
const version = "HEAD"
t.Run("root", func(t *testing.T) {
tests := map[string]struct {
args []string
in standalone.Input
}{
"Defaults": {
args: []string{executable},
in: standalone.Input{
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: defaultListenAddress,
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
},
"FullOptions": {
args: []string{executable,
"--kubeconfig", "/path/to/kubeconfig",
"--context", "hello.k8s.local",
"--user", "google",
"-v1",
},
in: standalone.Input{
KubeconfigFilename: "/path/to/kubeconfig",
KubeconfigContext: "hello.k8s.local",
KubeconfigUser: "google",
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: defaultListenAddress,
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
},
}
for name, c := range tests {
t.Run(name, func(t *testing.T) {
ctx := context.TODO()
mockStandalone := standalone.NewMockInterface(t)
mockStandalone.EXPECT().
Do(ctx, c.in).
Return(nil)
cmd := Cmd{
Root: &Root{
Standalone: mockStandalone,
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(ctx, c.args, version)
if exitCode != 0 {
t.Errorf("exitCode wants 0 but %d", exitCode)
}
})
}
t.Run("TooManyArgs", func(t *testing.T) {
cmd := Cmd{
Root: &Root{
Standalone: standalone.NewMockInterface(t),
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(context.TODO(), []string{executable, "some"}, version)
if exitCode != 1 {
t.Errorf("exitCode wants 1 but %d", exitCode)
}
})
})
t.Run("get-token", func(t *testing.T) {
userHomeDir, err := os.UserHomeDir()
if err != nil {
t.Fatalf("os.UserHomeDir error: %s", err)
}
tests := map[string]struct {
args []string
in credentialplugin.Input
}{
"Defaults": {
args: []string{executable,
"get-token",
"--oidc-issuer-url", "https://issuer.example.com",
"--oidc-client-id", "YOUR_CLIENT_ID",
},
in: credentialplugin.Input{
TokenCacheDir: filepath.Join(userHomeDir, ".kube/cache/oidc-login"),
Provider: oidc.Provider{
IssuerURL: "https://issuer.example.com",
ClientID: "YOUR_CLIENT_ID",
},
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: defaultListenAddress,
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
},
"FullOptions": {
args: []string{executable,
"get-token",
"--oidc-issuer-url", "https://issuer.example.com",
"--oidc-client-id", "YOUR_CLIENT_ID",
"--oidc-client-secret", "YOUR_CLIENT_SECRET",
"--oidc-extra-scope", "email",
"--oidc-extra-scope", "profile",
"-v1",
},
in: credentialplugin.Input{
TokenCacheDir: filepath.Join(userHomeDir, ".kube/cache/oidc-login"),
Provider: oidc.Provider{
IssuerURL: "https://issuer.example.com",
ClientID: "YOUR_CLIENT_ID",
ClientSecret: "YOUR_CLIENT_SECRET",
ExtraScopes: []string{"email", "profile"},
},
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: defaultListenAddress,
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
},
},
},
},
"HomedirExpansion": {
args: []string{executable,
"get-token",
"--oidc-issuer-url", "https://issuer.example.com",
"--oidc-client-id", "YOUR_CLIENT_ID",
"--certificate-authority", "~/.kube/ca.crt",
"--local-server-cert", "~/.kube/oidc-server.crt",
"--local-server-key", "~/.kube/oidc-server.key",
"--token-cache-dir", "~/.kube/oidc-cache",
},
in: credentialplugin.Input{
TokenCacheDir: filepath.Join(userHomeDir, ".kube/oidc-cache"),
Provider: oidc.Provider{
IssuerURL: "https://issuer.example.com",
ClientID: "YOUR_CLIENT_ID",
},
GrantOptionSet: authentication.GrantOptionSet{
AuthCodeBrowserOption: &authcode.BrowserOption{
BindAddress: defaultListenAddress,
AuthenticationTimeout: defaultAuthenticationTimeoutSec * time.Second,
RedirectURLHostname: "localhost",
LocalServerCertFile: filepath.Join(userHomeDir, ".kube/oidc-server.crt"),
LocalServerKeyFile: filepath.Join(userHomeDir, ".kube/oidc-server.key"),
},
},
TLSClientConfig: tlsclientconfig.Config{
CACertFilename: []string{filepath.Join(userHomeDir, ".kube/ca.crt")},
},
},
},
}
for name, c := range tests {
t.Run(name, func(t *testing.T) {
ctx := context.TODO()
getToken := credentialplugin.NewMockInterface(t)
getToken.EXPECT().
Do(ctx, c.in).
Return(nil)
cmd := Cmd{
Root: &Root{
Logger: logger.New(t),
},
GetToken: &GetToken{
GetToken: getToken,
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(ctx, c.args, version)
if exitCode != 0 {
t.Errorf("exitCode wants 0 but %d", exitCode)
}
})
}
t.Run("MissingMandatoryOptions", func(t *testing.T) {
ctx := context.TODO()
cmd := Cmd{
Root: &Root{
Logger: logger.New(t),
},
GetToken: &GetToken{
GetToken: credentialplugin.NewMockInterface(t),
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(ctx, []string{executable, "get-token"}, version)
if exitCode != 1 {
t.Errorf("exitCode wants 1 but %d", exitCode)
}
})
t.Run("TooManyArgs", func(t *testing.T) {
ctx := context.TODO()
cmd := Cmd{
Root: &Root{
Logger: logger.New(t),
},
GetToken: &GetToken{
GetToken: credentialplugin.NewMockInterface(t),
Logger: logger.New(t),
},
Logger: logger.New(t),
}
exitCode := cmd.Run(ctx, []string{executable, "get-token", "foo"}, version)
if exitCode != 1 {
t.Errorf("exitCode wants 1 but %d", exitCode)
}
})
})
}

View File

@@ -1,11 +1,14 @@
package cmd
import (
"github.com/int128/kubelogin/pkg/adaptors/logger"
"errors"
"fmt"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
"github.com/int128/kubelogin/pkg/oidc"
"github.com/int128/kubelogin/pkg/usecases/credentialplugin"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/xerrors"
)
// getTokenOptions represents the options for get-token command.
@@ -14,6 +17,7 @@ type getTokenOptions struct {
ClientID string
ClientSecret string
ExtraScopes []string
UsePKCE bool
TokenCacheDir string
tlsOptions tlsOptions
authenticationOptions authenticationOptions
@@ -24,11 +28,19 @@ func (o *getTokenOptions) addFlags(f *pflag.FlagSet) {
f.StringVar(&o.ClientID, "oidc-client-id", "", "Client ID of the provider (mandatory)")
f.StringVar(&o.ClientSecret, "oidc-client-secret", "", "Client secret of the provider")
f.StringSliceVar(&o.ExtraScopes, "oidc-extra-scope", nil, "Scopes to request to the provider")
f.BoolVar(&o.UsePKCE, "oidc-use-pkce", false, "Force PKCE usage")
f.StringVar(&o.TokenCacheDir, "token-cache-dir", defaultTokenCacheDir, "Path to a directory for token cache")
o.tlsOptions.addFlags(f)
o.authenticationOptions.addFlags(f)
}
func (o *getTokenOptions) expandHomedir() error {
o.TokenCacheDir = expandHomedir(o.TokenCacheDir)
o.authenticationOptions.expandHomedir()
o.tlsOptions.expandHomedir()
return nil
}
type GetToken struct {
GetToken credentialplugin.Interface
Logger logger.Interface
@@ -44,31 +56,35 @@ func (cmd *GetToken) New() *cobra.Command {
return err
}
if o.IssuerURL == "" {
return xerrors.New("--oidc-issuer-url is missing")
return errors.New("--oidc-issuer-url is missing")
}
if o.ClientID == "" {
return xerrors.New("--oidc-client-id is missing")
return errors.New("--oidc-client-id is missing")
}
return nil
},
RunE: func(c *cobra.Command, _ []string) error {
if err := o.expandHomedir(); err != nil {
return err
}
grantOptionSet, err := o.authenticationOptions.grantOptionSet()
if err != nil {
return xerrors.Errorf("get-token: %w", err)
return fmt.Errorf("get-token: %w", err)
}
in := credentialplugin.Input{
IssuerURL: o.IssuerURL,
ClientID: o.ClientID,
ClientSecret: o.ClientSecret,
ExtraScopes: o.ExtraScopes,
CACertFilename: o.tlsOptions.CACertFilename,
CACertData: o.tlsOptions.CACertData,
SkipTLSVerify: o.tlsOptions.SkipTLSVerify,
TokenCacheDir: o.TokenCacheDir,
GrantOptionSet: grantOptionSet,
Provider: oidc.Provider{
IssuerURL: o.IssuerURL,
ClientID: o.ClientID,
ClientSecret: o.ClientSecret,
UsePKCE: o.UsePKCE,
ExtraScopes: o.ExtraScopes,
},
TokenCacheDir: o.TokenCacheDir,
GrantOptionSet: grantOptionSet,
TLSClientConfig: o.tlsOptions.tlsClientConfig(),
}
if err := cmd.GetToken.Do(c.Context(), in); err != nil {
return xerrors.Errorf("get-token: %w", err)
return fmt.Errorf("get-token: %w", err)
}
return nil
},

15
pkg/cmd/homedir.go Normal file
View File

@@ -0,0 +1,15 @@
package cmd
import (
"path/filepath"
"strings"
"k8s.io/client-go/util/homedir"
)
func expandHomedir(s string) string {
if !strings.HasPrefix(s, "~") {
return s
}
return filepath.Join(homedir.HomeDir(), strings.TrimPrefix(s, "~"))
}

76
pkg/cmd/mock_Interface.go Normal file
View File

@@ -0,0 +1,76 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package cmd
import (
context "context"
mock "github.com/stretchr/testify/mock"
)
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// Run provides a mock function with given fields: ctx, args, version
func (_m *MockInterface) Run(ctx context.Context, args []string, version string) int {
ret := _m.Called(ctx, args, version)
var r0 int
if rf, ok := ret.Get(0).(func(context.Context, []string, string) int); ok {
r0 = rf(ctx, args, version)
} else {
r0 = ret.Get(0).(int)
}
return r0
}
// MockInterface_Run_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Run'
type MockInterface_Run_Call struct {
*mock.Call
}
// Run is a helper method to define mock.On call
// - ctx context.Context
// - args []string
// - version string
func (_e *MockInterface_Expecter) Run(ctx interface{}, args interface{}, version interface{}) *MockInterface_Run_Call {
return &MockInterface_Run_Call{Call: _e.mock.On("Run", ctx, args, version)}
}
func (_c *MockInterface_Run_Call) Run(run func(ctx context.Context, args []string, version string)) *MockInterface_Run_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].([]string), args[2].(string))
})
return _c
}
func (_c *MockInterface_Run_Call) Return(_a0 int) *MockInterface_Run_Call {
_c.Call.Return(_a0)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -1,12 +1,12 @@
package cmd
import (
"github.com/int128/kubelogin/pkg/adaptors/kubeconfig"
"github.com/int128/kubelogin/pkg/adaptors/logger"
"fmt"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
"github.com/int128/kubelogin/pkg/kubeconfig"
"github.com/int128/kubelogin/pkg/usecases/standalone"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/xerrors"
)
const rootDescription = `Log in to the OpenID Connect provider.
@@ -51,19 +51,17 @@ func (cmd *Root) New() *cobra.Command {
RunE: func(c *cobra.Command, _ []string) error {
grantOptionSet, err := o.authenticationOptions.grantOptionSet()
if err != nil {
return xerrors.Errorf("invalid option: %w", err)
return fmt.Errorf("invalid option: %w", err)
}
in := standalone.Input{
KubeconfigFilename: o.Kubeconfig,
KubeconfigContext: kubeconfig.ContextName(o.Context),
KubeconfigUser: kubeconfig.UserName(o.User),
CACertFilename: o.tlsOptions.CACertFilename,
CACertData: o.tlsOptions.CACertData,
SkipTLSVerify: o.tlsOptions.SkipTLSVerify,
GrantOptionSet: grantOptionSet,
TLSClientConfig: o.tlsOptions.tlsClientConfig(),
}
if err := cmd.Standalone.Do(c.Context(), in); err != nil {
return xerrors.Errorf("login: %w", err)
return fmt.Errorf("login: %w", err)
}
return nil
},

View File

@@ -1,10 +1,11 @@
package cmd
import (
"fmt"
"github.com/int128/kubelogin/pkg/usecases/setup"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/xerrors"
)
// setupOptions represents the options for setup command.
@@ -13,6 +14,7 @@ type setupOptions struct {
ClientID string
ClientSecret string
ExtraScopes []string
UsePKCE bool
tlsOptions tlsOptions
authenticationOptions authenticationOptions
}
@@ -22,6 +24,7 @@ func (o *setupOptions) addFlags(f *pflag.FlagSet) {
f.StringVar(&o.ClientID, "oidc-client-id", "", "Client ID of the provider")
f.StringVar(&o.ClientSecret, "oidc-client-secret", "", "Client secret of the provider")
f.StringSliceVar(&o.ExtraScopes, "oidc-extra-scope", nil, "Scopes to request to the provider")
f.BoolVar(&o.UsePKCE, "oidc-use-pkce", false, "Force PKCE usage")
o.tlsOptions.addFlags(f)
o.authenticationOptions.addFlags(f)
}
@@ -39,17 +42,16 @@ func (cmd *Setup) New() *cobra.Command {
RunE: func(c *cobra.Command, _ []string) error {
grantOptionSet, err := o.authenticationOptions.grantOptionSet()
if err != nil {
return xerrors.Errorf("setup: %w", err)
return fmt.Errorf("setup: %w", err)
}
in := setup.Stage2Input{
IssuerURL: o.IssuerURL,
ClientID: o.ClientID,
ClientSecret: o.ClientSecret,
ExtraScopes: o.ExtraScopes,
CACertFilename: o.tlsOptions.CACertFilename,
CACertData: o.tlsOptions.CACertData,
SkipTLSVerify: o.tlsOptions.SkipTLSVerify,
GrantOptionSet: grantOptionSet,
IssuerURL: o.IssuerURL,
ClientID: o.ClientID,
ClientSecret: o.ClientSecret,
ExtraScopes: o.ExtraScopes,
UsePKCE: o.UsePKCE,
GrantOptionSet: grantOptionSet,
TLSClientConfig: o.tlsOptions.tlsClientConfig(),
}
if c.Flags().Lookup("listen-address").Changed {
in.ListenAddressArgs = o.authenticationOptions.ListenAddress
@@ -59,7 +61,7 @@ func (cmd *Setup) New() *cobra.Command {
return nil
}
if err := cmd.Setup.DoStage2(c.Context(), in); err != nil {
return xerrors.Errorf("setup: %w", err)
return fmt.Errorf("setup: %w", err)
}
return nil
},

52
pkg/cmd/tls.go Normal file
View File

@@ -0,0 +1,52 @@
package cmd
import (
"crypto/tls"
"github.com/int128/kubelogin/pkg/tlsclientconfig"
"github.com/spf13/pflag"
)
type tlsOptions struct {
CACertFilename []string
CACertData []string
SkipTLSVerify bool
RenegotiateOnceAsClient bool
RenegotiateFreelyAsClient bool
}
func (o *tlsOptions) addFlags(f *pflag.FlagSet) {
f.StringArrayVar(&o.CACertFilename, "certificate-authority", nil, "Path to a cert file for the certificate authority")
f.StringArrayVar(&o.CACertData, "certificate-authority-data", nil, "Base64 encoded cert for the certificate authority")
f.BoolVar(&o.SkipTLSVerify, "insecure-skip-tls-verify", false, "If set, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure")
f.BoolVar(&o.RenegotiateOnceAsClient, "tls-renegotiation-once", false, "If set, allow a remote server to request renegotiation once per connection")
f.BoolVar(&o.RenegotiateFreelyAsClient, "tls-renegotiation-freely", false, "If set, allow a remote server to repeatedly request renegotiation")
}
func (o *tlsOptions) expandHomedir() {
var caCertFilenames []string
for _, caCertFilename := range o.CACertFilename {
expanded := expandHomedir(caCertFilename)
caCertFilenames = append(caCertFilenames, expanded)
}
o.CACertFilename = caCertFilenames
}
func (o tlsOptions) tlsClientConfig() tlsclientconfig.Config {
return tlsclientconfig.Config{
CACertFilename: o.CACertFilename,
CACertData: o.CACertData,
SkipTLSVerify: o.SkipTLSVerify,
Renegotiation: o.renegotiationSupport(),
}
}
func (o tlsOptions) renegotiationSupport() tls.RenegotiationSupport {
if o.RenegotiateOnceAsClient {
return tls.RenegotiateOnceAsClient
}
if o.RenegotiateFreelyAsClient {
return tls.RenegotiateFreelyAsClient
}
return tls.RenegotiateNever
}

92
pkg/cmd/tls_test.go Normal file
View File

@@ -0,0 +1,92 @@
package cmd
import (
"crypto/tls"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/int128/kubelogin/pkg/tlsclientconfig"
"github.com/spf13/pflag"
)
func Test_tlsOptions_tlsClientConfig(t *testing.T) {
tests := map[string]struct {
args []string
want tlsclientconfig.Config
}{
"NoFlag": {},
"SkipTLSVerify": {
args: []string{
"--insecure-skip-tls-verify",
},
want: tlsclientconfig.Config{
SkipTLSVerify: true,
},
},
"CACertFilename1": {
args: []string{
"--certificate-authority", "/path/to/cert1",
},
want: tlsclientconfig.Config{
CACertFilename: []string{"/path/to/cert1"},
},
},
"CACertFilename2": {
args: []string{
"--certificate-authority", "/path/to/cert1",
"--certificate-authority", "/path/to/cert2",
},
want: tlsclientconfig.Config{
CACertFilename: []string{"/path/to/cert1", "/path/to/cert2"},
},
},
"CACertData1": {
args: []string{
"--certificate-authority-data", "base64encoded1",
},
want: tlsclientconfig.Config{
CACertData: []string{"base64encoded1"},
},
},
"CACertData2": {
args: []string{
"--certificate-authority-data", "base64encoded1",
"--certificate-authority-data", "base64encoded2",
},
want: tlsclientconfig.Config{
CACertData: []string{"base64encoded1", "base64encoded2"},
},
},
"RenegotiateOnceAsClient": {
args: []string{
"--tls-renegotiation-once",
},
want: tlsclientconfig.Config{
Renegotiation: tls.RenegotiateOnceAsClient,
},
},
"RenegotiateFreelyAsClient": {
args: []string{
"--tls-renegotiation-freely",
},
want: tlsclientconfig.Config{
Renegotiation: tls.RenegotiateFreelyAsClient,
},
},
}
for name, c := range tests {
t.Run(name, func(t *testing.T) {
var o tlsOptions
f := pflag.NewFlagSet("", pflag.ContinueOnError)
o.addFlags(f)
if err := f.Parse(c.args); err != nil {
t.Fatalf("Parse error: %s", err)
}
got := o.tlsClientConfig()
if diff := cmp.Diff(c.want, got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
})
}
}

View File

@@ -0,0 +1,10 @@
// Package credentialplugin provides the types for client-go credential plugins.
package credentialplugin
import "time"
// Output represents an output object of the credential plugin.
type Output struct {
Token string
Expiry time.Time
}

View File

@@ -1,32 +1,24 @@
// Package credentialpluginwriter provides a writer for a credential plugin.
package credentialpluginwriter
// Package writer provides a writer for a credential plugin.
package writer
import (
"encoding/json"
"time"
"fmt"
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/adaptors/stdio"
"golang.org/x/xerrors"
"github.com/int128/kubelogin/pkg/credentialplugin"
"github.com/int128/kubelogin/pkg/infrastructure/stdio"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
)
//go:generate mockgen -destination mock_credentialpluginwriter/mock_credentialpluginwriter.go github.com/int128/kubelogin/pkg/adaptors/credentialpluginwriter Interface
var Set = wire.NewSet(
wire.Struct(new(Writer), "*"),
wire.Bind(new(Interface), new(*Writer)),
)
type Interface interface {
Write(out Output) error
}
// Output represents an output object of the credential plugin.
type Output struct {
Token string
Expiry time.Time
Write(out credentialplugin.Output) error
}
type Writer struct {
@@ -34,7 +26,7 @@ type Writer struct {
}
// Write writes the ExecCredential to standard output for kubectl.
func (w *Writer) Write(out Output) error {
func (w *Writer) Write(out credentialplugin.Output) error {
ec := &clientauthenticationv1beta1.ExecCredential{
TypeMeta: metav1.TypeMeta{
APIVersion: "client.authentication.k8s.io/v1beta1",
@@ -47,7 +39,7 @@ func (w *Writer) Write(out Output) error {
}
e := json.NewEncoder(w.Stdout)
if err := e.Encode(ec); err != nil {
return xerrors.Errorf("could not write the ExecCredential: %w", err)
return fmt.Errorf("could not write the ExecCredential: %w", err)
}
return nil
}

View File

@@ -0,0 +1,73 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package writer
import (
credentialplugin "github.com/int128/kubelogin/pkg/credentialplugin"
mock "github.com/stretchr/testify/mock"
)
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// Write provides a mock function with given fields: out
func (_m *MockInterface) Write(out credentialplugin.Output) error {
ret := _m.Called(out)
var r0 error
if rf, ok := ret.Get(0).(func(credentialplugin.Output) error); ok {
r0 = rf(out)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockInterface_Write_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Write'
type MockInterface_Write_Call struct {
*mock.Call
}
// Write is a helper method to define mock.On call
// - out credentialplugin.Output
func (_e *MockInterface_Expecter) Write(out interface{}) *MockInterface_Write_Call {
return &MockInterface_Write_Call{Call: _e.mock.On("Write", out)}
}
func (_c *MockInterface_Write_Call) Run(run func(out credentialplugin.Output)) *MockInterface_Write_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(credentialplugin.Output))
})
return _c
}
func (_c *MockInterface_Write_Call) Return(_a0 error) *MockInterface_Write_Call {
_c.Call.Return(_a0)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -5,24 +5,26 @@ package di
import (
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/adaptors/browser"
"github.com/int128/kubelogin/pkg/adaptors/certpool"
"github.com/int128/kubelogin/pkg/adaptors/clock"
"github.com/int128/kubelogin/pkg/adaptors/cmd"
"github.com/int128/kubelogin/pkg/adaptors/credentialpluginwriter"
"github.com/int128/kubelogin/pkg/adaptors/kubeconfig"
"github.com/int128/kubelogin/pkg/adaptors/logger"
"github.com/int128/kubelogin/pkg/adaptors/oidcclient"
"github.com/int128/kubelogin/pkg/adaptors/reader"
"github.com/int128/kubelogin/pkg/adaptors/stdio"
"github.com/int128/kubelogin/pkg/adaptors/tokencache"
"github.com/int128/kubelogin/pkg/cmd"
"github.com/int128/kubelogin/pkg/credentialplugin/writer"
"github.com/int128/kubelogin/pkg/infrastructure/browser"
"github.com/int128/kubelogin/pkg/infrastructure/clock"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
"github.com/int128/kubelogin/pkg/infrastructure/mutex"
"github.com/int128/kubelogin/pkg/infrastructure/reader"
"github.com/int128/kubelogin/pkg/infrastructure/stdio"
kubeconfigLoader "github.com/int128/kubelogin/pkg/kubeconfig/loader"
kubeconfigWriter "github.com/int128/kubelogin/pkg/kubeconfig/writer"
"github.com/int128/kubelogin/pkg/oidc/client"
"github.com/int128/kubelogin/pkg/tlsclientconfig/loader"
"github.com/int128/kubelogin/pkg/tokencache/repository"
"github.com/int128/kubelogin/pkg/usecases/authentication"
"github.com/int128/kubelogin/pkg/usecases/credentialplugin"
"github.com/int128/kubelogin/pkg/usecases/setup"
"github.com/int128/kubelogin/pkg/usecases/standalone"
)
// NewCmd returns an instance of adaptors.Cmd.
// NewCmd returns an instance of infrastructure.Cmd.
func NewCmd() cmd.Interface {
wire.Build(
NewCmdForHeadless,
@@ -36,7 +38,7 @@ func NewCmd() cmd.Interface {
return nil
}
// NewCmdForHeadless returns an instance of adaptors.Cmd for headless testing.
// NewCmdForHeadless returns an instance of infrastructure.Cmd for headless testing.
func NewCmdForHeadless(clock.Interface, stdio.Stdin, stdio.Stdout, logger.Interface, browser.Interface) cmd.Interface {
wire.Build(
// use-cases
@@ -45,14 +47,16 @@ func NewCmdForHeadless(clock.Interface, stdio.Stdin, stdio.Stdout, logger.Interf
credentialplugin.Set,
setup.Set,
// adaptors
// infrastructure
cmd.Set,
reader.Set,
kubeconfig.Set,
tokencache.Set,
oidcclient.Set,
certpool.Set,
credentialpluginwriter.Set,
kubeconfigLoader.Set,
kubeconfigWriter.Set,
repository.Set,
client.Set,
loader.Set,
writer.Set,
mutex.Set,
)
return nil
}

View File

@@ -6,17 +6,19 @@
package di
import (
"github.com/int128/kubelogin/pkg/adaptors/browser"
"github.com/int128/kubelogin/pkg/adaptors/certpool"
"github.com/int128/kubelogin/pkg/adaptors/clock"
"github.com/int128/kubelogin/pkg/adaptors/cmd"
"github.com/int128/kubelogin/pkg/adaptors/credentialpluginwriter"
"github.com/int128/kubelogin/pkg/adaptors/kubeconfig"
"github.com/int128/kubelogin/pkg/adaptors/logger"
"github.com/int128/kubelogin/pkg/adaptors/oidcclient"
"github.com/int128/kubelogin/pkg/adaptors/reader"
"github.com/int128/kubelogin/pkg/adaptors/stdio"
"github.com/int128/kubelogin/pkg/adaptors/tokencache"
"github.com/int128/kubelogin/pkg/cmd"
writer2 "github.com/int128/kubelogin/pkg/credentialplugin/writer"
"github.com/int128/kubelogin/pkg/infrastructure/browser"
"github.com/int128/kubelogin/pkg/infrastructure/clock"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
"github.com/int128/kubelogin/pkg/infrastructure/mutex"
"github.com/int128/kubelogin/pkg/infrastructure/reader"
"github.com/int128/kubelogin/pkg/infrastructure/stdio"
loader2 "github.com/int128/kubelogin/pkg/kubeconfig/loader"
"github.com/int128/kubelogin/pkg/kubeconfig/writer"
"github.com/int128/kubelogin/pkg/oidc/client"
"github.com/int128/kubelogin/pkg/tlsclientconfig/loader"
"github.com/int128/kubelogin/pkg/tokencache/repository"
"github.com/int128/kubelogin/pkg/usecases/authentication"
"github.com/int128/kubelogin/pkg/usecases/authentication/authcode"
"github.com/int128/kubelogin/pkg/usecases/authentication/ropc"
@@ -28,7 +30,6 @@ import (
// Injectors from di.go:
// NewCmd returns an instance of adaptors.Cmd.
func NewCmd() cmd.Interface {
clockReal := &clock.Real{}
stdin := _wireFileValue
@@ -44,9 +45,10 @@ var (
_wireOsFileValue = os.Stdout
)
// NewCmdForHeadless returns an instance of adaptors.Cmd for headless testing.
func NewCmdForHeadless(clockInterface clock.Interface, stdin stdio.Stdin, stdout stdio.Stdout, loggerInterface logger.Interface, browserInterface browser.Interface) cmd.Interface {
factory := &oidcclient.Factory{
loaderLoader := loader.Loader{}
factory := &client.Factory{
Loader: loaderLoader,
Clock: clockInterface,
Logger: loggerInterface,
}
@@ -66,36 +68,37 @@ func NewCmdForHeadless(clockInterface clock.Interface, stdin stdio.Stdin, stdout
Logger: loggerInterface,
}
authenticationAuthentication := &authentication.Authentication{
OIDCClient: factory,
ClientFactory: factory,
Logger: loggerInterface,
Clock: clockInterface,
AuthCodeBrowser: authcodeBrowser,
AuthCodeKeyboard: keyboard,
ROPC: ropcROPC,
}
kubeconfigKubeconfig := &kubeconfig.Kubeconfig{
Logger: loggerInterface,
}
newFunc := _wireNewFuncValue
loader3 := &loader2.Loader{}
writerWriter := &writer.Writer{}
standaloneStandalone := &standalone.Standalone{
Authentication: authenticationAuthentication,
Kubeconfig: kubeconfigKubeconfig,
NewCertPool: newFunc,
Logger: loggerInterface,
Authentication: authenticationAuthentication,
KubeconfigLoader: loader3,
KubeconfigWriter: writerWriter,
Logger: loggerInterface,
}
root := &cmd.Root{
Standalone: standaloneStandalone,
Logger: loggerInterface,
}
repository := &tokencache.Repository{}
writer := &credentialpluginwriter.Writer{
repositoryRepository := &repository.Repository{}
writer3 := &writer2.Writer{
Stdout: stdout,
}
mutexMutex := &mutex.Mutex{
Logger: loggerInterface,
}
getToken := &credentialplugin.GetToken{
Authentication: authenticationAuthentication,
TokenCacheRepository: repository,
NewCertPool: newFunc,
Writer: writer,
TokenCacheRepository: repositoryRepository,
Writer: writer3,
Mutex: mutexMutex,
Logger: loggerInterface,
}
cmdGetToken := &cmd.GetToken{
@@ -104,7 +107,6 @@ func NewCmdForHeadless(clockInterface clock.Interface, stdin stdio.Stdin, stdout
}
setupSetup := &setup.Setup{
Authentication: authenticationAuthentication,
NewCertPool: newFunc,
Logger: loggerInterface,
}
cmdSetup := &cmd.Setup{
@@ -118,7 +120,3 @@ func NewCmdForHeadless(clockInterface clock.Interface, stdin stdio.Stdin, stdout
}
return cmdCmd
}
var (
_wireNewFuncValue = certpool.NewFunc(certpool.New)
)

View File

@@ -1,14 +1,14 @@
package browser
import (
"context"
"os"
"os/exec"
"github.com/google/wire"
"github.com/pkg/browser"
)
//go:generate mockgen -destination mock_browser/mock_browser.go github.com/int128/kubelogin/pkg/adaptors/browser Interface
func init() {
// In credential plugin mode, some browser launcher writes a message to stdout
// and it may break the credential json for client-go.
@@ -23,6 +23,7 @@ var Set = wire.NewSet(
type Interface interface {
Open(url string) error
OpenCommand(ctx context.Context, url, command string) error
}
type Browser struct{}
@@ -31,3 +32,11 @@ type Browser struct{}
func (*Browser) Open(url string) error {
return browser.OpenURL(url)
}
// OpenCommand opens the browser using the command.
func (*Browser) OpenCommand(ctx context.Context, url, command string) error {
c := exec.CommandContext(ctx, command, url)
c.Stdout = os.Stderr // see above
c.Stderr = os.Stderr
return c.Run()
}

View File

@@ -0,0 +1,113 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package browser
import (
context "context"
mock "github.com/stretchr/testify/mock"
)
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// Open provides a mock function with given fields: url
func (_m *MockInterface) Open(url string) error {
ret := _m.Called(url)
var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(url)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockInterface_Open_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Open'
type MockInterface_Open_Call struct {
*mock.Call
}
// Open is a helper method to define mock.On call
// - url string
func (_e *MockInterface_Expecter) Open(url interface{}) *MockInterface_Open_Call {
return &MockInterface_Open_Call{Call: _e.mock.On("Open", url)}
}
func (_c *MockInterface_Open_Call) Run(run func(url string)) *MockInterface_Open_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockInterface_Open_Call) Return(_a0 error) *MockInterface_Open_Call {
_c.Call.Return(_a0)
return _c
}
// OpenCommand provides a mock function with given fields: ctx, url, command
func (_m *MockInterface) OpenCommand(ctx context.Context, url string, command string) error {
ret := _m.Called(ctx, url, command)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
r0 = rf(ctx, url, command)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockInterface_OpenCommand_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OpenCommand'
type MockInterface_OpenCommand_Call struct {
*mock.Call
}
// OpenCommand is a helper method to define mock.On call
// - ctx context.Context
// - url string
// - command string
func (_e *MockInterface_Expecter) OpenCommand(ctx interface{}, url interface{}, command interface{}) *MockInterface_OpenCommand_Call {
return &MockInterface_OpenCommand_Call{Call: _e.mock.On("OpenCommand", ctx, url, command)}
}
func (_c *MockInterface_OpenCommand_Call) Run(run func(ctx context.Context, url string, command string)) *MockInterface_OpenCommand_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(string), args[2].(string))
})
return _c
}
func (_c *MockInterface_OpenCommand_Call) Return(_a0 error) *MockInterface_OpenCommand_Call {
_c.Call.Return(_a0)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,73 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package clock
import (
time "time"
mock "github.com/stretchr/testify/mock"
)
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// Now provides a mock function with given fields:
func (_m *MockInterface) Now() time.Time {
ret := _m.Called()
var r0 time.Time
if rf, ok := ret.Get(0).(func() time.Time); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(time.Time)
}
return r0
}
// MockInterface_Now_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Now'
type MockInterface_Now_Call struct {
*mock.Call
}
// Now is a helper method to define mock.On call
func (_e *MockInterface_Expecter) Now() *MockInterface_Now_Call {
return &MockInterface_Now_Call{Call: _e.mock.On("Now")}
}
func (_c *MockInterface_Now_Call) Run(run func()) *MockInterface_Now_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockInterface_Now_Call) Return(_a0 time.Time) *MockInterface_Now_Call {
_c.Call.Return(_a0)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -7,7 +7,7 @@ import (
"github.com/google/wire"
"github.com/spf13/pflag"
"k8s.io/klog"
"k8s.io/klog/v2"
)
// Set provides an implementation and interface for Logger.
@@ -56,5 +56,5 @@ func (*Logger) V(level int) Verbose {
// IsEnabled returns true if the level is enabled.
func (*Logger) IsEnabled(level int) bool {
return bool(klog.V(klog.Level(level)))
return klog.V(klog.Level(level)).Enabled()
}

View File

@@ -0,0 +1,179 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package logger
import (
pflag "github.com/spf13/pflag"
mock "github.com/stretchr/testify/mock"
)
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// AddFlags provides a mock function with given fields: f
func (_m *MockInterface) AddFlags(f *pflag.FlagSet) {
_m.Called(f)
}
// MockInterface_AddFlags_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddFlags'
type MockInterface_AddFlags_Call struct {
*mock.Call
}
// AddFlags is a helper method to define mock.On call
// - f *pflag.FlagSet
func (_e *MockInterface_Expecter) AddFlags(f interface{}) *MockInterface_AddFlags_Call {
return &MockInterface_AddFlags_Call{Call: _e.mock.On("AddFlags", f)}
}
func (_c *MockInterface_AddFlags_Call) Run(run func(f *pflag.FlagSet)) *MockInterface_AddFlags_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*pflag.FlagSet))
})
return _c
}
func (_c *MockInterface_AddFlags_Call) Return() *MockInterface_AddFlags_Call {
_c.Call.Return()
return _c
}
// IsEnabled provides a mock function with given fields: level
func (_m *MockInterface) IsEnabled(level int) bool {
ret := _m.Called(level)
var r0 bool
if rf, ok := ret.Get(0).(func(int) bool); ok {
r0 = rf(level)
} else {
r0 = ret.Get(0).(bool)
}
return r0
}
// MockInterface_IsEnabled_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsEnabled'
type MockInterface_IsEnabled_Call struct {
*mock.Call
}
// IsEnabled is a helper method to define mock.On call
// - level int
func (_e *MockInterface_Expecter) IsEnabled(level interface{}) *MockInterface_IsEnabled_Call {
return &MockInterface_IsEnabled_Call{Call: _e.mock.On("IsEnabled", level)}
}
func (_c *MockInterface_IsEnabled_Call) Run(run func(level int)) *MockInterface_IsEnabled_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(int))
})
return _c
}
func (_c *MockInterface_IsEnabled_Call) Return(_a0 bool) *MockInterface_IsEnabled_Call {
_c.Call.Return(_a0)
return _c
}
// Printf provides a mock function with given fields: format, args
func (_m *MockInterface) Printf(format string, args ...interface{}) {
var _ca []interface{}
_ca = append(_ca, format)
_ca = append(_ca, args...)
_m.Called(_ca...)
}
// MockInterface_Printf_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Printf'
type MockInterface_Printf_Call struct {
*mock.Call
}
// Printf is a helper method to define mock.On call
// - format string
// - args ...interface{}
func (_e *MockInterface_Expecter) Printf(format interface{}, args ...interface{}) *MockInterface_Printf_Call {
return &MockInterface_Printf_Call{Call: _e.mock.On("Printf",
append([]interface{}{format}, args...)...)}
}
func (_c *MockInterface_Printf_Call) Run(run func(format string, args ...interface{})) *MockInterface_Printf_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-1)
for i, a := range args[1:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(string), variadicArgs...)
})
return _c
}
func (_c *MockInterface_Printf_Call) Return() *MockInterface_Printf_Call {
_c.Call.Return()
return _c
}
// V provides a mock function with given fields: level
func (_m *MockInterface) V(level int) Verbose {
ret := _m.Called(level)
var r0 Verbose
if rf, ok := ret.Get(0).(func(int) Verbose); ok {
r0 = rf(level)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(Verbose)
}
}
return r0
}
// MockInterface_V_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'V'
type MockInterface_V_Call struct {
*mock.Call
}
// V is a helper method to define mock.On call
// - level int
func (_e *MockInterface_Expecter) V(level interface{}) *MockInterface_V_Call {
return &MockInterface_V_Call{Call: _e.mock.On("V", level)}
}
func (_c *MockInterface_V_Call) Run(run func(level int)) *MockInterface_V_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(int))
})
return _c
}
func (_c *MockInterface_V_Call) Return(_a0 Verbose) *MockInterface_V_Call {
_c.Call.Return(_a0)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,72 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package logger
import mock "github.com/stretchr/testify/mock"
// MockVerbose is an autogenerated mock type for the Verbose type
type MockVerbose struct {
mock.Mock
}
type MockVerbose_Expecter struct {
mock *mock.Mock
}
func (_m *MockVerbose) EXPECT() *MockVerbose_Expecter {
return &MockVerbose_Expecter{mock: &_m.Mock}
}
// Infof provides a mock function with given fields: format, args
func (_m *MockVerbose) Infof(format string, args ...interface{}) {
var _ca []interface{}
_ca = append(_ca, format)
_ca = append(_ca, args...)
_m.Called(_ca...)
}
// MockVerbose_Infof_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Infof'
type MockVerbose_Infof_Call struct {
*mock.Call
}
// Infof is a helper method to define mock.On call
// - format string
// - args ...interface{}
func (_e *MockVerbose_Expecter) Infof(format interface{}, args ...interface{}) *MockVerbose_Infof_Call {
return &MockVerbose_Infof_Call{Call: _e.mock.On("Infof",
append([]interface{}{format}, args...)...)}
}
func (_c *MockVerbose_Infof_Call) Run(run func(format string, args ...interface{})) *MockVerbose_Infof_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-1)
for i, a := range args[1:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(string), variadicArgs...)
})
return _c
}
func (_c *MockVerbose_Infof_Call) Return() *MockVerbose_Infof_Call {
_c.Call.Return()
return _c
}
type mockConstructorTestingTNewMockVerbose interface {
mock.TestingT
Cleanup(func())
}
// NewMockVerbose creates a new instance of MockVerbose. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockVerbose(t mockConstructorTestingTNewMockVerbose) *MockVerbose {
mock := &MockVerbose{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,72 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package logger
import mock "github.com/stretchr/testify/mock"
// mockGoLogger is an autogenerated mock type for the goLogger type
type mockGoLogger struct {
mock.Mock
}
type mockGoLogger_Expecter struct {
mock *mock.Mock
}
func (_m *mockGoLogger) EXPECT() *mockGoLogger_Expecter {
return &mockGoLogger_Expecter{mock: &_m.Mock}
}
// Printf provides a mock function with given fields: format, v
func (_m *mockGoLogger) Printf(format string, v ...interface{}) {
var _ca []interface{}
_ca = append(_ca, format)
_ca = append(_ca, v...)
_m.Called(_ca...)
}
// mockGoLogger_Printf_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Printf'
type mockGoLogger_Printf_Call struct {
*mock.Call
}
// Printf is a helper method to define mock.On call
// - format string
// - v ...interface{}
func (_e *mockGoLogger_Expecter) Printf(format interface{}, v ...interface{}) *mockGoLogger_Printf_Call {
return &mockGoLogger_Printf_Call{Call: _e.mock.On("Printf",
append([]interface{}{format}, v...)...)}
}
func (_c *mockGoLogger_Printf_Call) Run(run func(format string, v ...interface{})) *mockGoLogger_Printf_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-1)
for i, a := range args[1:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(string), variadicArgs...)
})
return _c
}
func (_c *mockGoLogger_Printf_Call) Return() *mockGoLogger_Printf_Call {
_c.Call.Return()
return _c
}
type mockConstructorTestingTnewMockGoLogger interface {
mock.TestingT
Cleanup(func())
}
// newMockGoLogger creates a new instance of mockGoLogger. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func newMockGoLogger(t mockConstructorTestingTnewMockGoLogger) *mockGoLogger {
mock := &mockGoLogger{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,121 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package mutex
import (
context "context"
mock "github.com/stretchr/testify/mock"
)
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// Acquire provides a mock function with given fields: ctx, name
func (_m *MockInterface) Acquire(ctx context.Context, name string) (*Lock, error) {
ret := _m.Called(ctx, name)
var r0 *Lock
if rf, ok := ret.Get(0).(func(context.Context, string) *Lock); ok {
r0 = rf(ctx, name)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*Lock)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
r1 = rf(ctx, name)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockInterface_Acquire_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Acquire'
type MockInterface_Acquire_Call struct {
*mock.Call
}
// Acquire is a helper method to define mock.On call
// - ctx context.Context
// - name string
func (_e *MockInterface_Expecter) Acquire(ctx interface{}, name interface{}) *MockInterface_Acquire_Call {
return &MockInterface_Acquire_Call{Call: _e.mock.On("Acquire", ctx, name)}
}
func (_c *MockInterface_Acquire_Call) Run(run func(ctx context.Context, name string)) *MockInterface_Acquire_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(string))
})
return _c
}
func (_c *MockInterface_Acquire_Call) Return(_a0 *Lock, _a1 error) *MockInterface_Acquire_Call {
_c.Call.Return(_a0, _a1)
return _c
}
// Release provides a mock function with given fields: lock
func (_m *MockInterface) Release(lock *Lock) error {
ret := _m.Called(lock)
var r0 error
if rf, ok := ret.Get(0).(func(*Lock) error); ok {
r0 = rf(lock)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockInterface_Release_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Release'
type MockInterface_Release_Call struct {
*mock.Call
}
// Release is a helper method to define mock.On call
// - lock *Lock
func (_e *MockInterface_Expecter) Release(lock interface{}) *MockInterface_Release_Call {
return &MockInterface_Release_Call{Call: _e.mock.On("Release", lock)}
}
func (_c *MockInterface_Release_Call) Run(run func(lock *Lock)) *MockInterface_Release_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(*Lock))
})
return _c
}
func (_c *MockInterface_Release_Call) Return(_a0 error) *MockInterface_Release_Call {
_c.Call.Return(_a0)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,87 @@
package mutex
import (
"context"
"fmt"
"os"
"path"
"github.com/alexflint/go-filemutex"
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
)
var Set = wire.NewSet(
wire.Struct(new(Mutex), "*"),
wire.Bind(new(Interface), new(*Mutex)),
)
type Interface interface {
Acquire(ctx context.Context, name string) (*Lock, error)
Release(lock *Lock) error
}
// Lock holds the lock data.
type Lock struct {
Data interface{}
Name string
}
type Mutex struct {
Logger logger.Interface
}
// internalAcquire wait for acquisition of the lock
func internalAcquire(fm *filemutex.FileMutex) chan error {
result := make(chan error)
go func() {
if err := fm.Lock(); err != nil {
result <- err
}
close(result)
}()
return result
}
// internalRelease disposes of resources associated with a lock
func internalRelease(fm *filemutex.FileMutex, lfn string, log logger.Interface) error {
err := fm.Close()
if err != nil {
log.V(1).Infof("Error closing lock file %s: %s", lfn, err)
}
return err
}
// LockFileName get the lock file name from the lock name.
func LockFileName(name string) string {
return path.Join(os.TempDir(), fmt.Sprintf(".kubelogin.%s.lock", name))
}
// Acquire acquire a lock for the specified name. The context could be used to set a timeout.
func (m *Mutex) Acquire(ctx context.Context, name string) (*Lock, error) {
lfn := LockFileName(name)
fm, err := filemutex.New(lfn)
if err != nil {
return nil, fmt.Errorf("error creating mutex file %s: %w", lfn, err)
}
lockChan := internalAcquire(fm)
select {
case <-ctx.Done():
_ = internalRelease(fm, lfn, m.Logger)
return nil, ctx.Err()
case err := <-lockChan:
if err != nil {
_ = internalRelease(fm, lfn, m.Logger)
return nil, fmt.Errorf("error acquiring lock on file %s: %w", lfn, err)
}
return &Lock{Data: fm, Name: name}, nil
}
}
// Release release the specified lock
func (m *Mutex) Release(lock *Lock) error {
fm := lock.Data.(*filemutex.FileMutex)
lfn := LockFileName(lock.Name)
return internalRelease(fm, lfn, m.Logger)
}

View File

@@ -0,0 +1,64 @@
package mutex
import (
"fmt"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
"golang.org/x/net/context"
"math/rand"
"sync"
"testing"
"time"
)
func TestMutex(t *testing.T) {
t.Run("Test successful parallel acquisition with no reentry allowed", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
nbConcurrency := 20
wg := sync.WaitGroup{}
events := make(chan int, nbConcurrency*2)
errors := make(chan error, nbConcurrency)
doLockUnlock := func() {
defer wg.Done()
m := Mutex{
Logger: logger.New(),
}
if mutex, err := m.Acquire(ctx, "test"); err == nil {
events <- 1
var dur = time.Duration(rand.Intn(5000))
time.Sleep(dur * time.Microsecond)
events <- -1
if err := m.Release(mutex); err != nil {
errors <- fmt.Errorf("Release error: %w", err)
}
} else {
errors <- fmt.Errorf("Acquire error: %w", err)
}
}
for i := 0; i < nbConcurrency; i++ {
wg.Add(1)
go doLockUnlock()
}
wg.Wait()
close(events)
close(errors)
countConcurrent := 0
for delta := range events {
countConcurrent += delta
if countConcurrent > 1 {
t.Errorf("The mutex did not prevented reentry: %d", countConcurrent)
}
}
for anError := range errors {
t.Errorf("The gorouting returned an error: %s", anError)
}
})
}

View File

@@ -0,0 +1,121 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package reader
import mock "github.com/stretchr/testify/mock"
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// ReadPassword provides a mock function with given fields: prompt
func (_m *MockInterface) ReadPassword(prompt string) (string, error) {
ret := _m.Called(prompt)
var r0 string
if rf, ok := ret.Get(0).(func(string) string); ok {
r0 = rf(prompt)
} else {
r0 = ret.Get(0).(string)
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(prompt)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockInterface_ReadPassword_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReadPassword'
type MockInterface_ReadPassword_Call struct {
*mock.Call
}
// ReadPassword is a helper method to define mock.On call
// - prompt string
func (_e *MockInterface_Expecter) ReadPassword(prompt interface{}) *MockInterface_ReadPassword_Call {
return &MockInterface_ReadPassword_Call{Call: _e.mock.On("ReadPassword", prompt)}
}
func (_c *MockInterface_ReadPassword_Call) Run(run func(prompt string)) *MockInterface_ReadPassword_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockInterface_ReadPassword_Call) Return(_a0 string, _a1 error) *MockInterface_ReadPassword_Call {
_c.Call.Return(_a0, _a1)
return _c
}
// ReadString provides a mock function with given fields: prompt
func (_m *MockInterface) ReadString(prompt string) (string, error) {
ret := _m.Called(prompt)
var r0 string
if rf, ok := ret.Get(0).(func(string) string); ok {
r0 = rf(prompt)
} else {
r0 = ret.Get(0).(string)
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(prompt)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockInterface_ReadString_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReadString'
type MockInterface_ReadString_Call struct {
*mock.Call
}
// ReadString is a helper method to define mock.On call
// - prompt string
func (_e *MockInterface_Expecter) ReadString(prompt interface{}) *MockInterface_ReadString_Call {
return &MockInterface_ReadString_Call{Call: _e.mock.On("ReadString", prompt)}
}
func (_c *MockInterface_ReadString_Call) Run(run func(prompt string)) *MockInterface_ReadString_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string))
})
return _c
}
func (_c *MockInterface_ReadString_Call) Return(_a0 string, _a1 error) *MockInterface_ReadString_Call {
_c.Call.Return(_a0, _a1)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -9,13 +9,10 @@ import (
"syscall"
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/adaptors/stdio"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/xerrors"
"github.com/int128/kubelogin/pkg/infrastructure/stdio"
"golang.org/x/term"
)
//go:generate mockgen -destination mock_reader/mock_reader.go github.com/int128/kubelogin/pkg/adaptors/reader Interface
// Set provides an implementation and interface for Reader.
var Set = wire.NewSet(
wire.Struct(new(Reader), "*"),
@@ -34,12 +31,12 @@ type Reader struct {
// ReadString reads a string from the stdin.
func (x *Reader) ReadString(prompt string) (string, error) {
if _, err := fmt.Fprint(os.Stderr, prompt); err != nil {
return "", xerrors.Errorf("write error: %w", err)
return "", fmt.Errorf("write error: %w", err)
}
r := bufio.NewReader(x.Stdin)
s, err := r.ReadString('\n')
if err != nil {
return "", xerrors.Errorf("read error: %w", err)
return "", fmt.Errorf("read error: %w", err)
}
s = strings.TrimRight(s, "\r\n")
return s, nil
@@ -48,14 +45,14 @@ func (x *Reader) ReadString(prompt string) (string, error) {
// ReadPassword reads a password from the stdin without echo back.
func (*Reader) ReadPassword(prompt string) (string, error) {
if _, err := fmt.Fprint(os.Stderr, prompt); err != nil {
return "", xerrors.Errorf("write error: %w", err)
return "", fmt.Errorf("write error: %w", err)
}
b, err := terminal.ReadPassword(int(syscall.Stdin))
b, err := term.ReadPassword(int(syscall.Stdin))
if err != nil {
return "", xerrors.Errorf("read error: %w", err)
return "", fmt.Errorf("read error: %w", err)
}
if _, err := fmt.Fprintln(os.Stderr); err != nil {
return "", xerrors.Errorf("write error: %w", err)
return "", fmt.Errorf("write error: %w", err)
}
return string(b), nil
}

View File

@@ -6,10 +6,9 @@ import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"time"
"golang.org/x/xerrors"
)
// DecodeWithoutVerify decodes the JWT string and returns the claims.
@@ -17,18 +16,18 @@ import (
func DecodeWithoutVerify(s string) (*Claims, error) {
payload, err := DecodePayloadAsRawJSON(s)
if err != nil {
return nil, xerrors.Errorf("could not decode the payload: %w", err)
return nil, fmt.Errorf("could not decode the payload: %w", err)
}
var claims struct {
Subject string `json:"sub,omitempty"`
ExpiresAt int64 `json:"exp,omitempty"`
}
if err := json.NewDecoder(bytes.NewReader(payload)).Decode(&claims); err != nil {
return nil, xerrors.Errorf("could not decode the json of token: %w", err)
return nil, fmt.Errorf("could not decode the json of token: %w", err)
}
var prettyJson bytes.Buffer
if err := json.Indent(&prettyJson, payload, "", " "); err != nil {
return nil, xerrors.Errorf("could not indent the json of token: %w", err)
return nil, fmt.Errorf("could not indent the json of token: %w", err)
}
return &Claims{
Subject: claims.Subject,
@@ -41,11 +40,11 @@ func DecodeWithoutVerify(s string) (*Claims, error) {
func DecodePayloadAsPrettyJSON(s string) (string, error) {
payload, err := DecodePayloadAsRawJSON(s)
if err != nil {
return "", xerrors.Errorf("could not decode the payload: %w", err)
return "", fmt.Errorf("could not decode the payload: %w", err)
}
var prettyJson bytes.Buffer
if err := json.Indent(&prettyJson, payload, "", " "); err != nil {
return "", xerrors.Errorf("could not indent the json of token: %w", err)
return "", fmt.Errorf("could not indent the json of token: %w", err)
}
return prettyJson.String(), nil
}
@@ -54,11 +53,11 @@ func DecodePayloadAsPrettyJSON(s string) (string, error) {
func DecodePayloadAsRawJSON(s string) ([]byte, error) {
parts := strings.SplitN(s, ".", 3)
if len(parts) != 3 {
return nil, xerrors.Errorf("wants %d segments but got %d segments", 3, len(parts))
return nil, fmt.Errorf("wants %d segments but got %d segments", 3, len(parts))
}
payloadJSON, err := decodePayload(parts[1])
if err != nil {
return nil, xerrors.Errorf("could not decode the payload: %w", err)
return nil, fmt.Errorf("could not decode the payload: %w", err)
}
return payloadJSON, nil
}
@@ -66,7 +65,7 @@ func DecodePayloadAsRawJSON(s string) ([]byte, error) {
func decodePayload(payload string) ([]byte, error) {
b, err := base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(payload)
if err != nil {
return nil, xerrors.Errorf("invalid base64: %w", err)
return nil, fmt.Errorf("invalid base64: %w", err)
}
return b, nil
}

73
pkg/jwt/mock_Clock.go Normal file
View File

@@ -0,0 +1,73 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package jwt
import (
time "time"
mock "github.com/stretchr/testify/mock"
)
// MockClock is an autogenerated mock type for the Clock type
type MockClock struct {
mock.Mock
}
type MockClock_Expecter struct {
mock *mock.Mock
}
func (_m *MockClock) EXPECT() *MockClock_Expecter {
return &MockClock_Expecter{mock: &_m.Mock}
}
// Now provides a mock function with given fields:
func (_m *MockClock) Now() time.Time {
ret := _m.Called()
var r0 time.Time
if rf, ok := ret.Get(0).(func() time.Time); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(time.Time)
}
return r0
}
// MockClock_Now_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Now'
type MockClock_Now_Call struct {
*mock.Call
}
// Now is a helper method to define mock.On call
func (_e *MockClock_Expecter) Now() *MockClock_Now_Call {
return &MockClock_Now_Call{Call: _e.mock.On("Now")}
}
func (_c *MockClock_Now_Call) Run(run func()) *MockClock_Now_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockClock_Now_Call) Return(_a0 time.Time) *MockClock_Now_Call {
_c.Call.Return(_a0)
return _c
}
type mockConstructorTestingTNewMockClock interface {
mock.TestingT
Cleanup(func())
}
// NewMockClock creates a new instance of MockClock. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockClock(t mockConstructorTestingTNewMockClock) *MockClock {
mock := &MockClock{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -1,21 +1,35 @@
package kubeconfig
package loader
import (
"errors"
"fmt"
"strings"
"golang.org/x/xerrors"
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/kubeconfig"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
)
func (*Kubeconfig) GetCurrentAuthProvider(explicitFilename string, contextName ContextName, userName UserName) (*AuthProvider, error) {
var Set = wire.NewSet(
wire.Struct(new(Loader), "*"),
wire.Bind(new(Interface), new(*Loader)),
)
type Interface interface {
GetCurrentAuthProvider(explicitFilename string, contextName kubeconfig.ContextName, userName kubeconfig.UserName) (*kubeconfig.AuthProvider, error)
}
type Loader struct{}
func (Loader) GetCurrentAuthProvider(explicitFilename string, contextName kubeconfig.ContextName, userName kubeconfig.UserName) (*kubeconfig.AuthProvider, error) {
config, err := loadByDefaultRules(explicitFilename)
if err != nil {
return nil, xerrors.Errorf("could not load the kubeconfig: %w", err)
return nil, fmt.Errorf("could not load the kubeconfig: %w", err)
}
auth, err := findCurrentAuthProvider(config, contextName, userName)
if err != nil {
return nil, xerrors.Errorf("could not find the current auth provider: %w", err)
return nil, fmt.Errorf("could not find the current auth provider: %w", err)
}
return auth, nil
}
@@ -25,7 +39,7 @@ func loadByDefaultRules(explicitFilename string) (*api.Config, error) {
rules.ExplicitPath = explicitFilename
config, err := rules.Load()
if err != nil {
return nil, xerrors.Errorf("load error: %w", err)
return nil, fmt.Errorf("load error: %w", err)
}
return config, err
}
@@ -34,29 +48,29 @@ func loadByDefaultRules(explicitFilename string) (*api.Config, error) {
// If contextName is given, this returns the user of the context.
// If userName is given, this ignores the context and returns the user.
// If any context or user is not found, this returns an error.
func findCurrentAuthProvider(config *api.Config, contextName ContextName, userName UserName) (*AuthProvider, error) {
func findCurrentAuthProvider(config *api.Config, contextName kubeconfig.ContextName, userName kubeconfig.UserName) (*kubeconfig.AuthProvider, error) {
if userName == "" {
if contextName == "" {
contextName = ContextName(config.CurrentContext)
contextName = kubeconfig.ContextName(config.CurrentContext)
}
contextNode, ok := config.Contexts[string(contextName)]
if !ok {
return nil, xerrors.Errorf("context %s does not exist", contextName)
return nil, fmt.Errorf("context %s does not exist", contextName)
}
userName = UserName(contextNode.AuthInfo)
userName = kubeconfig.UserName(contextNode.AuthInfo)
}
userNode, ok := config.AuthInfos[string(userName)]
if !ok {
return nil, xerrors.Errorf("user %s does not exist", userName)
return nil, fmt.Errorf("user %s does not exist", userName)
}
if userNode.AuthProvider == nil {
return nil, xerrors.New("auth-provider is missing")
return nil, errors.New("auth-provider is missing")
}
if userNode.AuthProvider.Name != "oidc" {
return nil, xerrors.Errorf("auth-provider.name must be oidc but is %s", userNode.AuthProvider.Name)
return nil, fmt.Errorf("auth-provider.name must be oidc but is %s", userNode.AuthProvider.Name)
}
if userNode.AuthProvider.Config == nil {
return nil, xerrors.New("auth-provider.config is missing")
return nil, errors.New("auth-provider.config is missing")
}
m := userNode.AuthProvider.Config
@@ -64,7 +78,7 @@ func findCurrentAuthProvider(config *api.Config, contextName ContextName, userNa
if m["extra-scopes"] != "" {
extraScopes = strings.Split(m["extra-scopes"], ",")
}
return &AuthProvider{
return &kubeconfig.AuthProvider{
LocationOfOrigin: userNode.LocationOfOrigin,
UserName: userName,
ContextName: contextName,

View File

@@ -1,17 +1,17 @@
package kubeconfig
package loader
import (
"os"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/int128/kubelogin/pkg/kubeconfig"
"k8s.io/client-go/tools/clientcmd/api"
)
func Test_loadByDefaultRules(t *testing.T) {
t.Run("google.yaml>keycloak.yaml", func(t *testing.T) {
setenv(t, "KUBECONFIG", "testdata/kubeconfig.google.yaml"+string(os.PathListSeparator)+"testdata/kubeconfig.keycloak.yaml")
defer unsetenv(t, "KUBECONFIG")
t.Setenv("KUBECONFIG", "testdata/kubeconfig.google.yaml"+string(os.PathListSeparator)+"testdata/kubeconfig.keycloak.yaml")
config, err := loadByDefaultRules("")
if err != nil {
@@ -35,8 +35,7 @@ func Test_loadByDefaultRules(t *testing.T) {
})
t.Run("keycloak.yaml>google.yaml", func(t *testing.T) {
setenv(t, "KUBECONFIG", "testdata/kubeconfig.keycloak.yaml"+string(os.PathListSeparator)+"testdata/kubeconfig.google.yaml")
defer unsetenv(t, "KUBECONFIG")
t.Setenv("KUBECONFIG", "testdata/kubeconfig.keycloak.yaml"+string(os.PathListSeparator)+"testdata/kubeconfig.google.yaml")
config, err := loadByDefaultRules("")
if err != nil {
@@ -60,20 +59,6 @@ func Test_loadByDefaultRules(t *testing.T) {
})
}
func setenv(t *testing.T, key, value string) {
t.Helper()
if err := os.Setenv(key, value); err != nil {
t.Fatalf("Could not set the env var %s=%s: %s", key, value, err)
}
}
func unsetenv(t *testing.T, key string) {
t.Helper()
if err := os.Unsetenv(key); err != nil {
t.Fatalf("Could not unset the env var %s: %s", key, err)
}
}
func Test_findCurrentAuthProvider(t *testing.T) {
t.Run("CurrentContext", func(t *testing.T) {
got, err := findCurrentAuthProvider(&api.Config{
@@ -105,7 +90,7 @@ func Test_findCurrentAuthProvider(t *testing.T) {
if err != nil {
t.Fatalf("Could not find the current auth: %s", err)
}
want := &AuthProvider{
want := &kubeconfig.AuthProvider{
LocationOfOrigin: "/path/to/kubeconfig",
UserName: "theUser",
ContextName: "theContext",
@@ -145,7 +130,7 @@ func Test_findCurrentAuthProvider(t *testing.T) {
if err != nil {
t.Fatalf("Could not find the current auth: %s", err)
}
want := &AuthProvider{
want := &kubeconfig.AuthProvider{
LocationOfOrigin: "/path/to/kubeconfig",
UserName: "theUser",
ContextName: "theContext",
@@ -173,7 +158,7 @@ func Test_findCurrentAuthProvider(t *testing.T) {
if err != nil {
t.Fatalf("Could not find the current auth: %s", err)
}
want := &AuthProvider{
want := &kubeconfig.AuthProvider{
LocationOfOrigin: "/path/to/kubeconfig",
UserName: "theUser",
IDPIssuerURL: "https://accounts.google.com",

View File

@@ -0,0 +1,84 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package loader
import (
kubeconfig "github.com/int128/kubelogin/pkg/kubeconfig"
mock "github.com/stretchr/testify/mock"
)
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// GetCurrentAuthProvider provides a mock function with given fields: explicitFilename, contextName, userName
func (_m *MockInterface) GetCurrentAuthProvider(explicitFilename string, contextName kubeconfig.ContextName, userName kubeconfig.UserName) (*kubeconfig.AuthProvider, error) {
ret := _m.Called(explicitFilename, contextName, userName)
var r0 *kubeconfig.AuthProvider
if rf, ok := ret.Get(0).(func(string, kubeconfig.ContextName, kubeconfig.UserName) *kubeconfig.AuthProvider); ok {
r0 = rf(explicitFilename, contextName, userName)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*kubeconfig.AuthProvider)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, kubeconfig.ContextName, kubeconfig.UserName) error); ok {
r1 = rf(explicitFilename, contextName, userName)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockInterface_GetCurrentAuthProvider_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCurrentAuthProvider'
type MockInterface_GetCurrentAuthProvider_Call struct {
*mock.Call
}
// GetCurrentAuthProvider is a helper method to define mock.On call
// - explicitFilename string
// - contextName kubeconfig.ContextName
// - userName kubeconfig.UserName
func (_e *MockInterface_Expecter) GetCurrentAuthProvider(explicitFilename interface{}, contextName interface{}, userName interface{}) *MockInterface_GetCurrentAuthProvider_Call {
return &MockInterface_GetCurrentAuthProvider_Call{Call: _e.mock.On("GetCurrentAuthProvider", explicitFilename, contextName, userName)}
}
func (_c *MockInterface_GetCurrentAuthProvider_Call) Run(run func(explicitFilename string, contextName kubeconfig.ContextName, userName kubeconfig.UserName)) *MockInterface_GetCurrentAuthProvider_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(string), args[1].(kubeconfig.ContextName), args[2].(kubeconfig.UserName))
})
return _c
}
func (_c *MockInterface_GetCurrentAuthProvider_Call) Return(_a0 *kubeconfig.AuthProvider, _a1 error) *MockInterface_GetCurrentAuthProvider_Call {
_c.Call.Return(_a0, _a1)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -1,23 +1,5 @@
package kubeconfig
import (
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/adaptors/logger"
)
//go:generate mockgen -destination mock_kubeconfig/mock_kubeconfig.go github.com/int128/kubelogin/pkg/adaptors/kubeconfig Interface
// Set provides an implementation and interface for Kubeconfig.
var Set = wire.NewSet(
wire.Struct(new(Kubeconfig), "*"),
wire.Bind(new(Interface), new(*Kubeconfig)),
)
type Interface interface {
GetCurrentAuthProvider(explicitFilename string, contextName ContextName, userName UserName) (*AuthProvider, error)
UpdateAuthProvider(auth *AuthProvider) error
}
// ContextName represents name of a context.
type ContextName string
@@ -39,7 +21,3 @@ type AuthProvider struct {
IDToken string // (optional) id-token
RefreshToken string // (optional) refresh-token
}
type Kubeconfig struct {
Logger logger.Interface
}

View File

@@ -0,0 +1,73 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package writer
import (
kubeconfig "github.com/int128/kubelogin/pkg/kubeconfig"
mock "github.com/stretchr/testify/mock"
)
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// UpdateAuthProvider provides a mock function with given fields: p
func (_m *MockInterface) UpdateAuthProvider(p kubeconfig.AuthProvider) error {
ret := _m.Called(p)
var r0 error
if rf, ok := ret.Get(0).(func(kubeconfig.AuthProvider) error); ok {
r0 = rf(p)
} else {
r0 = ret.Error(0)
}
return r0
}
// MockInterface_UpdateAuthProvider_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateAuthProvider'
type MockInterface_UpdateAuthProvider_Call struct {
*mock.Call
}
// UpdateAuthProvider is a helper method to define mock.On call
// - p kubeconfig.AuthProvider
func (_e *MockInterface_Expecter) UpdateAuthProvider(p interface{}) *MockInterface_UpdateAuthProvider_Call {
return &MockInterface_UpdateAuthProvider_Call{Call: _e.mock.On("UpdateAuthProvider", p)}
}
func (_c *MockInterface_UpdateAuthProvider_Call) Run(run func(p kubeconfig.AuthProvider)) *MockInterface_UpdateAuthProvider_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(kubeconfig.AuthProvider))
})
return _c
}
func (_c *MockInterface_UpdateAuthProvider_Call) Return(_a0 error) *MockInterface_UpdateAuthProvider_Call {
_c.Call.Return(_a0)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -1,35 +1,48 @@
package kubeconfig
package writer
import (
"fmt"
"strings"
"golang.org/x/xerrors"
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/kubeconfig"
"k8s.io/client-go/tools/clientcmd"
)
func (*Kubeconfig) UpdateAuthProvider(p *AuthProvider) error {
var Set = wire.NewSet(
wire.Struct(new(Writer), "*"),
wire.Bind(new(Interface), new(*Writer)),
)
type Interface interface {
UpdateAuthProvider(p kubeconfig.AuthProvider) error
}
type Writer struct{}
func (Writer) UpdateAuthProvider(p kubeconfig.AuthProvider) error {
config, err := clientcmd.LoadFromFile(p.LocationOfOrigin)
if err != nil {
return xerrors.Errorf("could not load %s: %w", p.LocationOfOrigin, err)
return fmt.Errorf("could not load %s: %w", p.LocationOfOrigin, err)
}
userNode, ok := config.AuthInfos[string(p.UserName)]
if !ok {
return xerrors.Errorf("user %s does not exist", p.UserName)
return fmt.Errorf("user %s does not exist", p.UserName)
}
if userNode.AuthProvider == nil {
return xerrors.Errorf("auth-provider is missing")
return fmt.Errorf("auth-provider is missing")
}
if userNode.AuthProvider.Name != "oidc" {
return xerrors.Errorf("auth-provider must be oidc but is %s", userNode.AuthProvider.Name)
return fmt.Errorf("auth-provider must be oidc but is %s", userNode.AuthProvider.Name)
}
copyAuthProviderConfig(p, userNode.AuthProvider.Config)
if err := clientcmd.WriteToFile(*config, p.LocationOfOrigin); err != nil {
return xerrors.Errorf("could not update %s: %w", p.LocationOfOrigin, err)
return fmt.Errorf("could not update %s: %w", p.LocationOfOrigin, err)
}
return nil
}
func copyAuthProviderConfig(p *AuthProvider, m map[string]string) {
func copyAuthProviderConfig(p kubeconfig.AuthProvider, m map[string]string) {
setOrDeleteKey(m, "idp-issuer-url", p.IDPIssuerURL)
setOrDeleteKey(m, "client-id", p.ClientID)
setOrDeleteKey(m, "client-secret", p.ClientSecret)

View File

@@ -1,25 +1,22 @@
package kubeconfig
package writer
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/int128/kubelogin/pkg/kubeconfig"
)
func TestKubeconfig_UpdateAuth(t *testing.T) {
var k Kubeconfig
var w Writer
t.Run("MinimumKeys", func(t *testing.T) {
f := newKubeconfigFile(t)
defer func() {
if err := os.Remove(f.Name()); err != nil {
t.Errorf("Could not remove the temp file: %s", err)
}
}()
if err := k.UpdateAuthProvider(&AuthProvider{
LocationOfOrigin: f.Name(),
if err := w.UpdateAuthProvider(kubeconfig.AuthProvider{
LocationOfOrigin: f,
UserName: "google",
IDPIssuerURL: "https://accounts.google.com",
ClientID: "GOOGLE_CLIENT_ID",
@@ -29,7 +26,7 @@ func TestKubeconfig_UpdateAuth(t *testing.T) {
}); err != nil {
t.Fatalf("Could not update auth: %s", err)
}
b, err := ioutil.ReadFile(f.Name())
b, err := ioutil.ReadFile(f)
if err != nil {
t.Fatalf("Could not read kubeconfig: %s", err)
}
@@ -60,13 +57,8 @@ users:
t.Run("FullKeys", func(t *testing.T) {
f := newKubeconfigFile(t)
defer func() {
if err := os.Remove(f.Name()); err != nil {
t.Errorf("Could not remove the temp file: %s", err)
}
}()
if err := k.UpdateAuthProvider(&AuthProvider{
LocationOfOrigin: f.Name(),
if err := w.UpdateAuthProvider(kubeconfig.AuthProvider{
LocationOfOrigin: f,
UserName: "google",
IDPIssuerURL: "https://accounts.google.com",
ClientID: "GOOGLE_CLIENT_ID",
@@ -79,7 +71,7 @@ users:
}); err != nil {
t.Fatalf("Could not update auth: %s", err)
}
b, err := ioutil.ReadFile(f.Name())
b, err := ioutil.ReadFile(f)
if err != nil {
t.Fatalf("Could not read kubeconfig: %s", err)
}
@@ -112,8 +104,8 @@ users:
})
}
func newKubeconfigFile(t *testing.T) *os.File {
content := `apiVersion: v1
const kubeconfigContent = `
apiVersion: v1
clusters: []
kind: Config
preferences: {}
@@ -123,13 +115,12 @@ users:
auth-provider:
config:
idp-issuer-url: https://accounts.google.com
name: oidc`
f, err := ioutil.TempFile("", "kubeconfig")
if err != nil {
t.Fatalf("Could not create a file: %s", err)
}
defer f.Close()
if _, err := f.Write([]byte(content)); err != nil {
name: oidc
`
func newKubeconfigFile(t *testing.T) string {
f := filepath.Join(t.TempDir(), "kubeconfig")
if err := os.WriteFile(f, []byte(kubeconfigContent), 0644); err != nil {
t.Fatalf("Could not write kubeconfig: %s", err)
}
return f

3
pkg/mocks.go Normal file
View File

@@ -0,0 +1,3 @@
package pkg
//go:generate mockery --all --inpackage --with-expecter

View File

@@ -1,23 +1,20 @@
package oidcclient
package client
import (
"context"
"fmt"
"net/http"
"time"
gooidc "github.com/coreos/go-oidc"
"github.com/int128/kubelogin/pkg/adaptors/clock"
"github.com/int128/kubelogin/pkg/adaptors/logger"
"github.com/int128/kubelogin/pkg/jwt"
gooidc "github.com/coreos/go-oidc/v3/oidc"
"github.com/int128/kubelogin/pkg/infrastructure/clock"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
"github.com/int128/kubelogin/pkg/oidc"
"github.com/int128/kubelogin/pkg/pkce"
"github.com/int128/oauth2cli"
"golang.org/x/oauth2"
"golang.org/x/xerrors"
)
//go:generate mockgen -destination mock_oidcclient/mock_oidcclient.go github.com/int128/kubelogin/pkg/adaptors/oidcclient Interface
type Interface interface {
GetAuthCodeURL(in AuthCodeURLInput) string
ExchangeAuthCode(ctx context.Context, in ExchangeAuthCodeInput) (*oidc.TokenSet, error)
@@ -88,7 +85,7 @@ func (c *client) GetTokenByAuthCode(ctx context.Context, in GetTokenByAuthCodeIn
}
token, err := oauth2cli.GetToken(ctx, config)
if err != nil {
return nil, xerrors.Errorf("oauth2 error: %w", err)
return nil, fmt.Errorf("oauth2 error: %w", err)
}
return c.verifyToken(ctx, token, in.Nonce)
}
@@ -109,7 +106,7 @@ func (c *client) ExchangeAuthCode(ctx context.Context, in ExchangeAuthCodeInput)
opts := tokenRequestOptions(in.PKCEParams)
token, err := cfg.Exchange(ctx, in.Code, opts...)
if err != nil {
return nil, xerrors.Errorf("exchange error: %w", err)
return nil, fmt.Errorf("exchange error: %w", err)
}
return c.verifyToken(ctx, token, in.Nonce)
}
@@ -149,7 +146,7 @@ func (c *client) GetTokenByROPC(ctx context.Context, username, password string)
ctx = c.wrapContext(ctx)
token, err := c.oauth2Config.PasswordCredentialsToken(ctx, username, password)
if err != nil {
return nil, xerrors.Errorf("resource owner password credentials flow error: %w", err)
return nil, fmt.Errorf("resource owner password credentials flow error: %w", err)
}
return c.verifyToken(ctx, token, "")
}
@@ -164,7 +161,7 @@ func (c *client) Refresh(ctx context.Context, refreshToken string) (*oidc.TokenS
source := c.oauth2Config.TokenSource(ctx, currentToken)
token, err := source.Token()
if err != nil {
return nil, xerrors.Errorf("could not refresh the token: %w", err)
return nil, fmt.Errorf("could not refresh the token: %w", err)
}
return c.verifyToken(ctx, token, "")
}
@@ -174,27 +171,18 @@ func (c *client) Refresh(ctx context.Context, refreshToken string) (*oidc.TokenS
func (c *client) verifyToken(ctx context.Context, token *oauth2.Token, nonce string) (*oidc.TokenSet, error) {
idToken, ok := token.Extra("id_token").(string)
if !ok {
return nil, xerrors.Errorf("id_token is missing in the token response: %s", token)
return nil, fmt.Errorf("id_token is missing in the token response: %s", token)
}
verifier := c.provider.Verifier(&gooidc.Config{ClientID: c.oauth2Config.ClientID, Now: c.clock.Now})
verifiedIDToken, err := verifier.Verify(ctx, idToken)
if err != nil {
return nil, xerrors.Errorf("could not verify the ID token: %w", err)
return nil, fmt.Errorf("could not verify the ID token: %w", err)
}
if nonce != "" && nonce != verifiedIDToken.Nonce {
return nil, xerrors.Errorf("nonce did not match (wants %s but got %s)", nonce, verifiedIDToken.Nonce)
}
pretty, err := jwt.DecodePayloadAsPrettyJSON(idToken)
if err != nil {
return nil, xerrors.Errorf("could not decode the token: %w", err)
return nil, fmt.Errorf("nonce did not match (wants %s but got %s)", nonce, verifiedIDToken.Nonce)
}
return &oidc.TokenSet{
IDToken: idToken,
IDTokenClaims: jwt.Claims{
Subject: verifiedIDToken.Subject,
Expiry: verifiedIDToken.Expiry,
Pretty: pretty,
},
IDToken: idToken,
RefreshToken: token.RefreshToken,
}, nil
}

View File

@@ -0,0 +1,89 @@
// Package client provides a client of OpenID Connect.
package client
import (
"context"
"fmt"
"net/http"
gooidc "github.com/coreos/go-oidc/v3/oidc"
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/infrastructure/clock"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
"github.com/int128/kubelogin/pkg/oidc"
"github.com/int128/kubelogin/pkg/oidc/client/logging"
"github.com/int128/kubelogin/pkg/pkce"
"github.com/int128/kubelogin/pkg/tlsclientconfig"
"github.com/int128/kubelogin/pkg/tlsclientconfig/loader"
"golang.org/x/oauth2"
)
var Set = wire.NewSet(
wire.Struct(new(Factory), "*"),
wire.Bind(new(FactoryInterface), new(*Factory)),
)
type FactoryInterface interface {
New(ctx context.Context, p oidc.Provider, tlsClientConfig tlsclientconfig.Config) (Interface, error)
}
type Factory struct {
Loader loader.Loader
Clock clock.Interface
Logger logger.Interface
}
// New returns an instance of infrastructure.Interface with the given configuration.
func (f *Factory) New(ctx context.Context, p oidc.Provider, tlsClientConfig tlsclientconfig.Config) (Interface, error) {
rawTLSClientConfig, err := f.Loader.Load(tlsClientConfig)
if err != nil {
return nil, fmt.Errorf("could not load the TLS client config: %w", err)
}
baseTransport := &http.Transport{
TLSClientConfig: rawTLSClientConfig,
Proxy: http.ProxyFromEnvironment,
}
loggingTransport := &logging.Transport{
Base: baseTransport,
Logger: f.Logger,
}
httpClient := &http.Client{
Transport: loggingTransport,
}
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
provider, err := gooidc.NewProvider(ctx, p.IssuerURL)
if err != nil {
return nil, fmt.Errorf("oidc discovery error: %w", err)
}
supportedPKCEMethods, err := extractSupportedPKCEMethods(provider)
if err != nil {
return nil, fmt.Errorf("could not determine supported PKCE methods: %w", err)
}
if len(supportedPKCEMethods) == 0 && p.UsePKCE {
supportedPKCEMethods = []string{pkce.MethodS256}
}
return &client{
httpClient: httpClient,
provider: provider,
oauth2Config: oauth2.Config{
Endpoint: provider.Endpoint(),
ClientID: p.ClientID,
ClientSecret: p.ClientSecret,
Scopes: append(p.ExtraScopes, gooidc.ScopeOpenID),
},
clock: f.Clock,
logger: f.Logger,
supportedPKCEMethods: supportedPKCEMethods,
}, nil
}
func extractSupportedPKCEMethods(provider *gooidc.Provider) ([]string, error) {
var d struct {
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
}
if err := provider.Claims(&d); err != nil {
return nil, fmt.Errorf("invalid discovery document: %w", err)
}
return d.CodeChallengeMethodsSupported, nil
}

View File

@@ -4,7 +4,7 @@ import (
"net/http"
"net/http/httputil"
"github.com/int128/kubelogin/pkg/adaptors/logger"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
)
const (

View File

@@ -7,7 +7,6 @@ import (
"strings"
"testing"
"github.com/golang/mock/gomock"
"github.com/int128/kubelogin/pkg/testing/logger"
)
@@ -22,9 +21,6 @@ func (t *mockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
}
func TestLoggingTransport_RoundTrip(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
req := httptest.NewRequest("GET", "http://example.com/hello", nil)
resp, err := http.ReadResponse(bufio.NewReader(strings.NewReader(`HTTP/1.1 200 OK
Host: example.com

View File

@@ -0,0 +1,88 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package client
import (
context "context"
oidc "github.com/int128/kubelogin/pkg/oidc"
mock "github.com/stretchr/testify/mock"
tlsclientconfig "github.com/int128/kubelogin/pkg/tlsclientconfig"
)
// MockFactoryInterface is an autogenerated mock type for the FactoryInterface type
type MockFactoryInterface struct {
mock.Mock
}
type MockFactoryInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockFactoryInterface) EXPECT() *MockFactoryInterface_Expecter {
return &MockFactoryInterface_Expecter{mock: &_m.Mock}
}
// New provides a mock function with given fields: ctx, p, tlsClientConfig
func (_m *MockFactoryInterface) New(ctx context.Context, p oidc.Provider, tlsClientConfig tlsclientconfig.Config) (Interface, error) {
ret := _m.Called(ctx, p, tlsClientConfig)
var r0 Interface
if rf, ok := ret.Get(0).(func(context.Context, oidc.Provider, tlsclientconfig.Config) Interface); ok {
r0 = rf(ctx, p, tlsClientConfig)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(Interface)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, oidc.Provider, tlsclientconfig.Config) error); ok {
r1 = rf(ctx, p, tlsClientConfig)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockFactoryInterface_New_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'New'
type MockFactoryInterface_New_Call struct {
*mock.Call
}
// New is a helper method to define mock.On call
// - ctx context.Context
// - p oidc.Provider
// - tlsClientConfig tlsclientconfig.Config
func (_e *MockFactoryInterface_Expecter) New(ctx interface{}, p interface{}, tlsClientConfig interface{}) *MockFactoryInterface_New_Call {
return &MockFactoryInterface_New_Call{Call: _e.mock.On("New", ctx, p, tlsClientConfig)}
}
func (_c *MockFactoryInterface_New_Call) Run(run func(ctx context.Context, p oidc.Provider, tlsClientConfig tlsclientconfig.Config)) *MockFactoryInterface_New_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(oidc.Provider), args[2].(tlsclientconfig.Config))
})
return _c
}
func (_c *MockFactoryInterface_New_Call) Return(_a0 Interface, _a1 error) *MockFactoryInterface_New_Call {
_c.Call.Return(_a0, _a1)
return _c
}
type mockConstructorTestingTNewMockFactoryInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockFactoryInterface creates a new instance of MockFactoryInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockFactoryInterface(t mockConstructorTestingTNewMockFactoryInterface) *MockFactoryInterface {
mock := &MockFactoryInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,303 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package client
import (
context "context"
oidc "github.com/int128/kubelogin/pkg/oidc"
mock "github.com/stretchr/testify/mock"
)
// MockInterface is an autogenerated mock type for the Interface type
type MockInterface struct {
mock.Mock
}
type MockInterface_Expecter struct {
mock *mock.Mock
}
func (_m *MockInterface) EXPECT() *MockInterface_Expecter {
return &MockInterface_Expecter{mock: &_m.Mock}
}
// ExchangeAuthCode provides a mock function with given fields: ctx, in
func (_m *MockInterface) ExchangeAuthCode(ctx context.Context, in ExchangeAuthCodeInput) (*oidc.TokenSet, error) {
ret := _m.Called(ctx, in)
var r0 *oidc.TokenSet
if rf, ok := ret.Get(0).(func(context.Context, ExchangeAuthCodeInput) *oidc.TokenSet); ok {
r0 = rf(ctx, in)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*oidc.TokenSet)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, ExchangeAuthCodeInput) error); ok {
r1 = rf(ctx, in)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockInterface_ExchangeAuthCode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ExchangeAuthCode'
type MockInterface_ExchangeAuthCode_Call struct {
*mock.Call
}
// ExchangeAuthCode is a helper method to define mock.On call
// - ctx context.Context
// - in ExchangeAuthCodeInput
func (_e *MockInterface_Expecter) ExchangeAuthCode(ctx interface{}, in interface{}) *MockInterface_ExchangeAuthCode_Call {
return &MockInterface_ExchangeAuthCode_Call{Call: _e.mock.On("ExchangeAuthCode", ctx, in)}
}
func (_c *MockInterface_ExchangeAuthCode_Call) Run(run func(ctx context.Context, in ExchangeAuthCodeInput)) *MockInterface_ExchangeAuthCode_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(ExchangeAuthCodeInput))
})
return _c
}
func (_c *MockInterface_ExchangeAuthCode_Call) Return(_a0 *oidc.TokenSet, _a1 error) *MockInterface_ExchangeAuthCode_Call {
_c.Call.Return(_a0, _a1)
return _c
}
// GetAuthCodeURL provides a mock function with given fields: in
func (_m *MockInterface) GetAuthCodeURL(in AuthCodeURLInput) string {
ret := _m.Called(in)
var r0 string
if rf, ok := ret.Get(0).(func(AuthCodeURLInput) string); ok {
r0 = rf(in)
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// MockInterface_GetAuthCodeURL_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAuthCodeURL'
type MockInterface_GetAuthCodeURL_Call struct {
*mock.Call
}
// GetAuthCodeURL is a helper method to define mock.On call
// - in AuthCodeURLInput
func (_e *MockInterface_Expecter) GetAuthCodeURL(in interface{}) *MockInterface_GetAuthCodeURL_Call {
return &MockInterface_GetAuthCodeURL_Call{Call: _e.mock.On("GetAuthCodeURL", in)}
}
func (_c *MockInterface_GetAuthCodeURL_Call) Run(run func(in AuthCodeURLInput)) *MockInterface_GetAuthCodeURL_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(AuthCodeURLInput))
})
return _c
}
func (_c *MockInterface_GetAuthCodeURL_Call) Return(_a0 string) *MockInterface_GetAuthCodeURL_Call {
_c.Call.Return(_a0)
return _c
}
// GetTokenByAuthCode provides a mock function with given fields: ctx, in, localServerReadyChan
func (_m *MockInterface) GetTokenByAuthCode(ctx context.Context, in GetTokenByAuthCodeInput, localServerReadyChan chan<- string) (*oidc.TokenSet, error) {
ret := _m.Called(ctx, in, localServerReadyChan)
var r0 *oidc.TokenSet
if rf, ok := ret.Get(0).(func(context.Context, GetTokenByAuthCodeInput, chan<- string) *oidc.TokenSet); ok {
r0 = rf(ctx, in, localServerReadyChan)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*oidc.TokenSet)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, GetTokenByAuthCodeInput, chan<- string) error); ok {
r1 = rf(ctx, in, localServerReadyChan)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockInterface_GetTokenByAuthCode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenByAuthCode'
type MockInterface_GetTokenByAuthCode_Call struct {
*mock.Call
}
// GetTokenByAuthCode is a helper method to define mock.On call
// - ctx context.Context
// - in GetTokenByAuthCodeInput
// - localServerReadyChan chan<- string
func (_e *MockInterface_Expecter) GetTokenByAuthCode(ctx interface{}, in interface{}, localServerReadyChan interface{}) *MockInterface_GetTokenByAuthCode_Call {
return &MockInterface_GetTokenByAuthCode_Call{Call: _e.mock.On("GetTokenByAuthCode", ctx, in, localServerReadyChan)}
}
func (_c *MockInterface_GetTokenByAuthCode_Call) Run(run func(ctx context.Context, in GetTokenByAuthCodeInput, localServerReadyChan chan<- string)) *MockInterface_GetTokenByAuthCode_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(GetTokenByAuthCodeInput), args[2].(chan<- string))
})
return _c
}
func (_c *MockInterface_GetTokenByAuthCode_Call) Return(_a0 *oidc.TokenSet, _a1 error) *MockInterface_GetTokenByAuthCode_Call {
_c.Call.Return(_a0, _a1)
return _c
}
// GetTokenByROPC provides a mock function with given fields: ctx, username, password
func (_m *MockInterface) GetTokenByROPC(ctx context.Context, username string, password string) (*oidc.TokenSet, error) {
ret := _m.Called(ctx, username, password)
var r0 *oidc.TokenSet
if rf, ok := ret.Get(0).(func(context.Context, string, string) *oidc.TokenSet); ok {
r0 = rf(ctx, username, password)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*oidc.TokenSet)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
r1 = rf(ctx, username, password)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockInterface_GetTokenByROPC_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenByROPC'
type MockInterface_GetTokenByROPC_Call struct {
*mock.Call
}
// GetTokenByROPC is a helper method to define mock.On call
// - ctx context.Context
// - username string
// - password string
func (_e *MockInterface_Expecter) GetTokenByROPC(ctx interface{}, username interface{}, password interface{}) *MockInterface_GetTokenByROPC_Call {
return &MockInterface_GetTokenByROPC_Call{Call: _e.mock.On("GetTokenByROPC", ctx, username, password)}
}
func (_c *MockInterface_GetTokenByROPC_Call) Run(run func(ctx context.Context, username string, password string)) *MockInterface_GetTokenByROPC_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(string), args[2].(string))
})
return _c
}
func (_c *MockInterface_GetTokenByROPC_Call) Return(_a0 *oidc.TokenSet, _a1 error) *MockInterface_GetTokenByROPC_Call {
_c.Call.Return(_a0, _a1)
return _c
}
// Refresh provides a mock function with given fields: ctx, refreshToken
func (_m *MockInterface) Refresh(ctx context.Context, refreshToken string) (*oidc.TokenSet, error) {
ret := _m.Called(ctx, refreshToken)
var r0 *oidc.TokenSet
if rf, ok := ret.Get(0).(func(context.Context, string) *oidc.TokenSet); ok {
r0 = rf(ctx, refreshToken)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*oidc.TokenSet)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
r1 = rf(ctx, refreshToken)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// MockInterface_Refresh_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Refresh'
type MockInterface_Refresh_Call struct {
*mock.Call
}
// Refresh is a helper method to define mock.On call
// - ctx context.Context
// - refreshToken string
func (_e *MockInterface_Expecter) Refresh(ctx interface{}, refreshToken interface{}) *MockInterface_Refresh_Call {
return &MockInterface_Refresh_Call{Call: _e.mock.On("Refresh", ctx, refreshToken)}
}
func (_c *MockInterface_Refresh_Call) Run(run func(ctx context.Context, refreshToken string)) *MockInterface_Refresh_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(string))
})
return _c
}
func (_c *MockInterface_Refresh_Call) Return(_a0 *oidc.TokenSet, _a1 error) *MockInterface_Refresh_Call {
_c.Call.Return(_a0, _a1)
return _c
}
// SupportedPKCEMethods provides a mock function with given fields:
func (_m *MockInterface) SupportedPKCEMethods() []string {
ret := _m.Called()
var r0 []string
if rf, ok := ret.Get(0).(func() []string); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
return r0
}
// MockInterface_SupportedPKCEMethods_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SupportedPKCEMethods'
type MockInterface_SupportedPKCEMethods_Call struct {
*mock.Call
}
// SupportedPKCEMethods is a helper method to define mock.On call
func (_e *MockInterface_Expecter) SupportedPKCEMethods() *MockInterface_SupportedPKCEMethods_Call {
return &MockInterface_SupportedPKCEMethods_Call{Call: _e.mock.On("SupportedPKCEMethods")}
}
func (_c *MockInterface_SupportedPKCEMethods_Call) Run(run func()) *MockInterface_SupportedPKCEMethods_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *MockInterface_SupportedPKCEMethods_Call) Return(_a0 []string) *MockInterface_SupportedPKCEMethods_Call {
_c.Call.Return(_a0)
return _c
}
type mockConstructorTestingTNewMockInterface interface {
mock.TestingT
Cleanup(func())
}
// NewMockInterface creates a new instance of MockInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockInterface(t mockConstructorTestingTNewMockInterface) *MockInterface {
mock := &MockInterface{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -4,23 +4,34 @@ import (
"crypto/rand"
"encoding/base64"
"encoding/binary"
"fmt"
"github.com/int128/kubelogin/pkg/jwt"
"golang.org/x/xerrors"
)
// TokenSet represents an output DTO of
// Interface.GetTokenByAuthCode, Interface.GetTokenByROPC and Interface.Refresh.
// Provider represents an OIDC provider.
type Provider struct {
IssuerURL string
ClientID string
ClientSecret string // optional
ExtraScopes []string // optional
UsePKCE bool // optional
}
// TokenSet represents a set of ID token and refresh token.
type TokenSet struct {
IDToken string
RefreshToken string
IDTokenClaims jwt.Claims
IDToken string
RefreshToken string
}
func (ts TokenSet) DecodeWithoutVerify() (*jwt.Claims, error) {
return jwt.DecodeWithoutVerify(ts.IDToken)
}
func NewState() (string, error) {
b, err := random32()
if err != nil {
return "", xerrors.Errorf("could not generate a random: %w", err)
return "", fmt.Errorf("could not generate a random: %w", err)
}
return base64URLEncode(b), nil
}
@@ -28,7 +39,7 @@ func NewState() (string, error) {
func NewNonce() (string, error) {
b, err := random32()
if err != nil {
return "", xerrors.Errorf("could not generate a random: %w", err)
return "", fmt.Errorf("could not generate a random: %w", err)
}
return base64URLEncode(b), nil
}
@@ -36,7 +47,7 @@ func NewNonce() (string, error) {
func random32() ([]byte, error) {
b := make([]byte, 32)
if err := binary.Read(rand.Reader, binary.LittleEndian, b); err != nil {
return nil, xerrors.Errorf("read error: %w", err)
return nil, fmt.Errorf("read error: %w", err)
}
return b, nil
}

View File

@@ -7,15 +7,14 @@ import (
"crypto/sha256"
"encoding/base64"
"encoding/binary"
"golang.org/x/xerrors"
"fmt"
)
var Plain Params
const (
// code challenge methods defined as https://tools.ietf.org/html/rfc7636#section-4.3
methodS256 = "S256"
MethodS256 = "S256"
)
// Params represents a set of the PKCE parameters.
@@ -34,7 +33,7 @@ func (p Params) IsZero() bool {
// It returns Plain if no method is available.
func New(methods []string) (Params, error) {
for _, method := range methods {
if method == methodS256 {
if method == MethodS256 {
return NewS256()
}
}
@@ -45,7 +44,7 @@ func New(methods []string) (Params, error) {
func NewS256() (Params, error) {
b, err := random32()
if err != nil {
return Plain, xerrors.Errorf("could not generate a random: %w", err)
return Plain, fmt.Errorf("could not generate a random: %w", err)
}
return computeS256(b), nil
}
@@ -53,7 +52,7 @@ func NewS256() (Params, error) {
func random32() ([]byte, error) {
b := make([]byte, 32)
if err := binary.Read(rand.Reader, binary.LittleEndian, b); err != nil {
return nil, xerrors.Errorf("read error: %w", err)
return nil, fmt.Errorf("read error: %w", err)
}
return b, nil
}
@@ -64,7 +63,7 @@ func computeS256(b []byte) Params {
_, _ = s.Write([]byte(v))
return Params{
CodeChallenge: base64URLEncode(s.Sum(nil)),
CodeChallengeMethod: methodS256,
CodeChallengeMethod: MethodS256,
CodeVerifier: v,
}
}

View File

@@ -5,7 +5,7 @@ import (
"crypto/rsa"
"testing"
"github.com/dgrijalva/jwt-go"
"github.com/golang-jwt/jwt/v4"
)
var PrivateKey = generateKey(1024)

View File

@@ -3,7 +3,7 @@ package logger
import (
"fmt"
"github.com/int128/kubelogin/pkg/adaptors/logger"
"github.com/int128/kubelogin/pkg/infrastructure/logger"
"github.com/spf13/pflag"
)

View File

@@ -0,0 +1,72 @@
// Code generated by mockery v2.13.1. DO NOT EDIT.
package logger
import mock "github.com/stretchr/testify/mock"
// mockTestingLogger is an autogenerated mock type for the testingLogger type
type mockTestingLogger struct {
mock.Mock
}
type mockTestingLogger_Expecter struct {
mock *mock.Mock
}
func (_m *mockTestingLogger) EXPECT() *mockTestingLogger_Expecter {
return &mockTestingLogger_Expecter{mock: &_m.Mock}
}
// Logf provides a mock function with given fields: format, v
func (_m *mockTestingLogger) Logf(format string, v ...interface{}) {
var _ca []interface{}
_ca = append(_ca, format)
_ca = append(_ca, v...)
_m.Called(_ca...)
}
// mockTestingLogger_Logf_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Logf'
type mockTestingLogger_Logf_Call struct {
*mock.Call
}
// Logf is a helper method to define mock.On call
// - format string
// - v ...interface{}
func (_e *mockTestingLogger_Expecter) Logf(format interface{}, v ...interface{}) *mockTestingLogger_Logf_Call {
return &mockTestingLogger_Logf_Call{Call: _e.mock.On("Logf",
append([]interface{}{format}, v...)...)}
}
func (_c *mockTestingLogger_Logf_Call) Run(run func(format string, v ...interface{})) *mockTestingLogger_Logf_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-1)
for i, a := range args[1:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(string), variadicArgs...)
})
return _c
}
func (_c *mockTestingLogger_Logf_Call) Return() *mockTestingLogger_Logf_Call {
_c.Call.Return()
return _c
}
type mockConstructorTestingTnewMockTestingLogger interface {
mock.TestingT
Cleanup(func())
}
// newMockTestingLogger creates a new instance of mockTestingLogger. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func newMockTestingLogger(t mockConstructorTestingTnewMockTestingLogger) *mockTestingLogger {
mock := &mockTestingLogger{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -0,0 +1,11 @@
package tlsclientconfig
import "crypto/tls"
// Config represents a config for TLS client.
type Config struct {
CACertFilename []string
CACertData []string
SkipTLSVerify bool
Renegotiation tls.RenegotiationSupport
}

View File

@@ -0,0 +1,72 @@
// Package loader provides loading certificates from files or base64 encoded string.
package loader
import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
"github.com/google/wire"
"github.com/int128/kubelogin/pkg/tlsclientconfig"
)
// Set provides an implementation and interface.
var Set = wire.NewSet(
wire.Struct(new(Loader), "*"),
wire.Bind(new(Interface), new(*Loader)),
)
type Interface interface {
Load(config tlsclientconfig.Config) (*tls.Config, error)
}
// Loader represents a pool of certificates.
type Loader struct{}
func (l *Loader) Load(config tlsclientconfig.Config) (*tls.Config, error) {
rootCAs := x509.NewCertPool()
for _, f := range config.CACertFilename {
if err := addFile(rootCAs, f); err != nil {
return nil, fmt.Errorf("could not load the certificate from %s: %w", f, err)
}
}
for _, d := range config.CACertData {
if err := addBase64Encoded(rootCAs, d); err != nil {
return nil, fmt.Errorf("could not load the certificate: %w", err)
}
}
if len(rootCAs.Subjects()) == 0 {
// use the host's root CA set
rootCAs = nil
}
return &tls.Config{
RootCAs: rootCAs,
InsecureSkipVerify: config.SkipTLSVerify,
Renegotiation: config.Renegotiation,
}, nil
}
func addFile(p *x509.CertPool, filename string) error {
b, err := ioutil.ReadFile(filename)
if err != nil {
return fmt.Errorf("could not read: %w", err)
}
if !p.AppendCertsFromPEM(b) {
return errors.New("invalid certificate")
}
return nil
}
func addBase64Encoded(p *x509.CertPool, s string) error {
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return fmt.Errorf("could not decode base64: %w", err)
}
if !p.AppendCertsFromPEM(b) {
return errors.New("invalid certificate")
}
return nil
}

Some files were not shown because too many files have changed in this diff Show More