mirror of
https://github.com/kubernetes/client-go.git
synced 2026-06-30 14:05:24 +00:00
Compare commits
37 Commits
kubernetes
...
kubernetes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e4461f622 | ||
|
|
f2f85107ca | ||
|
|
60fd738f89 | ||
|
|
1f13a808da | ||
|
|
401c87eddd | ||
|
|
897ec2f639 | ||
|
|
e07adc6e69 | ||
|
|
e5bc2a7bbb | ||
|
|
5c54f12e94 | ||
|
|
11bffe824e | ||
|
|
8560813064 | ||
|
|
2d1fce8ff8 | ||
|
|
ab6fed13f4 | ||
|
|
cd89475a09 | ||
|
|
0bb1a137a4 | ||
|
|
94da772526 | ||
|
|
90da597c77 | ||
|
|
9aa389df39 | ||
|
|
61801dc04d | ||
|
|
389936a9c8 | ||
|
|
75756cae80 | ||
|
|
532187284b | ||
|
|
4fcb07e80e | ||
|
|
dc18462b71 | ||
|
|
60d2f9ee1b | ||
|
|
37fcf22e5b | ||
|
|
a2802ecd41 | ||
|
|
5e3044cdb8 | ||
|
|
15affbb73e | ||
|
|
a776f223c2 | ||
|
|
8e3c4b8b5c | ||
|
|
0243d85adf | ||
|
|
e9e677202c | ||
|
|
d0c8d510fb | ||
|
|
a6fa57c79c | ||
|
|
f8adda79b7 | ||
|
|
c7ec09eb4f |
174
Godeps/Godeps.json
generated
174
Godeps/Godeps.json
generated
@@ -68,23 +68,23 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/proto",
|
||||
"Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/ptypes",
|
||||
"Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/ptypes/any",
|
||||
"Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/ptypes/duration",
|
||||
"Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/ptypes/timestamp",
|
||||
"Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/btree",
|
||||
@@ -156,7 +156,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/json-iterator/go",
|
||||
"Rev": "2ddf6d758266fcb080a4f9e054b9f292c85e6798"
|
||||
"Rev": "f2b4162afba35581b6d4a50d3b8f34e33c144682"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/modern-go/concurrent",
|
||||
@@ -268,327 +268,327 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/admissionregistration/v1alpha1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/admissionregistration/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/apps/v1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/apps/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/apps/v1beta2",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/authentication/v1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/authentication/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/authorization/v1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/authorization/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/autoscaling/v1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/autoscaling/v2beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/batch/v1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/batch/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/batch/v2alpha1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/certificates/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/core/v1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/events/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/extensions/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/imagepolicy/v1alpha1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/networking/v1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/policy/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/rbac/v1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/rbac/v1alpha1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/rbac/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/scheduling/v1alpha1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/scheduling/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/settings/v1alpha1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/storage/v1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/storage/v1alpha1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api/storage/v1beta1",
|
||||
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
|
||||
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/fields",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/labels",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/selection",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/types",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/cache",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/clock",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/framer",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/version",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/watch",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
|
||||
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
|
||||
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
|
||||
"Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5"
|
||||
"Rev": "91cfa479c814065e420cee7ed227db0f63a5854e"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
17
SECURITY_CONTACTS
Normal file
17
SECURITY_CONTACTS
Normal file
@@ -0,0 +1,17 @@
|
||||
# Defined below are the security contacts for this repo.
|
||||
#
|
||||
# They are the contact point for the Product Security Team to reach out
|
||||
# to for triaging and handling of incoming issues.
|
||||
#
|
||||
# The below names agree to abide by the
|
||||
# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy)
|
||||
# and will be removed and replaced if they violate that agreement.
|
||||
#
|
||||
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
|
||||
# INSTRUCTIONS AT https://kubernetes.io/security/
|
||||
|
||||
cjcullen
|
||||
jessfraz
|
||||
liggitt
|
||||
philips
|
||||
tallclair
|
||||
26
pkg/apis/clientauthentication/v1beta1/conversion.go
Normal file
26
pkg/apis/clientauthentication/v1beta1/conversion.go
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
clientauthentication "k8s.io/client-go/pkg/apis/clientauthentication"
|
||||
)
|
||||
|
||||
func Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
23
pkg/apis/clientauthentication/v1beta1/doc.go
Normal file
23
pkg/apis/clientauthentication/v1beta1/doc.go
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/client-go/pkg/apis/clientauthentication
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
|
||||
// +groupName=client.authentication.k8s.io
|
||||
package v1beta1 // import "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
55
pkg/apis/clientauthentication/v1beta1/register.go
Normal file
55
pkg/apis/clientauthentication/v1beta1/register.go
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "client.authentication.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
// We only register manually written functions here. The registration of the
|
||||
// generated functions takes place in the generated files. The separation
|
||||
// makes the code compile even when the generated files are missing.
|
||||
localSchemeBuilder.Register(addKnownTypes)
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&ExecCredential{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
59
pkg/apis/clientauthentication/v1beta1/types.go
Normal file
59
pkg/apis/clientauthentication/v1beta1/types.go
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ExecCredentials is used by exec-based plugins to communicate credentials to
|
||||
// HTTP transports.
|
||||
type ExecCredential struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// Spec holds information passed to the plugin by the transport. This contains
|
||||
// request and runtime specific information, such as if the session is interactive.
|
||||
Spec ExecCredentialSpec `json:"spec,omitempty"`
|
||||
|
||||
// Status is filled in by the plugin and holds the credentials that the transport
|
||||
// should use to contact the API.
|
||||
// +optional
|
||||
Status *ExecCredentialStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// ExecCredenitalSpec holds request and runtime specific information provided by
|
||||
// the transport.
|
||||
type ExecCredentialSpec struct{}
|
||||
|
||||
// ExecCredentialStatus holds credentials for the transport to use.
|
||||
//
|
||||
// Token and ClientKeyData are sensitive fields. This data should only be
|
||||
// transmitted in-memory between client and exec plugin process. Exec plugin
|
||||
// itself should at least be protected via file permissions.
|
||||
type ExecCredentialStatus struct {
|
||||
// ExpirationTimestamp indicates a time when the provided credentials expire.
|
||||
// +optional
|
||||
ExpirationTimestamp *metav1.Time `json:"expirationTimestamp,omitempty"`
|
||||
// Token is a bearer token used by the client for request authentication.
|
||||
Token string `json:"token,omitempty"`
|
||||
// PEM-encoded client TLS certificates (including intermediates, if any).
|
||||
ClientCertificateData string `json:"clientCertificateData,omitempty"`
|
||||
// PEM-encoded private key for the above certificate.
|
||||
ClientKeyData string `json:"clientKeyData,omitempty"`
|
||||
}
|
||||
114
pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go
Normal file
114
pkg/apis/clientauthentication/v1beta1/zz_generated.conversion.go
Normal file
@@ -0,0 +1,114 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
clientauthentication "k8s.io/client-go/pkg/apis/clientauthentication"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
return scheme.AddGeneratedConversionFuncs(
|
||||
Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential,
|
||||
Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential,
|
||||
Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec,
|
||||
Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec,
|
||||
Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus,
|
||||
Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus,
|
||||
)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in *ExecCredential, out *clientauthentication.ExecCredential, s conversion.Scope) error {
|
||||
if err := Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Status = (*clientauthentication.ExecCredentialStatus)(unsafe.Pointer(in.Status))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in *ExecCredential, out *clientauthentication.ExecCredential, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ExecCredential_To_clientauthentication_ExecCredential(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in *clientauthentication.ExecCredential, out *ExecCredential, s conversion.Scope) error {
|
||||
if err := Convert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Status = (*ExecCredentialStatus)(unsafe.Pointer(in.Status))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential is an autogenerated conversion function.
|
||||
func Convert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in *clientauthentication.ExecCredential, out *ExecCredential, s conversion.Scope) error {
|
||||
return autoConvert_clientauthentication_ExecCredential_To_v1beta1_ExecCredential(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in *ExecCredentialSpec, out *clientauthentication.ExecCredentialSpec, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in *ExecCredentialSpec, out *clientauthentication.ExecCredentialSpec, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ExecCredentialSpec_To_clientauthentication_ExecCredentialSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_clientauthentication_ExecCredentialSpec_To_v1beta1_ExecCredentialSpec(in *clientauthentication.ExecCredentialSpec, out *ExecCredentialSpec, s conversion.Scope) error {
|
||||
// WARNING: in.Response requires manual conversion: does not exist in peer-type
|
||||
// WARNING: in.Interactive requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error {
|
||||
out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp))
|
||||
out.Token = in.Token
|
||||
out.ClientCertificateData = in.ClientCertificateData
|
||||
out.ClientKeyData = in.ClientKeyData
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in *ExecCredentialStatus, out *clientauthentication.ExecCredentialStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ExecCredentialStatus_To_clientauthentication_ExecCredentialStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error {
|
||||
out.ExpirationTimestamp = (*v1.Time)(unsafe.Pointer(in.ExpirationTimestamp))
|
||||
out.Token = in.Token
|
||||
out.ClientCertificateData = in.ClientCertificateData
|
||||
out.ClientKeyData = in.ClientKeyData
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus is an autogenerated conversion function.
|
||||
func Convert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in *clientauthentication.ExecCredentialStatus, out *ExecCredentialStatus, s conversion.Scope) error {
|
||||
return autoConvert_clientauthentication_ExecCredentialStatus_To_v1beta1_ExecCredentialStatus(in, out, s)
|
||||
}
|
||||
100
pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go
Normal file
100
pkg/apis/clientauthentication/v1beta1/zz_generated.deepcopy.go
Normal file
@@ -0,0 +1,100 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExecCredential) DeepCopyInto(out *ExecCredential) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.Spec = in.Spec
|
||||
if in.Status != nil {
|
||||
in, out := &in.Status, &out.Status
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(ExecCredentialStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredential.
|
||||
func (in *ExecCredential) DeepCopy() *ExecCredential {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExecCredential)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *ExecCredential) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExecCredentialSpec) DeepCopyInto(out *ExecCredentialSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredentialSpec.
|
||||
func (in *ExecCredentialSpec) DeepCopy() *ExecCredentialSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExecCredentialSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExecCredentialStatus) DeepCopyInto(out *ExecCredentialStatus) {
|
||||
*out = *in
|
||||
if in.ExpirationTimestamp != nil {
|
||||
in, out := &in.ExpirationTimestamp, &out.ExpirationTimestamp
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExecCredentialStatus.
|
||||
func (in *ExecCredentialStatus) DeepCopy() *ExecCredentialStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExecCredentialStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
return nil
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -38,6 +39,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/pkg/apis/clientauthentication"
|
||||
"k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1"
|
||||
"k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
"k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/client-go/transport"
|
||||
"k8s.io/client-go/util/connrotation"
|
||||
@@ -51,6 +53,7 @@ var codecs = serializer.NewCodecFactory(scheme)
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
v1alpha1.AddToScheme(scheme)
|
||||
v1beta1.AddToScheme(scheme)
|
||||
clientauthentication.AddToScheme(scheme)
|
||||
}
|
||||
|
||||
@@ -61,6 +64,7 @@ var (
|
||||
// The list of API versions we accept.
|
||||
apiVersions = map[string]schema.GroupVersion{
|
||||
v1alpha1.SchemeGroupVersion.String(): v1alpha1.SchemeGroupVersion,
|
||||
v1beta1.SchemeGroupVersion.String(): v1beta1.SchemeGroupVersion,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -175,21 +179,10 @@ func (a *Authenticator) UpdateTransportConfig(c *transport.Config) error {
|
||||
return &roundTripper{a, rt}
|
||||
}
|
||||
|
||||
getCert := c.TLS.GetCert
|
||||
c.TLS.GetCert = func() (*tls.Certificate, error) {
|
||||
// If previous GetCert is present and returns a valid non-nil
|
||||
// certificate, use that. Otherwise use cert from exec plugin.
|
||||
if getCert != nil {
|
||||
cert, err := getCert()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cert != nil {
|
||||
return cert, nil
|
||||
}
|
||||
}
|
||||
return a.cert()
|
||||
if c.TLS.GetCert != nil {
|
||||
return errors.New("can't add TLS certificate callback: transport.Config.TLS.GetCert already set")
|
||||
}
|
||||
c.TLS.GetCert = a.cert
|
||||
|
||||
var dial func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
if c.Dial != nil {
|
||||
@@ -294,13 +287,18 @@ func (a *Authenticator) refreshCredsLocked(r *clientauthentication.Response) err
|
||||
},
|
||||
}
|
||||
|
||||
data, err := runtime.Encode(codecs.LegacyCodec(a.group), cred)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode ExecCredentials: %v", err)
|
||||
}
|
||||
|
||||
env := append(a.environ(), a.env...)
|
||||
env = append(env, fmt.Sprintf("%s=%s", execInfoEnv, data))
|
||||
if a.group == v1alpha1.SchemeGroupVersion {
|
||||
// Input spec disabled for beta due to lack of use. Possibly re-enable this later if
|
||||
// someone wants it back.
|
||||
//
|
||||
// See: https://github.com/kubernetes/kubernetes/issues/61796
|
||||
data, err := runtime.Encode(codecs.LegacyCodec(a.group), cred)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode ExecCredentials: %v", err)
|
||||
}
|
||||
env = append(env, fmt.Sprintf("%s=%s", execInfoEnv, data))
|
||||
}
|
||||
|
||||
stdout := &bytes.Buffer{}
|
||||
cmd := exec.Command(a.cmd, a.args...)
|
||||
|
||||
@@ -380,6 +380,72 @@ func TestRefreshCreds(t *testing.T) {
|
||||
}`, certData),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "beta-basic-request",
|
||||
config: api.ExecConfig{
|
||||
APIVersion: "client.authentication.k8s.io/v1beta1",
|
||||
},
|
||||
output: `{
|
||||
"kind": "ExecCredential",
|
||||
"apiVersion": "client.authentication.k8s.io/v1beta1",
|
||||
"status": {
|
||||
"token": "foo-bar"
|
||||
}
|
||||
}`,
|
||||
wantCreds: credentials{token: "foo-bar"},
|
||||
},
|
||||
{
|
||||
name: "beta-expiry",
|
||||
config: api.ExecConfig{
|
||||
APIVersion: "client.authentication.k8s.io/v1beta1",
|
||||
},
|
||||
output: `{
|
||||
"kind": "ExecCredential",
|
||||
"apiVersion": "client.authentication.k8s.io/v1beta1",
|
||||
"status": {
|
||||
"token": "foo-bar",
|
||||
"expirationTimestamp": "2006-01-02T15:04:05Z"
|
||||
}
|
||||
}`,
|
||||
wantExpiry: time.Date(2006, 01, 02, 15, 04, 05, 0, time.UTC),
|
||||
wantCreds: credentials{token: "foo-bar"},
|
||||
},
|
||||
{
|
||||
name: "beta-no-group-version",
|
||||
config: api.ExecConfig{
|
||||
APIVersion: "client.authentication.k8s.io/v1beta1",
|
||||
},
|
||||
output: `{
|
||||
"kind": "ExecCredential",
|
||||
"status": {
|
||||
"token": "foo-bar"
|
||||
}
|
||||
}`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "beta-no-status",
|
||||
config: api.ExecConfig{
|
||||
APIVersion: "client.authentication.k8s.io/v1beta1",
|
||||
},
|
||||
output: `{
|
||||
"kind": "ExecCredential",
|
||||
"apiVersion":"client.authentication.k8s.io/v1beta1"
|
||||
}`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "beta-no-token",
|
||||
config: api.ExecConfig{
|
||||
APIVersion: "client.authentication.k8s.io/v1beta1",
|
||||
},
|
||||
output: `{
|
||||
"kind": "ExecCredential",
|
||||
"apiVersion":"client.authentication.k8s.io/v1beta1",
|
||||
"status": {}
|
||||
}`,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -420,6 +486,13 @@ func TestRefreshCreds(t *testing.T) {
|
||||
t.Errorf("expected expiry %v got %v", test.wantExpiry, a.exp)
|
||||
}
|
||||
|
||||
if test.wantInput == "" {
|
||||
if got := strings.TrimSpace(stderr.String()); got != "" {
|
||||
t.Errorf("expected no input parameters, got %q", got)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
compJSON(t, stderr.Bytes(), []byte(test.wantInput))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ func newOpenstackAuthProvider(_ string, config map[string]string, persister rest
|
||||
var ttlDuration time.Duration
|
||||
var err error
|
||||
|
||||
glog.Warningf("WARNING: in-tree openstack auth plugin is now deprecated. please use the \"client-keystone-auth\" kubectl/client-go credential plugin instead")
|
||||
ttl, found := config["ttl"]
|
||||
if !found {
|
||||
ttlDuration = DefaultTTLDuration
|
||||
|
||||
@@ -18,6 +18,7 @@ package rest
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"k8s.io/client-go/plugin/pkg/client/auth/exec"
|
||||
@@ -83,6 +84,11 @@ func (c *Config) TransportConfig() (*transport.Config, error) {
|
||||
},
|
||||
Dial: c.Dial,
|
||||
}
|
||||
|
||||
if c.ExecProvider != nil && c.AuthProvider != nil {
|
||||
return nil, errors.New("execProvider and authProvider cannot be used in combination")
|
||||
}
|
||||
|
||||
if c.ExecProvider != nil {
|
||||
provider, err := exec.GetAuthenticator(c.ExecProvider)
|
||||
if err != nil {
|
||||
|
||||
@@ -99,18 +99,20 @@ func NewDiscoveryRESTMapper(groupResources []*APIGroupResources) meta.RESTMapper
|
||||
scope = meta.RESTScopeRoot
|
||||
}
|
||||
|
||||
// this is for legacy resources and servers which don't list singular forms. For those we must still guess.
|
||||
if len(resource.SingularName) == 0 {
|
||||
versionMapper.Add(gv.WithKind(resource.Kind), scope)
|
||||
// TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior
|
||||
versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope)
|
||||
// if we have a slash, then this is a subresource and we shouldn't create mappings for those.
|
||||
if strings.Contains(resource.Name, "/") {
|
||||
continue
|
||||
}
|
||||
|
||||
plural := gv.WithResource(resource.Name)
|
||||
singular := gv.WithResource(resource.SingularName)
|
||||
versionMapper.AddSpecific(gv.WithKind(resource.Kind), plural, singular, scope)
|
||||
// this is for legacy resources and servers which don't list singular forms. For those we must still guess.
|
||||
if len(resource.SingularName) == 0 {
|
||||
_, singular = meta.UnsafeGuessKindToResource(gv.WithKind(resource.Kind))
|
||||
}
|
||||
|
||||
versionMapper.AddSpecific(gv.WithKind(strings.ToLower(resource.Kind)), plural, singular, scope)
|
||||
versionMapper.AddSpecific(gv.WithKind(resource.Kind), plural, singular, scope)
|
||||
// TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior
|
||||
versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package api (pkg/bootstrap/token/api) contains constants and types needed for
|
||||
// Package api (k8s.io/client-go/tools/bootstrap/token/api) contains constants and types needed for
|
||||
// bootstrap tokens as maintained by the BootstrapSigner and TokenCleaner
|
||||
// controllers (in pkg/controller/bootstrap)
|
||||
// controllers (in k8s.io/kubernetes/pkg/controller/bootstrap)
|
||||
package api // import "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
|
||||
@@ -86,14 +86,26 @@ const (
|
||||
// authenticate as. The full username given is "system:bootstrap:<token-id>".
|
||||
BootstrapUserPrefix = "system:bootstrap:"
|
||||
|
||||
// BootstrapGroupPattern is the valid regex pattern that all groups
|
||||
// assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match.
|
||||
// See also ValidateBootstrapGroupName().
|
||||
BootstrapGroupPattern = "system:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]"
|
||||
|
||||
// BootstrapDefaultGroup is the default group for bootstrapping bearer
|
||||
// tokens (in addition to any groups from BootstrapTokenExtraGroupsKey).
|
||||
BootstrapDefaultGroup = "system:bootstrappers"
|
||||
|
||||
// BootstrapGroupPattern is the valid regex pattern that all groups
|
||||
// assigned to a bootstrap token by BootstrapTokenExtraGroupsKey must match.
|
||||
// See also util.ValidateBootstrapGroupName()
|
||||
BootstrapGroupPattern = `\Asystem:bootstrappers:[a-z0-9:-]{0,255}[a-z0-9]\z`
|
||||
|
||||
// BootstrapTokenPattern defines the {id}.{secret} regular expression pattern
|
||||
BootstrapTokenPattern = `\A([a-z0-9]{6})\.([a-z0-9]{16})\z`
|
||||
|
||||
// BootstrapTokenIDPattern defines token's id regular expression pattern
|
||||
BootstrapTokenIDPattern = `\A([a-z0-9]{6})\z`
|
||||
|
||||
// BootstrapTokenIDBytes defines the number of bytes used for the Bootstrap Token's ID field
|
||||
BootstrapTokenIDBytes = 6
|
||||
|
||||
// BootstrapTokenSecretBytes defines the number of bytes used the Bootstrap Token's Secret field
|
||||
BootstrapTokenSecretBytes = 16
|
||||
)
|
||||
|
||||
// KnownTokenUsages specifies the known functions a token will get.
|
||||
|
||||
@@ -17,20 +17,101 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/tools/bootstrap/token/api"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/tools/bootstrap/token/api"
|
||||
)
|
||||
|
||||
var bootstrapGroupRegexp = regexp.MustCompile(`\A` + api.BootstrapGroupPattern + `\z`)
|
||||
// validBootstrapTokenChars defines the characters a bootstrap token can consist of
|
||||
const validBootstrapTokenChars = "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
var (
|
||||
// BootstrapTokenRegexp is a compiled regular expression of TokenRegexpString
|
||||
BootstrapTokenRegexp = regexp.MustCompile(api.BootstrapTokenPattern)
|
||||
// BootstrapTokenIDRegexp is a compiled regular expression of TokenIDRegexpString
|
||||
BootstrapTokenIDRegexp = regexp.MustCompile(api.BootstrapTokenIDPattern)
|
||||
// BootstrapGroupRegexp is a compiled regular expression of BootstrapGroupPattern
|
||||
BootstrapGroupRegexp = regexp.MustCompile(api.BootstrapGroupPattern)
|
||||
)
|
||||
|
||||
// GenerateBootstrapToken generates a new, random Bootstrap Token.
|
||||
func GenerateBootstrapToken() (string, error) {
|
||||
tokenID, err := randBytes(api.BootstrapTokenIDBytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
tokenSecret, err := randBytes(api.BootstrapTokenSecretBytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return TokenFromIDAndSecret(tokenID, tokenSecret), nil
|
||||
}
|
||||
|
||||
// randBytes returns a random string consisting of the characters in
|
||||
// validBootstrapTokenChars, with the length customized by the parameter
|
||||
func randBytes(length int) (string, error) {
|
||||
// len("0123456789abcdefghijklmnopqrstuvwxyz") = 36 which doesn't evenly divide
|
||||
// the possible values of a byte: 256 mod 36 = 4. Discard any random bytes we
|
||||
// read that are >= 252 so the bytes we evenly divide the character set.
|
||||
const maxByteValue = 252
|
||||
|
||||
var (
|
||||
b byte
|
||||
err error
|
||||
token = make([]byte, length)
|
||||
)
|
||||
|
||||
reader := bufio.NewReaderSize(rand.Reader, length*2)
|
||||
for i := range token {
|
||||
for {
|
||||
if b, err = reader.ReadByte(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if b < maxByteValue {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
token[i] = validBootstrapTokenChars[int(b)%len(validBootstrapTokenChars)]
|
||||
}
|
||||
|
||||
return string(token), nil
|
||||
}
|
||||
|
||||
// TokenFromIDAndSecret returns the full token which is of the form "{id}.{secret}"
|
||||
func TokenFromIDAndSecret(id, secret string) string {
|
||||
return fmt.Sprintf("%s.%s", id, secret)
|
||||
}
|
||||
|
||||
// IsValidBootstrapToken returns whether the given string is valid as a Bootstrap Token and
|
||||
// in other words satisfies the BootstrapTokenRegexp
|
||||
func IsValidBootstrapToken(token string) bool {
|
||||
return BootstrapTokenRegexp.MatchString(token)
|
||||
}
|
||||
|
||||
// IsValidBootstrapTokenID returns whether the given string is valid as a Bootstrap Token ID and
|
||||
// in other words satisfies the BootstrapTokenIDRegexp
|
||||
func IsValidBootstrapTokenID(tokenID string) bool {
|
||||
return BootstrapTokenIDRegexp.MatchString(tokenID)
|
||||
}
|
||||
|
||||
// BootstrapTokenSecretName returns the expected name for the Secret storing the
|
||||
// Bootstrap Token in the Kubernetes API.
|
||||
func BootstrapTokenSecretName(tokenID string) string {
|
||||
return fmt.Sprintf("%s%s", api.BootstrapTokenSecretPrefix, tokenID)
|
||||
}
|
||||
|
||||
// ValidateBootstrapGroupName checks if the provided group name is a valid
|
||||
// bootstrap group name. Returns nil if valid or a validation error if invalid.
|
||||
// TODO(mattmoyer): this validation should migrate out to client-go (see https://github.com/kubernetes/client-go/issues/114)
|
||||
func ValidateBootstrapGroupName(name string) error {
|
||||
if bootstrapGroupRegexp.Match([]byte(name)) {
|
||||
if BootstrapGroupRegexp.Match([]byte(name)) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("bootstrap group %q is invalid (must match %s)", name, api.BootstrapGroupPattern)
|
||||
@@ -46,7 +127,7 @@ func ValidateUsages(usages []string) error {
|
||||
}
|
||||
}
|
||||
if len(invalidUsages) > 0 {
|
||||
return fmt.Errorf("invalide bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ","))
|
||||
return fmt.Errorf("invalid bootstrap token usage string: %s, valid usage options: %s", strings.Join(invalidUsages.List(), ","), strings.Join(api.KnownTokenUsages, ","))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,6 +21,143 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGenerateBootstrapToken(t *testing.T) {
|
||||
token, err := GenerateBootstrapToken()
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateBootstrapToken returned an unexpected error: %+v", err)
|
||||
}
|
||||
if !IsValidBootstrapToken(token) {
|
||||
t.Errorf("GenerateBootstrapToken didn't generate a valid token: %q", token)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandBytes(t *testing.T) {
|
||||
var randTest = []int{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
100,
|
||||
}
|
||||
|
||||
for _, rt := range randTest {
|
||||
actual, err := randBytes(rt)
|
||||
if err != nil {
|
||||
t.Errorf("failed randBytes: %v", err)
|
||||
}
|
||||
if len(actual) != rt {
|
||||
t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt, len(actual))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenFromIDAndSecret(t *testing.T) {
|
||||
var tests = []struct {
|
||||
id string
|
||||
secret string
|
||||
expected string
|
||||
}{
|
||||
{"foo", "bar", "foo.bar"}, // should use default
|
||||
{"abcdef", "abcdef0123456789", "abcdef.abcdef0123456789"},
|
||||
{"h", "b", "h.b"},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := TokenFromIDAndSecret(rt.id, rt.secret)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed TokenFromIDAndSecret:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidBootstrapToken(t *testing.T) {
|
||||
var tests = []struct {
|
||||
token string
|
||||
expected bool
|
||||
}{
|
||||
{token: "", expected: false},
|
||||
{token: ".", expected: false},
|
||||
{token: "1234567890123456789012", expected: false}, // invalid parcel size
|
||||
{token: "12345.1234567890123456", expected: false}, // invalid parcel size
|
||||
{token: ".1234567890123456", expected: false}, // invalid parcel size
|
||||
{token: "123456.", expected: false}, // invalid parcel size
|
||||
{token: "123456:1234567890.123456", expected: false}, // invalid separation
|
||||
{token: "abcdef:1234567890123456", expected: false}, // invalid separation
|
||||
{token: "Abcdef.1234567890123456", expected: false}, // invalid token id
|
||||
{token: "123456.AABBCCDDEEFFGGHH", expected: false}, // invalid token secret
|
||||
{token: "123456.AABBCCD-EEFFGGHH", expected: false}, // invalid character
|
||||
{token: "abc*ef.1234567890123456", expected: false}, // invalid character
|
||||
{token: "abcdef.1234567890123456", expected: true},
|
||||
{token: "123456.aabbccddeeffgghh", expected: true},
|
||||
{token: "ABCDEF.abcdef0123456789", expected: false},
|
||||
{token: "abcdef.abcdef0123456789", expected: true},
|
||||
{token: "123456.1234560123456789", expected: true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := IsValidBootstrapToken(rt.token)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed IsValidBootstrapToken for the token %q\n\texpected: %t\n\t actual: %t",
|
||||
rt.token,
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsValidBootstrapTokenID(t *testing.T) {
|
||||
var tests = []struct {
|
||||
tokenID string
|
||||
expected bool
|
||||
}{
|
||||
{tokenID: "", expected: false},
|
||||
{tokenID: "1234567890123456789012", expected: false},
|
||||
{tokenID: "12345", expected: false},
|
||||
{tokenID: "Abcdef", expected: false},
|
||||
{tokenID: "ABCDEF", expected: false},
|
||||
{tokenID: "abcdef.", expected: false},
|
||||
{tokenID: "abcdef", expected: true},
|
||||
{tokenID: "123456", expected: true},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := IsValidBootstrapTokenID(rt.tokenID)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed IsValidBootstrapTokenID for the token %q\n\texpected: %t\n\t actual: %t",
|
||||
rt.tokenID,
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapTokenSecretName(t *testing.T) {
|
||||
var tests = []struct {
|
||||
tokenID string
|
||||
expected string
|
||||
}{
|
||||
{"foo", "bootstrap-token-foo"},
|
||||
{"bar", "bootstrap-token-bar"},
|
||||
{"", "bootstrap-token-"},
|
||||
{"abcdef", "bootstrap-token-abcdef"},
|
||||
}
|
||||
for _, rt := range tests {
|
||||
actual := BootstrapTokenSecretName(rt.tokenID)
|
||||
if actual != rt.expected {
|
||||
t.Errorf(
|
||||
"failed BootstrapTokenSecretName:\n\texpected: %s\n\t actual: %s",
|
||||
rt.expected,
|
||||
actual,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateBootstrapGroupName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -129,7 +129,7 @@ func SetAuthProxyHeaders(req *http.Request, username string, groups []string, ex
|
||||
}
|
||||
for key, values := range extra {
|
||||
for _, value := range values {
|
||||
req.Header.Add("X-Remote-Extra-"+key, value)
|
||||
req.Header.Add("X-Remote-Extra-"+headerKeyEscape(key), value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,7 +246,7 @@ func (rt *impersonatingRoundTripper) RoundTrip(req *http.Request) (*http.Respons
|
||||
}
|
||||
for k, vv := range rt.impersonate.Extra {
|
||||
for _, v := range vv {
|
||||
req.Header.Add(ImpersonateUserExtraHeaderPrefix+k, v)
|
||||
req.Header.Add(ImpersonateUserExtraHeaderPrefix+headerKeyEscape(k), v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,3 +422,110 @@ func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, e
|
||||
func (rt *debuggingRoundTripper) WrappedRoundTripper() http.RoundTripper {
|
||||
return rt.delegatedRoundTripper
|
||||
}
|
||||
|
||||
func legalHeaderByte(b byte) bool {
|
||||
return int(b) < len(legalHeaderKeyBytes) && legalHeaderKeyBytes[b]
|
||||
}
|
||||
|
||||
func shouldEscape(b byte) bool {
|
||||
// url.PathUnescape() returns an error if any '%' is not followed by two
|
||||
// hexadecimal digits, so we'll intentionally encode it.
|
||||
return !legalHeaderByte(b) || b == '%'
|
||||
}
|
||||
|
||||
func headerKeyEscape(key string) string {
|
||||
buf := strings.Builder{}
|
||||
for i := 0; i < len(key); i++ {
|
||||
b := key[i]
|
||||
if shouldEscape(b) {
|
||||
// %-encode bytes that should be escaped:
|
||||
// https://tools.ietf.org/html/rfc3986#section-2.1
|
||||
fmt.Fprintf(&buf, "%%%02X", b)
|
||||
continue
|
||||
}
|
||||
buf.WriteByte(b)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// legalHeaderKeyBytes was copied from net/http/lex.go's isTokenTable.
|
||||
// See https://httpwg.github.io/specs/rfc7230.html#rule.token.separators
|
||||
var legalHeaderKeyBytes = [127]bool{
|
||||
'%': true,
|
||||
'!': true,
|
||||
'#': true,
|
||||
'$': true,
|
||||
'&': true,
|
||||
'\'': true,
|
||||
'*': true,
|
||||
'+': true,
|
||||
'-': true,
|
||||
'.': true,
|
||||
'0': true,
|
||||
'1': true,
|
||||
'2': true,
|
||||
'3': true,
|
||||
'4': true,
|
||||
'5': true,
|
||||
'6': true,
|
||||
'7': true,
|
||||
'8': true,
|
||||
'9': true,
|
||||
'A': true,
|
||||
'B': true,
|
||||
'C': true,
|
||||
'D': true,
|
||||
'E': true,
|
||||
'F': true,
|
||||
'G': true,
|
||||
'H': true,
|
||||
'I': true,
|
||||
'J': true,
|
||||
'K': true,
|
||||
'L': true,
|
||||
'M': true,
|
||||
'N': true,
|
||||
'O': true,
|
||||
'P': true,
|
||||
'Q': true,
|
||||
'R': true,
|
||||
'S': true,
|
||||
'T': true,
|
||||
'U': true,
|
||||
'W': true,
|
||||
'V': true,
|
||||
'X': true,
|
||||
'Y': true,
|
||||
'Z': true,
|
||||
'^': true,
|
||||
'_': true,
|
||||
'`': true,
|
||||
'a': true,
|
||||
'b': true,
|
||||
'c': true,
|
||||
'd': true,
|
||||
'e': true,
|
||||
'f': true,
|
||||
'g': true,
|
||||
'h': true,
|
||||
'i': true,
|
||||
'j': true,
|
||||
'k': true,
|
||||
'l': true,
|
||||
'm': true,
|
||||
'n': true,
|
||||
'o': true,
|
||||
'p': true,
|
||||
'q': true,
|
||||
'r': true,
|
||||
's': true,
|
||||
't': true,
|
||||
'u': true,
|
||||
'v': true,
|
||||
'w': true,
|
||||
'x': true,
|
||||
'y': true,
|
||||
'z': true,
|
||||
'|': true,
|
||||
'~': true,
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package transport
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -125,6 +126,32 @@ func TestImpersonationRoundTripper(t *testing.T) {
|
||||
ImpersonateUserExtraHeaderPrefix + "Second": {"B", "b"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "escape handling",
|
||||
impersonationConfig: ImpersonationConfig{
|
||||
UserName: "user",
|
||||
Extra: map[string][]string{
|
||||
"test.example.com/thing.thing": {"A", "a"},
|
||||
},
|
||||
},
|
||||
expected: map[string][]string{
|
||||
ImpersonateUserHeader: {"user"},
|
||||
ImpersonateUserExtraHeaderPrefix + `Test.example.com%2fthing.thing`: {"A", "a"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "double escape handling",
|
||||
impersonationConfig: ImpersonationConfig{
|
||||
UserName: "user",
|
||||
Extra: map[string][]string{
|
||||
"test.example.com/thing.thing%20another.thing": {"A", "a"},
|
||||
},
|
||||
},
|
||||
expected: map[string][]string{
|
||||
ImpersonateUserHeader: {"user"},
|
||||
ImpersonateUserExtraHeaderPrefix + `Test.example.com%2fthing.thing%2520another.thing`: {"A", "a"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
@@ -159,9 +186,10 @@ func TestImpersonationRoundTripper(t *testing.T) {
|
||||
|
||||
func TestAuthProxyRoundTripper(t *testing.T) {
|
||||
for n, tc := range map[string]struct {
|
||||
username string
|
||||
groups []string
|
||||
extra map[string][]string
|
||||
username string
|
||||
groups []string
|
||||
extra map[string][]string
|
||||
expectedExtra map[string][]string
|
||||
}{
|
||||
"allfields": {
|
||||
username: "user",
|
||||
@@ -170,6 +198,34 @@ func TestAuthProxyRoundTripper(t *testing.T) {
|
||||
"one": {"alpha", "bravo"},
|
||||
"two": {"charlie", "delta"},
|
||||
},
|
||||
expectedExtra: map[string][]string{
|
||||
"one": {"alpha", "bravo"},
|
||||
"two": {"charlie", "delta"},
|
||||
},
|
||||
},
|
||||
"escaped extra": {
|
||||
username: "user",
|
||||
groups: []string{"groupA", "groupB"},
|
||||
extra: map[string][]string{
|
||||
"one": {"alpha", "bravo"},
|
||||
"example.com/two": {"charlie", "delta"},
|
||||
},
|
||||
expectedExtra: map[string][]string{
|
||||
"one": {"alpha", "bravo"},
|
||||
"example.com%2ftwo": {"charlie", "delta"},
|
||||
},
|
||||
},
|
||||
"double escaped extra": {
|
||||
username: "user",
|
||||
groups: []string{"groupA", "groupB"},
|
||||
extra: map[string][]string{
|
||||
"one": {"alpha", "bravo"},
|
||||
"example.com/two%20three": {"charlie", "delta"},
|
||||
},
|
||||
expectedExtra: map[string][]string{
|
||||
"one": {"alpha", "bravo"},
|
||||
"example.com%2ftwo%2520three": {"charlie", "delta"},
|
||||
},
|
||||
},
|
||||
} {
|
||||
rt := &testRoundTripper{}
|
||||
@@ -210,9 +266,64 @@ func TestAuthProxyRoundTripper(t *testing.T) {
|
||||
actualExtra[extraKey] = append(actualExtra[key], values...)
|
||||
}
|
||||
}
|
||||
if e, a := tc.extra, actualExtra; !reflect.DeepEqual(e, a) {
|
||||
if e, a := tc.expectedExtra, actualExtra; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%s expected %v, got %v", n, e, a)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestHeaderEscapeRoundTrip tests to see if foo == url.PathUnescape(headerEscape(foo))
|
||||
// This behavior is important for client -> API server transmission of extra values.
|
||||
func TestHeaderEscapeRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := []struct {
|
||||
name string
|
||||
key string
|
||||
}{
|
||||
{
|
||||
name: "alpha",
|
||||
key: "alphabetical",
|
||||
},
|
||||
{
|
||||
name: "alphanumeric",
|
||||
key: "alph4num3r1c",
|
||||
},
|
||||
{
|
||||
name: "percent encoded",
|
||||
key: "percent%20encoded",
|
||||
},
|
||||
{
|
||||
name: "almost percent encoded",
|
||||
key: "almost%zzpercent%xxencoded",
|
||||
},
|
||||
{
|
||||
name: "illegal char & percent encoding",
|
||||
key: "example.com/percent%20encoded",
|
||||
},
|
||||
{
|
||||
name: "weird unicode stuff",
|
||||
key: "example.com/ᛒᚥᛏᛖᚥᚢとロビン",
|
||||
},
|
||||
{
|
||||
name: "header legal chars",
|
||||
key: "abc123!#$+.-_*\\^`~|'",
|
||||
},
|
||||
{
|
||||
name: "legal path, illegal header",
|
||||
key: "@=:",
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
escaped := headerKeyEscape(tc.key)
|
||||
unescaped, err := url.PathUnescape(escaped)
|
||||
if err != nil {
|
||||
t.Fatalf("url.PathUnescape(%q) returned error: %v", escaped, err)
|
||||
}
|
||||
if tc.key != unescaped {
|
||||
t.Errorf("url.PathUnescape(headerKeyEscape(%q)) returned %q, wanted %q", tc.key, unescaped, tc.key)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,8 @@ func WriteKey(keyPath string, data []byte) error {
|
||||
// can't find one, it will generate a new key and store it there.
|
||||
func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) {
|
||||
loadedData, err := ioutil.ReadFile(keyPath)
|
||||
if err == nil {
|
||||
// Call verifyKeyData to ensure the file wasn't empty/corrupt.
|
||||
if err == nil && verifyKeyData(loadedData) {
|
||||
return loadedData, false, err
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
@@ -181,3 +182,12 @@ func PublicKeysFromFile(file string) ([]interface{}, error) {
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
// verifyKeyData returns true if the provided data appears to be a valid private key.
|
||||
func verifyKeyData(data []byte) bool {
|
||||
if len(data) == 0 {
|
||||
return false
|
||||
}
|
||||
_, err := ParsePrivateKeyPEM(data)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user