Update dependencies to K8s 1.8
This commit is contained in:
parent
ba6c89672d
commit
6a59f4c9a2
1114 changed files with 160955 additions and 262845 deletions
16
vendor/k8s.io/apiserver/pkg/authentication/authenticator/BUILD
generated
vendored
16
vendor/k8s.io/apiserver/pkg/authentication/authenticator/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -10,6 +8,18 @@ load(
|
|||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["interfaces.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
|
|
|||
17
vendor/k8s.io/apiserver/pkg/authentication/serviceaccount/BUILD
generated
vendored
17
vendor/k8s.io/apiserver/pkg/authentication/serviceaccount/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -12,12 +10,23 @@ go_test(
|
|||
name = "go_default_test",
|
||||
srcs = ["util_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["util.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
|
|
|||
4
vendor/k8s.io/apiserver/pkg/authentication/serviceaccount/util.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/authentication/serviceaccount/util.go
generated
vendored
|
|
@ -59,8 +59,8 @@ func SplitUsername(username string) (string, string, error) {
|
|||
return namespace, name, nil
|
||||
}
|
||||
|
||||
// MakeGroupNames generates service account group names for the given namespace and ServiceAccount name
|
||||
func MakeGroupNames(namespace, name string) []string {
|
||||
// MakeGroupNames generates service account group names for the given namespace
|
||||
func MakeGroupNames(namespace string) []string {
|
||||
return []string{
|
||||
AllServiceAccountsGroup,
|
||||
MakeNamespaceGroupName(namespace),
|
||||
|
|
|
|||
14
vendor/k8s.io/apiserver/pkg/authentication/user/BUILD
generated
vendored
14
vendor/k8s.io/apiserver/pkg/authentication/user/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -13,5 +11,17 @@ go_library(
|
|||
"doc.go",
|
||||
"user.go",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
|
|
|||
16
vendor/k8s.io/apiserver/pkg/features/BUILD
generated
vendored
16
vendor/k8s.io/apiserver/pkg/features/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -10,6 +8,18 @@ load(
|
|||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["kube_features.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
|
|
|||
23
vendor/k8s.io/apiserver/pkg/features/kube_features.go
generated
vendored
23
vendor/k8s.io/apiserver/pkg/features/kube_features.go
generated
vendored
|
|
@ -27,15 +27,16 @@ const (
|
|||
// // alpha: v1.4
|
||||
// MyFeature() bool
|
||||
|
||||
// owner: tallclair
|
||||
// owner: @tallclair
|
||||
// alpha: v1.5
|
||||
//
|
||||
// StreamingProxyRedirects controls whether the apiserver should intercept (and follow)
|
||||
// redirects from the backend (Kubelet) for streaming requests (exec/attach/port-forward).
|
||||
StreamingProxyRedirects utilfeature.Feature = "StreamingProxyRedirects"
|
||||
|
||||
// owner: tallclair
|
||||
// owner: @tallclair
|
||||
// alpha: v1.7
|
||||
// beta: v1.8
|
||||
//
|
||||
// AdvancedAuditing enables a much more general API auditing pipeline, which includes support for
|
||||
// pluggable output backends and an audit policy specifying how different requests should be
|
||||
|
|
@ -47,6 +48,20 @@ const (
|
|||
//
|
||||
// Enables compression of REST responses (GET and LIST only)
|
||||
APIResponseCompression utilfeature.Feature = "APIResponseCompression"
|
||||
|
||||
// owner: @smarterclayton
|
||||
// alpha: v1.7
|
||||
//
|
||||
// Allow asynchronous coordination of object creation.
|
||||
// Auto-enabled by the Initializers admission plugin.
|
||||
Initializers utilfeature.Feature = "Initializers"
|
||||
|
||||
// owner: @smarterclayton
|
||||
// alpha: v1.8
|
||||
//
|
||||
// Allow API clients to retrieve resource lists in chunks rather than
|
||||
// all at once.
|
||||
APIListChunking utilfeature.Feature = "APIListChunking"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -58,6 +73,8 @@ func init() {
|
|||
// available throughout Kubernetes binaries.
|
||||
var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureSpec{
|
||||
StreamingProxyRedirects: {Default: true, PreRelease: utilfeature.Beta},
|
||||
AdvancedAuditing: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
AdvancedAuditing: {Default: true, PreRelease: utilfeature.Beta},
|
||||
APIResponseCompression: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
Initializers: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
APIListChunking: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
}
|
||||
|
|
|
|||
16
vendor/k8s.io/apiserver/pkg/server/healthz/BUILD
generated
vendored
16
vendor/k8s.io/apiserver/pkg/server/healthz/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -12,7 +10,6 @@ go_test(
|
|||
name = "go_default_test",
|
||||
srcs = ["healthz_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
|
|
@ -21,5 +18,18 @@ go_library(
|
|||
"doc.go",
|
||||
"healthz.go",
|
||||
],
|
||||
deps = ["//vendor/github.com/golang/glog:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
|
|
|||
26
vendor/k8s.io/apiserver/pkg/server/healthz/healthz.go
generated
vendored
26
vendor/k8s.io/apiserver/pkg/server/healthz/healthz.go
generated
vendored
|
|
@ -20,7 +20,10 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// HealthzChecker is a named healthz checker.
|
||||
|
|
@ -58,11 +61,18 @@ func NamedCheck(name string, check func(r *http.Request) error) HealthzChecker {
|
|||
return &healthzCheck{name, check}
|
||||
}
|
||||
|
||||
// InstallHandler registers a handler for health checking on the path "/healthz" to mux.
|
||||
// InstallHandler registers handlers for health checking on the path
|
||||
// "/healthz" to mux. *All handlers* for mux must be specified in
|
||||
// exactly one call to InstallHandler. Calling InstallHandler more
|
||||
// than once for the same mux will result in a panic.
|
||||
func InstallHandler(mux mux, checks ...HealthzChecker) {
|
||||
if len(checks) == 0 {
|
||||
glog.V(5).Info("No default health checks specified. Installing the ping handler.")
|
||||
checks = []HealthzChecker{PingHealthz}
|
||||
}
|
||||
|
||||
glog.V(5).Info("Installing healthz checkers:", strings.Join(checkerNames(checks...), ", "))
|
||||
|
||||
mux.Handle("/healthz", handleRootHealthz(checks...))
|
||||
for _, check := range checks {
|
||||
mux.Handle(fmt.Sprintf("/healthz/%v", check.Name()), adaptCheckToHandler(check.Check))
|
||||
|
|
@ -132,3 +142,17 @@ func adaptCheckToHandler(c func(r *http.Request) error) http.HandlerFunc {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
// checkerNames returns the names of the checks in the same order as passed in.
|
||||
func checkerNames(checks ...HealthzChecker) []string {
|
||||
if len(checks) > 0 {
|
||||
// accumulate the names of checks for printing them out.
|
||||
checkerNames := make([]string, 0, len(checks))
|
||||
for _, check := range checks {
|
||||
// quote the Name so we can disambiguate
|
||||
checkerNames = append(checkerNames, fmt.Sprintf("%q", check.Name()))
|
||||
}
|
||||
return checkerNames
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
50
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/BUILD
generated
vendored
Normal file
50
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"config.go",
|
||||
"plugins.go",
|
||||
"types.go",
|
||||
],
|
||||
deps = [
|
||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/identity:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["encryptionconfig_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
295
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/config.go
generated
vendored
Normal file
295
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/config.go
generated
vendored
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
Copyright 2017 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 encryptionconfig
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
yaml "github.com/ghodss/yaml"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/storage/value"
|
||||
aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
|
||||
"k8s.io/apiserver/pkg/storage/value/encrypt/envelope"
|
||||
"k8s.io/apiserver/pkg/storage/value/encrypt/identity"
|
||||
"k8s.io/apiserver/pkg/storage/value/encrypt/secretbox"
|
||||
)
|
||||
|
||||
const (
|
||||
aesCBCTransformerPrefixV1 = "k8s:enc:aescbc:v1:"
|
||||
aesGCMTransformerPrefixV1 = "k8s:enc:aesgcm:v1:"
|
||||
secretboxTransformerPrefixV1 = "k8s:enc:secretbox:v1:"
|
||||
kmsTransformerPrefixV1 = "k8s:enc:kms:v1:"
|
||||
)
|
||||
|
||||
// GetTransformerOverrides returns the transformer overrides by reading and parsing the encryption provider configuration file
|
||||
func GetTransformerOverrides(filepath string) (map[schema.GroupResource]value.Transformer, error) {
|
||||
f, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening encryption provider configuration file %q: %v", filepath, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
result, err := ParseEncryptionConfiguration(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while parsing encryption provider configuration file %q: %v", filepath, err)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ParseEncryptionConfiguration parses configuration data and returns the transformer overrides
|
||||
func ParseEncryptionConfiguration(f io.Reader) (map[schema.GroupResource]value.Transformer, error) {
|
||||
configFileContents, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read contents: %v", err)
|
||||
}
|
||||
|
||||
var config EncryptionConfig
|
||||
err = yaml.Unmarshal(configFileContents, &config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while parsing file: %v", err)
|
||||
}
|
||||
|
||||
if config.Kind == "" {
|
||||
return nil, fmt.Errorf("invalid configuration file, missing Kind")
|
||||
}
|
||||
if config.Kind != "EncryptionConfig" {
|
||||
return nil, fmt.Errorf("invalid configuration kind %q provided", config.Kind)
|
||||
}
|
||||
// TODO config.APIVersion is unchecked
|
||||
|
||||
resourceToPrefixTransformer := map[schema.GroupResource][]value.PrefixTransformer{}
|
||||
|
||||
// For each entry in the configuration
|
||||
for _, resourceConfig := range config.Resources {
|
||||
transformers, err := GetPrefixTransformers(&resourceConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// For each resource, create a list of providers to use
|
||||
for _, resource := range resourceConfig.Resources {
|
||||
gr := schema.ParseGroupResource(resource)
|
||||
resourceToPrefixTransformer[gr] = append(
|
||||
resourceToPrefixTransformer[gr], transformers...)
|
||||
}
|
||||
}
|
||||
|
||||
result := map[schema.GroupResource]value.Transformer{}
|
||||
for gr, transList := range resourceToPrefixTransformer {
|
||||
result[gr] = value.NewMutableTransformer(value.NewPrefixTransformers(fmt.Errorf("no matching prefix found"), transList...))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetPrefixTransformers constructs and returns the appropriate prefix transformers for the passed resource using its configuration
|
||||
func GetPrefixTransformers(config *ResourceConfig) ([]value.PrefixTransformer, error) {
|
||||
var result []value.PrefixTransformer
|
||||
for _, provider := range config.Providers {
|
||||
found := false
|
||||
|
||||
var transformer value.PrefixTransformer
|
||||
var err error
|
||||
|
||||
if provider.AESGCM != nil {
|
||||
transformer, err = GetAESPrefixTransformer(provider.AESGCM, aestransformer.NewGCMTransformer, aesGCMTransformerPrefixV1)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
found = true
|
||||
}
|
||||
|
||||
if provider.AESCBC != nil {
|
||||
if found == true {
|
||||
return result, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
|
||||
}
|
||||
transformer, err = GetAESPrefixTransformer(provider.AESCBC, aestransformer.NewCBCTransformer, aesCBCTransformerPrefixV1)
|
||||
found = true
|
||||
}
|
||||
|
||||
if provider.Secretbox != nil {
|
||||
if found == true {
|
||||
return result, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
|
||||
}
|
||||
transformer, err = GetSecretboxPrefixTransformer(provider.Secretbox)
|
||||
found = true
|
||||
}
|
||||
|
||||
if provider.Identity != nil {
|
||||
if found == true {
|
||||
return result, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
|
||||
}
|
||||
transformer = value.PrefixTransformer{
|
||||
Transformer: identity.NewEncryptCheckTransformer(),
|
||||
Prefix: []byte{},
|
||||
}
|
||||
found = true
|
||||
}
|
||||
|
||||
if provider.KMS != nil {
|
||||
if found == true {
|
||||
return nil, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
|
||||
}
|
||||
f, err := os.Open(provider.KMS.ConfigFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening KMS provider configuration file %q: %v", provider.KMS.ConfigFile, err)
|
||||
}
|
||||
defer f.Close()
|
||||
envelopeService, pluginFound, err := KMSPluginRegistry.getPlugin(provider.KMS.Name, f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not configure KMS plugin %q, %v", provider.KMS.Name, err)
|
||||
}
|
||||
if pluginFound == false {
|
||||
return nil, fmt.Errorf("KMS plugin %q not found", provider.KMS.Name)
|
||||
}
|
||||
transformer, err = getEnvelopePrefixTransformer(provider.KMS, envelopeService, kmsTransformerPrefixV1)
|
||||
found = true
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
result = append(result, transformer)
|
||||
|
||||
if found == false {
|
||||
return result, fmt.Errorf("invalid provider configuration: at least one provider must be specified")
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// BlockTransformerFunc takes an AES cipher block and returns a value transformer.
|
||||
type BlockTransformerFunc func(cipher.Block) value.Transformer
|
||||
|
||||
// GetAESPrefixTransformer returns a prefix transformer from the provided configuration.
|
||||
// Returns an AES transformer based on the provided prefix and block transformer.
|
||||
func GetAESPrefixTransformer(config *AESConfig, fn BlockTransformerFunc, prefix string) (value.PrefixTransformer, error) {
|
||||
var result value.PrefixTransformer
|
||||
|
||||
if len(config.Keys) == 0 {
|
||||
return result, fmt.Errorf("aes provider has no valid keys")
|
||||
}
|
||||
for _, key := range config.Keys {
|
||||
if key.Name == "" {
|
||||
return result, fmt.Errorf("key with invalid name provided")
|
||||
}
|
||||
if key.Secret == "" {
|
||||
return result, fmt.Errorf("key %v has no provided secret", key.Name)
|
||||
}
|
||||
}
|
||||
|
||||
keyTransformers := []value.PrefixTransformer{}
|
||||
|
||||
for _, keyData := range config.Keys {
|
||||
key, err := base64.StdEncoding.DecodeString(keyData.Secret)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("could not obtain secret for named key %s: %s", keyData.Name, err)
|
||||
}
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("error while creating cipher for named key %s: %s", keyData.Name, err)
|
||||
}
|
||||
|
||||
// Create a new PrefixTransformer for this key
|
||||
keyTransformers = append(keyTransformers,
|
||||
value.PrefixTransformer{
|
||||
Transformer: fn(block),
|
||||
Prefix: []byte(keyData.Name + ":"),
|
||||
})
|
||||
}
|
||||
|
||||
// Create a prefixTransformer which can choose between these keys
|
||||
keyTransformer := value.NewPrefixTransformers(
|
||||
fmt.Errorf("no matching key was found for the provided AES transformer"), keyTransformers...)
|
||||
|
||||
// Create a PrefixTransformer which shall later be put in a list with other providers
|
||||
result = value.PrefixTransformer{
|
||||
Transformer: keyTransformer,
|
||||
Prefix: []byte(prefix),
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetSecretboxPrefixTransformer returns a prefix transformer from the provided configuration
|
||||
func GetSecretboxPrefixTransformer(config *SecretboxConfig) (value.PrefixTransformer, error) {
|
||||
var result value.PrefixTransformer
|
||||
|
||||
if len(config.Keys) == 0 {
|
||||
return result, fmt.Errorf("secretbox provider has no valid keys")
|
||||
}
|
||||
for _, key := range config.Keys {
|
||||
if key.Name == "" {
|
||||
return result, fmt.Errorf("key with invalid name provided")
|
||||
}
|
||||
if key.Secret == "" {
|
||||
return result, fmt.Errorf("key %v has no provided secret", key.Name)
|
||||
}
|
||||
}
|
||||
|
||||
keyTransformers := []value.PrefixTransformer{}
|
||||
|
||||
for _, keyData := range config.Keys {
|
||||
key, err := base64.StdEncoding.DecodeString(keyData.Secret)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("could not obtain secret for named key %s: %s", keyData.Name, err)
|
||||
}
|
||||
|
||||
if len(key) != 32 {
|
||||
return result, fmt.Errorf("expected key size 32 for secretbox provider, got %v", len(key))
|
||||
}
|
||||
|
||||
keyArray := [32]byte{}
|
||||
copy(keyArray[:], key)
|
||||
|
||||
// Create a new PrefixTransformer for this key
|
||||
keyTransformers = append(keyTransformers,
|
||||
value.PrefixTransformer{
|
||||
Transformer: secretbox.NewSecretboxTransformer(keyArray),
|
||||
Prefix: []byte(keyData.Name + ":"),
|
||||
})
|
||||
}
|
||||
|
||||
// Create a prefixTransformer which can choose between these keys
|
||||
keyTransformer := value.NewPrefixTransformers(
|
||||
fmt.Errorf("no matching key was found for the provided Secretbox transformer"), keyTransformers...)
|
||||
|
||||
// Create a PrefixTransformer which shall later be put in a list with other providers
|
||||
result = value.PrefixTransformer{
|
||||
Transformer: keyTransformer,
|
||||
Prefix: []byte(secretboxTransformerPrefixV1),
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// getEnvelopePrefixTransformer returns a prefix transformer from the provided config.
|
||||
// envelopeService is used as the root of trust.
|
||||
func getEnvelopePrefixTransformer(config *KMSConfig, envelopeService envelope.Service, prefix string) (value.PrefixTransformer, error) {
|
||||
envelopeTransformer, err := envelope.NewEnvelopeTransformer(envelopeService, config.CacheSize, aestransformer.NewCBCTransformer)
|
||||
if err != nil {
|
||||
return value.PrefixTransformer{}, err
|
||||
}
|
||||
return value.PrefixTransformer{
|
||||
Transformer: envelopeTransformer,
|
||||
Prefix: []byte(prefix + config.Name + ":"),
|
||||
}, nil
|
||||
}
|
||||
118
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/plugins.go
generated
vendored
Normal file
118
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/plugins.go
generated
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
Copyright 2017 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 encryptionconfig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apiserver/pkg/storage/value/encrypt/envelope"
|
||||
)
|
||||
|
||||
// Factory is a function that returns an envelope Service for encryption providers.
|
||||
// The config parameter provides an io.Reader handler to the factory in
|
||||
// order to load specific configurations. If no configuration is provided
|
||||
// the parameter is nil.
|
||||
type Factory func(config io.Reader) (envelope.Service, error)
|
||||
|
||||
// KMSPlugins contains all registered KMS options.
|
||||
type KMSPlugins struct {
|
||||
lock sync.RWMutex
|
||||
registry map[string]Factory
|
||||
}
|
||||
|
||||
var (
|
||||
// PluginEnabledFn checks whether a plugin is enabled. By default, if you ask about it, it's enabled.
|
||||
PluginEnabledFn = func(name string, config io.Reader) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// KMSPluginRegistry contains the registered KMS plugins which can be used for configuring
|
||||
// encryption providers.
|
||||
KMSPluginRegistry = KMSPlugins{}
|
||||
)
|
||||
|
||||
// PluginEnabledFunc is a function type that can provide an external check on whether an admission plugin may be enabled
|
||||
type PluginEnabledFunc func(name string, config io.Reader) bool
|
||||
|
||||
// Register registers a plugin Factory by name. This
|
||||
// is expected to happen during app startup. It does not allow
|
||||
// registering a plugin by the same name twice.
|
||||
func (ps *KMSPlugins) Register(name string, plugin Factory) {
|
||||
ps.lock.Lock()
|
||||
defer ps.lock.Unlock()
|
||||
_, found := ps.registry[name]
|
||||
if ps.registry == nil {
|
||||
ps.registry = map[string]Factory{}
|
||||
}
|
||||
if found {
|
||||
glog.Fatalf("KMS plugin %q was registered twice", name)
|
||||
} else {
|
||||
ps.registry[name] = plugin
|
||||
glog.V(1).Infof("Registered KMS plugin %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
// getPlugin creates an instance of the named plugin. It returns `false` if the
|
||||
// the name is not known. The error is returned only when the named provider was
|
||||
// known but failed to initialize. The config parameter specifies the io.Reader
|
||||
// handler of the configuration file for the cloud provider, or nil for no configuration.
|
||||
func (ps *KMSPlugins) getPlugin(name string, config io.Reader) (envelope.Service, bool, error) {
|
||||
f, found := ps.fetchPluginFromRegistry(name)
|
||||
if !found {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
config1, config2, err := splitStream(config)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
if !PluginEnabledFn(name, config1) {
|
||||
return nil, true, nil
|
||||
}
|
||||
|
||||
ret, err := f(config2)
|
||||
return ret, true, err
|
||||
}
|
||||
|
||||
// fetchPluginFromRegistry tries to get a registered plugin with the requested name.
|
||||
func (ps *KMSPlugins) fetchPluginFromRegistry(name string) (Factory, bool) {
|
||||
ps.lock.RLock()
|
||||
defer ps.lock.RUnlock()
|
||||
// Map lookup defaults to single value context
|
||||
f, found := ps.registry[name]
|
||||
return f, found
|
||||
}
|
||||
|
||||
// splitStream reads the stream bytes and constructs two copies of it.
|
||||
func splitStream(config io.Reader) (io.Reader, io.Reader, error) {
|
||||
if config == nil || reflect.ValueOf(config).IsNil() {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
configBytes, err := ioutil.ReadAll(config)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return bytes.NewBuffer(configBytes), bytes.NewBuffer(configBytes), nil
|
||||
}
|
||||
86
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/types.go
generated
vendored
Normal file
86
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
Copyright 2017 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 encryptionconfig
|
||||
|
||||
// EncryptionConfig stores the complete configuration for encryption providers.
|
||||
type EncryptionConfig struct {
|
||||
// kind is the type of configuration file.
|
||||
Kind string `json:"kind"`
|
||||
// apiVersion is the API version this file has to be parsed as.
|
||||
APIVersion string `json:"apiVersion"`
|
||||
// resources is a list containing resources, and their corresponding encryption providers.
|
||||
Resources []ResourceConfig `json:"resources"`
|
||||
}
|
||||
|
||||
// ResourceConfig stores per resource configuration.
|
||||
type ResourceConfig struct {
|
||||
// resources is a list of kubernetes resources which have to be encrypted.
|
||||
Resources []string `json:"resources"`
|
||||
// providers is a list of transformers to be used for reading and writing the resources to disk.
|
||||
// eg: aesgcm, aescbc, secretbox, identity.
|
||||
Providers []ProviderConfig `json:"providers"`
|
||||
}
|
||||
|
||||
// ProviderConfig stores the provided configuration for an encryption provider.
|
||||
type ProviderConfig struct {
|
||||
// aesgcm is the configuration for the AES-GCM transformer.
|
||||
AESGCM *AESConfig `json:"aesgcm,omitempty"`
|
||||
// aescbc is the configuration for the AES-CBC transformer.
|
||||
AESCBC *AESConfig `json:"aescbc,omitempty"`
|
||||
// secretbox is the configuration for the Secretbox based transformer.
|
||||
Secretbox *SecretboxConfig `json:"secretbox,omitempty"`
|
||||
// identity is the (empty) configuration for the identity transformer.
|
||||
Identity *IdentityConfig `json:"identity,omitempty"`
|
||||
// kms contains the name, cache size and path to configuration file for a KMS based envelope transformer.
|
||||
KMS *KMSConfig `json:"kms,omitempty"`
|
||||
}
|
||||
|
||||
// AESConfig contains the API configuration for an AES transformer.
|
||||
type AESConfig struct {
|
||||
// keys is a list of keys to be used for creating the AES transformer.
|
||||
// Each key has to be 32 bytes long for AES-CBC and 16, 24 or 32 bytes for AES-GCM.
|
||||
Keys []Key `json:"keys"`
|
||||
}
|
||||
|
||||
// SecretboxConfig contains the API configuration for an Secretbox transformer.
|
||||
type SecretboxConfig struct {
|
||||
// keys is a list of keys to be used for creating the Secretbox transformer.
|
||||
// Each key has to be 32 bytes long.
|
||||
Keys []Key `json:"keys"`
|
||||
}
|
||||
|
||||
// Key contains name and secret of the provided key for a transformer.
|
||||
type Key struct {
|
||||
// name is the name of the key to be used while storing data to disk.
|
||||
Name string `json:"name"`
|
||||
// secret is the actual key, encoded in base64.
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
// IdentityConfig is an empty struct to allow identity transformer in provider configuration.
|
||||
type IdentityConfig struct{}
|
||||
|
||||
// KMSConfig contains the name, cache size and path to configuration file for a KMS based envelope transformer.
|
||||
type KMSConfig struct {
|
||||
// name is the name of the KMS plugin to be used.
|
||||
Name string `json:"name"`
|
||||
// cacheSize is the maximum number of secrets which are cached in memory. The default value is 1000.
|
||||
// +optional
|
||||
CacheSize int `json:"cachesize,omitempty"`
|
||||
// configfile is the path to the configuration file for the named KMS provider.
|
||||
ConfigFile string `json:"configfile"`
|
||||
}
|
||||
37
vendor/k8s.io/apiserver/pkg/storage/value/BUILD
generated
vendored
Normal file
37
vendor/k8s.io/apiserver/pkg/storage/value/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["transformer_test.go"],
|
||||
library = ":go_default_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["transformer.go"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes:all-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope:all-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/identity:all-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
33
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes/BUILD
generated
vendored
Normal file
33
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["aes_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["aes.go"],
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
152
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes.go
generated
vendored
Normal file
152
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes.go
generated
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
Copyright 2017 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 aes transforms values for storage at rest using AES-GCM.
|
||||
package aes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"k8s.io/apiserver/pkg/storage/value"
|
||||
)
|
||||
|
||||
// gcm implements AEAD encryption of the provided values given a cipher.Block algorithm.
|
||||
// The authenticated data provided as part of the value.Context method must match when the same
|
||||
// value is set to and loaded from storage. In order to ensure that values cannot be copied by
|
||||
// an attacker from a location under their control, use characteristics of the storage location
|
||||
// (such as the etcd key) as part of the authenticated data.
|
||||
//
|
||||
// Because this mode requires a generated IV and IV reuse is a known weakness of AES-GCM, keys
|
||||
// must be rotated before a birthday attack becomes feasible. NIST SP 800-38D
|
||||
// (http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf) recommends using the same
|
||||
// key with random 96-bit nonces (the default nonce length) no more than 2^32 times, and
|
||||
// therefore transformers using this implementation *must* ensure they allow for frequent key
|
||||
// rotation. Future work should include investigation of AES-GCM-SIV as an alternative to
|
||||
// random nonces.
|
||||
type gcm struct {
|
||||
block cipher.Block
|
||||
}
|
||||
|
||||
// NewGCMTransformer takes the given block cipher and performs encryption and decryption on the given
|
||||
// data.
|
||||
func NewGCMTransformer(block cipher.Block) value.Transformer {
|
||||
return &gcm{block: block}
|
||||
}
|
||||
|
||||
func (t *gcm) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||
aead, err := cipher.NewGCM(t.block)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
nonceSize := aead.NonceSize()
|
||||
if len(data) < nonceSize {
|
||||
return nil, false, fmt.Errorf("the stored data was shorter than the required size")
|
||||
}
|
||||
result, err := aead.Open(nil, data[:nonceSize], data[nonceSize:], context.AuthenticatedData())
|
||||
return result, false, err
|
||||
}
|
||||
|
||||
func (t *gcm) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||
aead, err := cipher.NewGCM(t.block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nonceSize := aead.NonceSize()
|
||||
result := make([]byte, nonceSize+aead.Overhead()+len(data))
|
||||
n, err := rand.Read(result[:nonceSize])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n != nonceSize {
|
||||
return nil, fmt.Errorf("unable to read sufficient random bytes")
|
||||
}
|
||||
cipherText := aead.Seal(result[nonceSize:nonceSize], result[:nonceSize], data, context.AuthenticatedData())
|
||||
return result[:nonceSize+len(cipherText)], nil
|
||||
}
|
||||
|
||||
// cbc implements encryption at rest of the provided values given a cipher.Block algorithm.
|
||||
type cbc struct {
|
||||
block cipher.Block
|
||||
}
|
||||
|
||||
// NewCBCTransformer takes the given block cipher and performs encryption and decryption on the given
|
||||
// data.
|
||||
func NewCBCTransformer(block cipher.Block) value.Transformer {
|
||||
return &cbc{block: block}
|
||||
}
|
||||
|
||||
var (
|
||||
errInvalidBlockSize = fmt.Errorf("the stored data is not a multiple of the block size")
|
||||
errInvalidPKCS7Data = errors.New("invalid PKCS7 data (empty or not padded)")
|
||||
errInvalidPKCS7Padding = errors.New("invalid padding on input")
|
||||
)
|
||||
|
||||
func (t *cbc) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||
blockSize := aes.BlockSize
|
||||
if len(data) < blockSize {
|
||||
return nil, false, fmt.Errorf("the stored data was shorter than the required size")
|
||||
}
|
||||
iv := data[:blockSize]
|
||||
data = data[blockSize:]
|
||||
|
||||
if len(data)%blockSize != 0 {
|
||||
return nil, false, errInvalidBlockSize
|
||||
}
|
||||
|
||||
result := make([]byte, len(data))
|
||||
copy(result, data)
|
||||
mode := cipher.NewCBCDecrypter(t.block, iv)
|
||||
mode.CryptBlocks(result, result)
|
||||
|
||||
// remove and verify PKCS#7 padding for CBC
|
||||
c := result[len(result)-1]
|
||||
paddingSize := int(c)
|
||||
size := len(result) - paddingSize
|
||||
if paddingSize == 0 || paddingSize > len(result) {
|
||||
return nil, false, errInvalidPKCS7Data
|
||||
}
|
||||
for i := 0; i < paddingSize; i++ {
|
||||
if result[size+i] != c {
|
||||
return nil, false, errInvalidPKCS7Padding
|
||||
}
|
||||
}
|
||||
|
||||
return result[:size], false, nil
|
||||
}
|
||||
|
||||
func (t *cbc) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||
blockSize := aes.BlockSize
|
||||
paddingSize := blockSize - (len(data) % blockSize)
|
||||
result := make([]byte, blockSize+len(data)+paddingSize)
|
||||
iv := result[:blockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
return nil, fmt.Errorf("unable to read sufficient random bytes")
|
||||
}
|
||||
copy(result[blockSize:], data)
|
||||
|
||||
// add PKCS#7 padding for CBC
|
||||
copy(result[blockSize+len(data):], bytes.Repeat([]byte{byte(paddingSize)}, paddingSize))
|
||||
|
||||
mode := cipher.NewCBCEncrypter(t.block, iv)
|
||||
mode.CryptBlocks(result[blockSize:], result[blockSize:])
|
||||
return result, nil
|
||||
}
|
||||
39
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD
generated
vendored
Normal file
39
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["envelope.go"],
|
||||
deps = [
|
||||
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["envelope_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
162
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go
generated
vendored
Normal file
162
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go
generated
vendored
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
Copyright 2017 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 envelope transforms values for storage at rest using a Envelope provider
|
||||
package envelope
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apiserver/pkg/storage/value"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// defaultCacheSize is the number of decrypted DEKs which would be cached by the transformer.
|
||||
const defaultCacheSize = 1000
|
||||
|
||||
// Service allows encrypting and decrypting data using an external Key Management Service.
|
||||
type Service interface {
|
||||
// Decrypt a given data string to obtain the original byte data.
|
||||
Decrypt(data string) ([]byte, error)
|
||||
// Encrypt bytes to a string ciphertext.
|
||||
Encrypt(data []byte) (string, error)
|
||||
}
|
||||
|
||||
type envelopeTransformer struct {
|
||||
envelopeService Service
|
||||
|
||||
// transformers is a thread-safe LRU cache which caches decrypted DEKs indexed by their encrypted form.
|
||||
transformers *lru.Cache
|
||||
|
||||
// cacheSize is the maximum number of DEKs that are cached.
|
||||
cacheSize int
|
||||
|
||||
// baseTransformerFunc creates a new transformer for encrypting the data with the DEK.
|
||||
baseTransformerFunc func(cipher.Block) value.Transformer
|
||||
}
|
||||
|
||||
// NewEnvelopeTransformer returns a transformer which implements a KEK-DEK based envelope encryption scheme.
|
||||
// It uses envelopeService to encrypt and decrypt DEKs. Respective DEKs (in encrypted form) are prepended to
|
||||
// the data items they encrypt. A cache (of size cacheSize) is maintained to store the most recently
|
||||
// used decrypted DEKs in memory.
|
||||
func NewEnvelopeTransformer(envelopeService Service, cacheSize int, baseTransformerFunc func(cipher.Block) value.Transformer) (value.Transformer, error) {
|
||||
if cacheSize == 0 {
|
||||
cacheSize = defaultCacheSize
|
||||
}
|
||||
cache, err := lru.New(cacheSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &envelopeTransformer{
|
||||
envelopeService: envelopeService,
|
||||
transformers: cache,
|
||||
cacheSize: cacheSize,
|
||||
baseTransformerFunc: baseTransformerFunc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TransformFromStorage decrypts data encrypted by this transformer using envelope encryption.
|
||||
func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||
// Read the 16 bit length-of-DEK encoded at the start of the encrypted DEK. 16 bits can
|
||||
// represent a maximum key length of 65536 bytes. We are using a 256 bit key, whose
|
||||
// length cannot fit in 8 bits (1 byte). Thus, we use 16 bits (2 bytes) to store the length.
|
||||
keyLen := int(binary.BigEndian.Uint16(data[:2]))
|
||||
if keyLen+2 > len(data) {
|
||||
return nil, false, fmt.Errorf("invalid data encountered by genvelope transformer, length longer than available bytes: %q", data)
|
||||
}
|
||||
encKey := string(data[2 : keyLen+2])
|
||||
encData := data[2+keyLen:]
|
||||
|
||||
var transformer value.Transformer
|
||||
// Look up the decrypted DEK from cache or Envelope.
|
||||
_transformer, found := t.transformers.Get(encKey)
|
||||
if found {
|
||||
transformer = _transformer.(value.Transformer)
|
||||
} else {
|
||||
key, err := t.envelopeService.Decrypt(encKey)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("error while decrypting key: %q", err)
|
||||
}
|
||||
transformer, err = t.addTransformer(encKey, key)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
return transformer.TransformFromStorage(encData, context)
|
||||
}
|
||||
|
||||
// TransformToStorage encrypts data to be written to disk using envelope encryption.
|
||||
func (t *envelopeTransformer) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||
newKey, err := generateKey(32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encKey, err := t.envelopeService.Encrypt(newKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transformer, err := t.addTransformer(encKey, newKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Append the length of the encrypted DEK as the first 2 bytes.
|
||||
encKeyLen := make([]byte, 2)
|
||||
encKeyBytes := []byte(encKey)
|
||||
binary.BigEndian.PutUint16(encKeyLen, uint16(len(encKeyBytes)))
|
||||
|
||||
prefix := append(encKeyLen, encKeyBytes...)
|
||||
|
||||
prefixedData := make([]byte, len(prefix), len(data)+len(prefix))
|
||||
copy(prefixedData, prefix)
|
||||
result, err := transformer.TransformToStorage(data, context)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prefixedData = append(prefixedData, result...)
|
||||
return prefixedData, nil
|
||||
}
|
||||
|
||||
var _ value.Transformer = &envelopeTransformer{}
|
||||
|
||||
// addTransformer inserts a new transformer to the Envelope cache of DEKs for future reads.
|
||||
func (t *envelopeTransformer) addTransformer(encKey string, key []byte) (value.Transformer, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
transformer := t.baseTransformerFunc(block)
|
||||
t.transformers.Add(encKey, transformer)
|
||||
return transformer, nil
|
||||
}
|
||||
|
||||
// generateKey generates a random key using system randomness.
|
||||
func generateKey(length int) ([]byte, error) {
|
||||
key := make([]byte, length)
|
||||
_, err := rand.Read(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return key, nil
|
||||
}
|
||||
25
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/identity/BUILD
generated
vendored
Normal file
25
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/identity/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["identity.go"],
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
50
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/identity/identity.go
generated
vendored
Normal file
50
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/identity/identity.go
generated
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright 2017 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 identity
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apiserver/pkg/storage/value"
|
||||
)
|
||||
|
||||
// identityTransformer performs no transformation on provided data, but validates
|
||||
// that the data is not encrypted data during TransformFromStorage
|
||||
type identityTransformer struct{}
|
||||
|
||||
// NewEncryptCheckTransformer returns an identityTransformer which returns an error
|
||||
// on attempts to read encrypted data
|
||||
func NewEncryptCheckTransformer() value.Transformer {
|
||||
return identityTransformer{}
|
||||
}
|
||||
|
||||
// TransformFromStorage returns the input bytes if the data is not encrypted
|
||||
func (identityTransformer) TransformFromStorage(b []byte, context value.Context) ([]byte, bool, error) {
|
||||
// identityTransformer has to return an error if the data is encoded using another transformer.
|
||||
// JSON data starts with '{'. Protobuf data has a prefix 'k8s[\x00-\xFF]'.
|
||||
// Prefix 'k8s:enc:' is reserved for encrypted data on disk.
|
||||
if bytes.HasPrefix(b, []byte("k8s:enc:")) {
|
||||
return []byte{}, false, fmt.Errorf("identity transformer tried to read encrypted data")
|
||||
}
|
||||
return b, false, nil
|
||||
}
|
||||
|
||||
// TransformToStorage implements the Transformer interface for identityTransformer
|
||||
func (identityTransformer) TransformToStorage(b []byte, context value.Context) ([]byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
36
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/BUILD
generated
vendored
Normal file
36
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/BUILD
generated
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["secretbox_test.go"],
|
||||
library = ":go_default_library",
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["secretbox.go"],
|
||||
deps = [
|
||||
"//vendor/golang.org/x/crypto/nacl/secretbox:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
69
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox.go
generated
vendored
Normal file
69
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox.go
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright 2017 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 secretbox transforms values for storage at rest using XSalsa20 and Poly1305.
|
||||
package secretbox
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
|
||||
"k8s.io/apiserver/pkg/storage/value"
|
||||
)
|
||||
|
||||
// secretbox implements at rest encryption of the provided values given a 32 byte secret key.
|
||||
// Uses a standard 24 byte nonce (placed at the the beginning of the cipher text) generated
|
||||
// from crypto/rand. Does not perform authentication of the data at rest.
|
||||
type secretboxTransformer struct {
|
||||
key [32]byte
|
||||
}
|
||||
|
||||
const nonceSize = 24
|
||||
|
||||
// NewSecretboxTransformer takes the given key and performs encryption and decryption on the given
|
||||
// data.
|
||||
func NewSecretboxTransformer(key [32]byte) value.Transformer {
|
||||
return &secretboxTransformer{key: key}
|
||||
}
|
||||
|
||||
func (t *secretboxTransformer) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||
if len(data) < (secretbox.Overhead + nonceSize) {
|
||||
return nil, false, fmt.Errorf("the stored data was shorter than the required size")
|
||||
}
|
||||
var nonce [nonceSize]byte
|
||||
copy(nonce[:], data[:nonceSize])
|
||||
data = data[nonceSize:]
|
||||
out := make([]byte, 0, len(data)-secretbox.Overhead)
|
||||
result, ok := secretbox.Open(out, data, &nonce, &t.key)
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("output array was not large enough for encryption")
|
||||
}
|
||||
return result, false, nil
|
||||
}
|
||||
|
||||
func (t *secretboxTransformer) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||
var nonce [nonceSize]byte
|
||||
n, err := rand.Read(nonce[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n != nonceSize {
|
||||
return nil, fmt.Errorf("unable to read sufficient random bytes")
|
||||
}
|
||||
return secretbox.Seal(nonce[:], data, &nonce, &t.key), nil
|
||||
}
|
||||
153
vendor/k8s.io/apiserver/pkg/storage/value/transformer.go
generated
vendored
Normal file
153
vendor/k8s.io/apiserver/pkg/storage/value/transformer.go
generated
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
Copyright 2017 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 value contains methods for assisting with transformation of values in storage.
|
||||
package value
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Context is additional information that a storage transformation may need to verify the data at rest.
|
||||
type Context interface {
|
||||
// AuthenticatedData should return an array of bytes that describes the current value. If the value changes,
|
||||
// the transformer may report the value as unreadable or tampered. This may be nil if no such description exists
|
||||
// or is needed. For additional verification, set this to data that strongly identifies the value, such as
|
||||
// the key and creation version of the stored data.
|
||||
AuthenticatedData() []byte
|
||||
}
|
||||
|
||||
// Transformer allows a value to be transformed before being read from or written to the underlying store. The methods
|
||||
// must be able to undo the transformation caused by the other.
|
||||
type Transformer interface {
|
||||
// TransformFromStorage may transform the provided data from its underlying storage representation or return an error.
|
||||
// Stale is true if the object on disk is stale and a write to etcd should be issued, even if the contents of the object
|
||||
// have not changed.
|
||||
TransformFromStorage(data []byte, context Context) (out []byte, stale bool, err error)
|
||||
// TransformToStorage may transform the provided data into the appropriate form in storage or return an error.
|
||||
TransformToStorage(data []byte, context Context) (out []byte, err error)
|
||||
}
|
||||
|
||||
type identityTransformer struct{}
|
||||
|
||||
// IdentityTransformer performs no transformation of the provided data.
|
||||
var IdentityTransformer Transformer = identityTransformer{}
|
||||
|
||||
func (identityTransformer) TransformFromStorage(b []byte, ctx Context) ([]byte, bool, error) {
|
||||
return b, false, nil
|
||||
}
|
||||
func (identityTransformer) TransformToStorage(b []byte, ctx Context) ([]byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// DefaultContext is a simple implementation of Context for a slice of bytes.
|
||||
type DefaultContext []byte
|
||||
|
||||
// AuthenticatedData returns itself.
|
||||
func (c DefaultContext) AuthenticatedData() []byte { return []byte(c) }
|
||||
|
||||
// MutableTransformer allows a transformer to be changed safely at runtime.
|
||||
type MutableTransformer struct {
|
||||
lock sync.RWMutex
|
||||
transformer Transformer
|
||||
}
|
||||
|
||||
// NewMutableTransformer creates a transformer that can be updated at any time by calling Set()
|
||||
func NewMutableTransformer(transformer Transformer) *MutableTransformer {
|
||||
return &MutableTransformer{transformer: transformer}
|
||||
}
|
||||
|
||||
// Set updates the nested transformer.
|
||||
func (t *MutableTransformer) Set(transformer Transformer) {
|
||||
t.lock.Lock()
|
||||
t.transformer = transformer
|
||||
t.lock.Unlock()
|
||||
}
|
||||
|
||||
func (t *MutableTransformer) TransformFromStorage(data []byte, context Context) (out []byte, stale bool, err error) {
|
||||
t.lock.RLock()
|
||||
transformer := t.transformer
|
||||
t.lock.RUnlock()
|
||||
return transformer.TransformFromStorage(data, context)
|
||||
}
|
||||
func (t *MutableTransformer) TransformToStorage(data []byte, context Context) (out []byte, err error) {
|
||||
t.lock.RLock()
|
||||
transformer := t.transformer
|
||||
t.lock.RUnlock()
|
||||
return transformer.TransformToStorage(data, context)
|
||||
}
|
||||
|
||||
// PrefixTransformer holds a transformer interface and the prefix that the transformation is located under.
|
||||
type PrefixTransformer struct {
|
||||
Prefix []byte
|
||||
Transformer Transformer
|
||||
}
|
||||
|
||||
type prefixTransformers struct {
|
||||
transformers []PrefixTransformer
|
||||
err error
|
||||
}
|
||||
|
||||
var _ Transformer = &prefixTransformers{}
|
||||
|
||||
// NewPrefixTransformers supports the Transformer interface by checking the incoming data against the provided
|
||||
// prefixes in order. The first matching prefix will be used to transform the value (the prefix is stripped
|
||||
// before the Transformer interface is invoked). The first provided transformer will be used when writing to
|
||||
// the store.
|
||||
func NewPrefixTransformers(err error, transformers ...PrefixTransformer) Transformer {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("the provided value does not match any of the supported transformers")
|
||||
}
|
||||
return &prefixTransformers{
|
||||
transformers: transformers,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// TransformFromStorage finds the first transformer with a prefix matching the provided data and returns
|
||||
// the result of transforming the value. It will always mark any transformation as stale that is not using
|
||||
// the first transformer.
|
||||
func (t *prefixTransformers) TransformFromStorage(data []byte, context Context) ([]byte, bool, error) {
|
||||
for i, transformer := range t.transformers {
|
||||
if bytes.HasPrefix(data, transformer.Prefix) {
|
||||
result, stale, err := transformer.Transformer.TransformFromStorage(data[len(transformer.Prefix):], context)
|
||||
// To migrate away from encryption, user can specify an identity transformer higher up
|
||||
// (in the config file) than the encryption transformer. In that scenario, the identity transformer needs to
|
||||
// identify (during reads from disk) whether the data being read is encrypted or not. If the data is encrypted,
|
||||
// it shall throw an error, but that error should not prevent subsequent transformers from being tried.
|
||||
if len(transformer.Prefix) == 0 && err != nil {
|
||||
continue
|
||||
}
|
||||
return result, stale || i != 0, err
|
||||
}
|
||||
}
|
||||
return nil, false, t.err
|
||||
}
|
||||
|
||||
// TransformToStorage uses the first transformer and adds its prefix to the data.
|
||||
func (t *prefixTransformers) TransformToStorage(data []byte, context Context) ([]byte, error) {
|
||||
transformer := t.transformers[0]
|
||||
prefixedData := make([]byte, len(transformer.Prefix), len(data)+len(transformer.Prefix))
|
||||
copy(prefixedData, transformer.Prefix)
|
||||
result, err := transformer.Transformer.TransformToStorage(data, context)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prefixedData = append(prefixedData, result...)
|
||||
return prefixedData, nil
|
||||
}
|
||||
20
vendor/k8s.io/apiserver/pkg/util/feature/BUILD
generated
vendored
20
vendor/k8s.io/apiserver/pkg/util/feature/BUILD
generated
vendored
|
|
@ -1,7 +1,5 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
|
|
@ -12,16 +10,30 @@ go_test(
|
|||
name = "go_default_test",
|
||||
srcs = ["feature_gate_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = ["//vendor/github.com/spf13/pflag:go_default_library"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["feature_gate.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
|
|
|||
32
vendor/k8s.io/apiserver/pkg/util/feature/feature_gate.go
generated
vendored
32
vendor/k8s.io/apiserver/pkg/util/feature/feature_gate.go
generated
vendored
|
|
@ -21,6 +21,7 @@ import (
|
|||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
|
|
@ -70,15 +71,23 @@ const (
|
|||
// FeatureGate parses and stores flag gates for known features from
|
||||
// a string like feature1=true,feature2=false,...
|
||||
type FeatureGate interface {
|
||||
// AddFlag adds a flag for setting global feature gates to the specified FlagSet.
|
||||
AddFlag(fs *pflag.FlagSet)
|
||||
// Set parses and stores flag gates for known features
|
||||
// from a string like feature1=true,feature2=false,...
|
||||
Set(value string) error
|
||||
// Enabled returns true if the key is enabled.
|
||||
Enabled(key Feature) bool
|
||||
// Add adds features to the featureGate.
|
||||
Add(features map[Feature]FeatureSpec) error
|
||||
// KnownFeatures returns a slice of strings describing the FeatureGate's known features.
|
||||
KnownFeatures() []string
|
||||
}
|
||||
|
||||
// featureGate implements FeatureGate as well as pflag.Value for flag parsing.
|
||||
type featureGate struct {
|
||||
lock sync.RWMutex
|
||||
|
||||
known map[Feature]FeatureSpec
|
||||
special map[Feature]func(*featureGate, bool)
|
||||
enabled map[Feature]bool
|
||||
|
|
@ -112,9 +121,12 @@ func NewFeatureGate() *featureGate {
|
|||
return f
|
||||
}
|
||||
|
||||
// Set Parses a string of the form // "key1=value1,key2=value2,..." into a
|
||||
// Set Parses a string of the form "key1=value1,key2=value2,..." into a
|
||||
// map[string]bool of known keys or returns an error.
|
||||
func (f *featureGate) Set(value string) error {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for _, s := range strings.Split(value, ",") {
|
||||
if len(s) == 0 {
|
||||
continue
|
||||
|
|
@ -145,7 +157,11 @@ func (f *featureGate) Set(value string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// String returns a string containing all enabled feature gates, formatted as "key1=value1,key2=value2,...".
|
||||
func (f *featureGate) String() string {
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
pairs := []string{}
|
||||
for k, v := range f.enabled {
|
||||
pairs = append(pairs, fmt.Sprintf("%s=%t", k, v))
|
||||
|
|
@ -158,7 +174,11 @@ func (f *featureGate) Type() string {
|
|||
return "mapStringBool"
|
||||
}
|
||||
|
||||
// Add adds features to the featureGate.
|
||||
func (f *featureGate) Add(features map[Feature]FeatureSpec) error {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.closed {
|
||||
return fmt.Errorf("cannot add a feature gate after adding it to the flag set")
|
||||
}
|
||||
|
|
@ -176,7 +196,11 @@ func (f *featureGate) Add(features map[Feature]FeatureSpec) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Enabled returns true if the key is enabled.
|
||||
func (f *featureGate) Enabled(key Feature) bool {
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
|
||||
defaultValue := f.known[key].Default
|
||||
if f.enabled != nil {
|
||||
if v, ok := f.enabled[key]; ok {
|
||||
|
|
@ -188,7 +212,9 @@ func (f *featureGate) Enabled(key Feature) bool {
|
|||
|
||||
// AddFlag adds a flag for setting global feature gates to the specified FlagSet.
|
||||
func (f *featureGate) AddFlag(fs *pflag.FlagSet) {
|
||||
f.lock.Lock()
|
||||
f.closed = true
|
||||
f.lock.Unlock()
|
||||
|
||||
known := f.KnownFeatures()
|
||||
fs.Var(f, flagName, ""+
|
||||
|
|
@ -196,8 +222,10 @@ func (f *featureGate) AddFlag(fs *pflag.FlagSet) {
|
|||
"Options are:\n"+strings.Join(known, "\n"))
|
||||
}
|
||||
|
||||
// Returns a string describing the FeatureGate's known features.
|
||||
// KnownFeatures returns a slice of strings describing the FeatureGate's known features.
|
||||
func (f *featureGate) KnownFeatures() []string {
|
||||
f.lock.RLock()
|
||||
defer f.lock.RUnlock()
|
||||
var known []string
|
||||
for k, v := range f.known {
|
||||
pre := ""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue