mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 20:24:09 +00:00
Add LRU Expire cache to webhook authorizer.
This commit is contained in:
parent
346f965871
commit
d03dbbcc14
@ -60,6 +60,8 @@ kube-apiserver
|
||||
--authentication-token-webhook-config-file="": File with webhook configuration for token authentication in kubeconfig format. The API server will query the remote service to determine authentication for bearer tokens.
|
||||
--authorization-mode="AlwaysAllow": Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: AlwaysAllow,AlwaysDeny,ABAC,Webhook
|
||||
--authorization-policy-file="": File with authorization policy in csv format, used with --authorization-mode=ABAC, on the secure port.
|
||||
--authorization-webhook-cache-authorized-ttl=5m0s: The duration to cache 'authorized' responses from the webhook authorizer. Default is 5m.
|
||||
--authorization-webhook-cache-unauthorized-ttl=30s: The duration to cache 'unauthorized' responses from the webhook authorizer. Default is 30s.
|
||||
--authorization-webhook-config-file="": File with webhook configuration in kubeconfig format, used with --authorization-mode=Webhook. The API server will query the remote service to determine access on the API server's secure port.
|
||||
--basic-auth-file="": If set, the file that will be used to admit requests to the secure port of the API server via http basic authentication.
|
||||
--bind-address=0.0.0.0: The IP address on which to listen for the --secure-port port. The associated interface(s) must be reachable by the rest of the cluster, and by CLI/web clients. If blank, all interfaces will be used (0.0.0.0).
|
||||
@ -121,7 +123,7 @@ kube-apiserver
|
||||
--watch-cache-sizes=[]: List of watch cache sizes for every resource (pods, nodes, etc.), comma separated. The individual override format: resource#size, where size is a number. It takes effect when watch-cache is enabled.
|
||||
```
|
||||
|
||||
###### Auto generated by spf13/cobra on 17-May-2016
|
||||
###### Auto generated by spf13/cobra on 18-May-2016
|
||||
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
|
@ -23,6 +23,8 @@ authentication-token-webhook-config-file
|
||||
authorization-mode
|
||||
authorization-policy-file
|
||||
authorization-webhook-config-file
|
||||
authorization-webhook-cache-authorized-ttl
|
||||
authorization-webhook-cache-unauthorized-ttl
|
||||
babysit-daemons
|
||||
basic-auth-file
|
||||
bench-pods
|
||||
|
@ -19,6 +19,7 @@ package apiserver
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
||||
@ -77,6 +78,10 @@ type AuthorizationConfig struct {
|
||||
|
||||
// Kubeconfig file for Webhook authorization plugin.
|
||||
WebhookConfigFile string
|
||||
// TTL for caching of authorized responses from the webhook server.
|
||||
WebhookCacheAuthorizedTTL time.Duration
|
||||
// TTL for caching of unauthorized responses from the webhook server.
|
||||
WebhookCacheUnauthorizedTTL time.Duration
|
||||
}
|
||||
|
||||
// NewAuthorizerFromAuthorizationConfig returns the right sort of union of multiple authorizer.Authorizer objects
|
||||
@ -114,7 +119,9 @@ func NewAuthorizerFromAuthorizationConfig(authorizationModes []string, config Au
|
||||
if config.WebhookConfigFile == "" {
|
||||
return nil, errors.New("Webhook's configuration file not passed")
|
||||
}
|
||||
webhookAuthorizer, err := webhook.New(config.WebhookConfigFile)
|
||||
webhookAuthorizer, err := webhook.New(config.WebhookConfigFile,
|
||||
config.WebhookCacheAuthorizedTTL,
|
||||
config.WebhookCacheUnauthorizedTTL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
@ -103,10 +104,14 @@ type ServerRunOptions struct {
|
||||
|
||||
func NewServerRunOptions() *ServerRunOptions {
|
||||
return &ServerRunOptions{
|
||||
APIGroupPrefix: "/apis",
|
||||
APIPrefix: "/api",
|
||||
AdmissionControl: "AlwaysAdmit",
|
||||
AuthorizationMode: "AlwaysAllow",
|
||||
APIGroupPrefix: "/apis",
|
||||
APIPrefix: "/api",
|
||||
AdmissionControl: "AlwaysAdmit",
|
||||
AuthorizationMode: "AlwaysAllow",
|
||||
AuthorizationConfig: apiserver.AuthorizationConfig{
|
||||
WebhookCacheAuthorizedTTL: 5 * time.Minute,
|
||||
WebhookCacheUnauthorizedTTL: 30 * time.Second,
|
||||
},
|
||||
BindAddress: net.ParseIP("0.0.0.0"),
|
||||
CertDirectory: "/var/run/kubernetes",
|
||||
DefaultStorageMediaType: "application/json",
|
||||
@ -220,6 +225,8 @@ func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
|
||||
fs.StringVar(&s.AuthorizationConfig.PolicyFile, "authorization-policy-file", s.AuthorizationConfig.PolicyFile, "File with authorization policy in csv format, used with --authorization-mode=ABAC, on the secure port.")
|
||||
fs.StringVar(&s.AuthorizationConfig.WebhookConfigFile, "authorization-webhook-config-file", s.AuthorizationConfig.WebhookConfigFile, "File with webhook configuration in kubeconfig format, used with --authorization-mode=Webhook. The API server will query the remote service to determine access on the API server's secure port.")
|
||||
fs.DurationVar(&s.AuthorizationConfig.WebhookCacheAuthorizedTTL, "authorization-webhook-cache-authorized-ttl", s.AuthorizationConfig.WebhookCacheAuthorizedTTL, "The duration to cache 'authorized' responses from the webhook authorizer. Default is 5m.")
|
||||
fs.DurationVar(&s.AuthorizationConfig.WebhookCacheUnauthorizedTTL, "authorization-webhook-cache-unauthorized-ttl", s.AuthorizationConfig.WebhookCacheUnauthorizedTTL, "The duration to cache 'unauthorized' responses from the webhook authorizer. Default is 30s.")
|
||||
|
||||
fs.StringVar(&s.BasicAuthFile, "basic-auth-file", s.BasicAuthFile, "If set, the file that will be used to admit requests to the secure port of the API server via http basic authentication.")
|
||||
|
||||
|
@ -18,11 +18,14 @@ limitations under the License.
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/authorization/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||
"k8s.io/kubernetes/pkg/util/cache"
|
||||
"k8s.io/kubernetes/plugin/pkg/webhook"
|
||||
|
||||
_ "k8s.io/kubernetes/pkg/apis/authorization/install"
|
||||
@ -37,6 +40,9 @@ var _ authorizer.Authorizer = (*WebhookAuthorizer)(nil)
|
||||
|
||||
type WebhookAuthorizer struct {
|
||||
*webhook.GenericWebhook
|
||||
responseCache *cache.LRUExpireCache
|
||||
authorizedTTL time.Duration
|
||||
unauthorizedTTL time.Duration
|
||||
}
|
||||
|
||||
// New creates a new WebhookAuthorizer from the provided kubeconfig file.
|
||||
@ -59,12 +65,12 @@ type WebhookAuthorizer struct {
|
||||
//
|
||||
// For additional HTTP configuration, refer to the kubeconfig documentation
|
||||
// http://kubernetes.io/v1.1/docs/user-guide/kubeconfig-file.html.
|
||||
func New(kubeConfigFile string) (*WebhookAuthorizer, error) {
|
||||
func New(kubeConfigFile string, authorizedTTL, unauthorizedTTL time.Duration) (*WebhookAuthorizer, error) {
|
||||
gw, err := webhook.NewGenericWebhook(kubeConfigFile, groupVersions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &WebhookAuthorizer{gw}, nil
|
||||
return &WebhookAuthorizer{gw, cache.NewLRUExpireCache(1024), authorizedTTL, unauthorizedTTL}, nil
|
||||
}
|
||||
|
||||
// Authorize makes a REST request to the remote service describing the attempted action as a JSON
|
||||
@ -134,13 +140,27 @@ func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (err error) {
|
||||
Verb: attr.GetVerb(),
|
||||
}
|
||||
}
|
||||
result := w.RestClient.Post().Body(r).Do()
|
||||
if err := result.Error(); err != nil {
|
||||
key, err := json.Marshal(r.Spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := result.Into(r); err != nil {
|
||||
return err
|
||||
if entry, ok := w.responseCache.Get(string(key)); ok {
|
||||
r.Status = entry.(v1beta1.SubjectAccessReviewStatus)
|
||||
} else {
|
||||
result := w.RestClient.Post().Body(r).Do()
|
||||
if err := result.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := result.Into(r); err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
if r.Status.Allowed {
|
||||
w.responseCache.Add(string(key), r.Status, w.authorizedTTL)
|
||||
} else {
|
||||
w.responseCache.Add(string(key), r.Status, w.unauthorizedTTL)
|
||||
}
|
||||
}()
|
||||
}
|
||||
if r.Status.Allowed {
|
||||
return nil
|
||||
|
@ -182,7 +182,7 @@ current-context: default
|
||||
return fmt.Errorf("failed to execute test template: %v", err)
|
||||
}
|
||||
// Create a new authorizer
|
||||
_, err = New(p)
|
||||
_, err = New(p, 0, 0)
|
||||
return err
|
||||
}()
|
||||
if err != nil && !tt.wantErr {
|
||||
@ -283,7 +283,7 @@ func newAuthorizer(callbackURL string, clientCert, clientKey, ca []byte) (*Webho
|
||||
if err := json.NewEncoder(tempfile).Encode(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return New(p)
|
||||
return New(p, 0, 0)
|
||||
}
|
||||
|
||||
func TestTLSConfig(t *testing.T) {
|
||||
|
Loading…
Reference in New Issue
Block a user