mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +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.
|
--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-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-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.
|
--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.
|
--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).
|
--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.
|
--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 -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
|
@ -23,6 +23,8 @@ authentication-token-webhook-config-file
|
|||||||
authorization-mode
|
authorization-mode
|
||||||
authorization-policy-file
|
authorization-policy-file
|
||||||
authorization-webhook-config-file
|
authorization-webhook-config-file
|
||||||
|
authorization-webhook-cache-authorized-ttl
|
||||||
|
authorization-webhook-cache-unauthorized-ttl
|
||||||
babysit-daemons
|
babysit-daemons
|
||||||
basic-auth-file
|
basic-auth-file
|
||||||
bench-pods
|
bench-pods
|
||||||
|
@ -19,6 +19,7 @@ package apiserver
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
||||||
@ -77,6 +78,10 @@ type AuthorizationConfig struct {
|
|||||||
|
|
||||||
// Kubeconfig file for Webhook authorization plugin.
|
// Kubeconfig file for Webhook authorization plugin.
|
||||||
WebhookConfigFile string
|
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
|
// 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 == "" {
|
if config.WebhookConfigFile == "" {
|
||||||
return nil, errors.New("Webhook's configuration file not passed")
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/admission"
|
"k8s.io/kubernetes/pkg/admission"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
@ -103,10 +104,14 @@ type ServerRunOptions struct {
|
|||||||
|
|
||||||
func NewServerRunOptions() *ServerRunOptions {
|
func NewServerRunOptions() *ServerRunOptions {
|
||||||
return &ServerRunOptions{
|
return &ServerRunOptions{
|
||||||
APIGroupPrefix: "/apis",
|
APIGroupPrefix: "/apis",
|
||||||
APIPrefix: "/api",
|
APIPrefix: "/api",
|
||||||
AdmissionControl: "AlwaysAdmit",
|
AdmissionControl: "AlwaysAdmit",
|
||||||
AuthorizationMode: "AlwaysAllow",
|
AuthorizationMode: "AlwaysAllow",
|
||||||
|
AuthorizationConfig: apiserver.AuthorizationConfig{
|
||||||
|
WebhookCacheAuthorizedTTL: 5 * time.Minute,
|
||||||
|
WebhookCacheUnauthorizedTTL: 30 * time.Second,
|
||||||
|
},
|
||||||
BindAddress: net.ParseIP("0.0.0.0"),
|
BindAddress: net.ParseIP("0.0.0.0"),
|
||||||
CertDirectory: "/var/run/kubernetes",
|
CertDirectory: "/var/run/kubernetes",
|
||||||
DefaultStorageMediaType: "application/json",
|
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.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.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.")
|
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
|
package webhook
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/authorization/v1beta1"
|
"k8s.io/kubernetes/pkg/apis/authorization/v1beta1"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||||
|
"k8s.io/kubernetes/pkg/util/cache"
|
||||||
"k8s.io/kubernetes/plugin/pkg/webhook"
|
"k8s.io/kubernetes/plugin/pkg/webhook"
|
||||||
|
|
||||||
_ "k8s.io/kubernetes/pkg/apis/authorization/install"
|
_ "k8s.io/kubernetes/pkg/apis/authorization/install"
|
||||||
@ -37,6 +40,9 @@ var _ authorizer.Authorizer = (*WebhookAuthorizer)(nil)
|
|||||||
|
|
||||||
type WebhookAuthorizer struct {
|
type WebhookAuthorizer struct {
|
||||||
*webhook.GenericWebhook
|
*webhook.GenericWebhook
|
||||||
|
responseCache *cache.LRUExpireCache
|
||||||
|
authorizedTTL time.Duration
|
||||||
|
unauthorizedTTL time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new WebhookAuthorizer from the provided kubeconfig file.
|
// 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
|
// For additional HTTP configuration, refer to the kubeconfig documentation
|
||||||
// http://kubernetes.io/v1.1/docs/user-guide/kubeconfig-file.html.
|
// 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)
|
gw, err := webhook.NewGenericWebhook(kubeConfigFile, groupVersions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// 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(),
|
Verb: attr.GetVerb(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result := w.RestClient.Post().Body(r).Do()
|
key, err := json.Marshal(r.Spec)
|
||||||
if err := result.Error(); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if entry, ok := w.responseCache.Get(string(key)); ok {
|
||||||
if err := result.Into(r); err != nil {
|
r.Status = entry.(v1beta1.SubjectAccessReviewStatus)
|
||||||
return err
|
} 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 {
|
if r.Status.Allowed {
|
||||||
return nil
|
return nil
|
||||||
|
@ -182,7 +182,7 @@ current-context: default
|
|||||||
return fmt.Errorf("failed to execute test template: %v", err)
|
return fmt.Errorf("failed to execute test template: %v", err)
|
||||||
}
|
}
|
||||||
// Create a new authorizer
|
// Create a new authorizer
|
||||||
_, err = New(p)
|
_, err = New(p, 0, 0)
|
||||||
return err
|
return err
|
||||||
}()
|
}()
|
||||||
if err != nil && !tt.wantErr {
|
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 {
|
if err := json.NewEncoder(tempfile).Encode(config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return New(p)
|
return New(p, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTLSConfig(t *testing.T) {
|
func TestTLSConfig(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user