Plumb failure policy from config to webhook construction

This commit is contained in:
Jordan Liggitt 2023-11-02 13:55:35 -04:00
parent a000af25ff
commit 2e2f51a441
No known key found for this signature in database
5 changed files with 23 additions and 10 deletions

View File

@ -118,11 +118,21 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
var decisionOnError authorizer.Decision
switch configuredAuthorizer.Webhook.FailurePolicy {
case authzconfig.FailurePolicyNoOpinion:
decisionOnError = authorizer.DecisionNoOpinion
case authzconfig.FailurePolicyDeny:
decisionOnError = authorizer.DecisionDeny
default:
return nil, nil, fmt.Errorf("unknown failurePolicy %q", configuredAuthorizer.Webhook.FailurePolicy)
}
webhookAuthorizer, err := webhook.New(clientConfig, webhookAuthorizer, err := webhook.New(clientConfig,
configuredAuthorizer.Webhook.SubjectAccessReviewVersion, configuredAuthorizer.Webhook.SubjectAccessReviewVersion,
configuredAuthorizer.Webhook.AuthorizedTTL.Duration, configuredAuthorizer.Webhook.AuthorizedTTL.Duration,
configuredAuthorizer.Webhook.UnauthorizedTTL.Duration, configuredAuthorizer.Webhook.UnauthorizedTTL.Duration,
*config.WebhookRetryBackoff, *config.WebhookRetryBackoff,
decisionOnError,
configuredAuthorizer.Webhook.MatchConditions, configuredAuthorizer.Webhook.MatchConditions,
) )
if err != nil { if err != nil {

View File

@ -54,6 +54,7 @@ func (c DelegatingAuthorizerConfig) New() (authorizer.Authorizer, error) {
c.AllowCacheTTL, c.AllowCacheTTL,
c.DenyCacheTTL, c.DenyCacheTTL,
*c.WebhookRetryBackoff, *c.WebhookRetryBackoff,
authorizer.DecisionNoOpinion,
webhook.AuthorizerMetrics{ webhook.AuthorizerMetrics{
RecordRequestTotal: RecordRequestTotal, RecordRequestTotal: RecordRequestTotal,
RecordRequestLatency: RecordRequestLatency, RecordRequestLatency: RecordRequestLatency,

View File

@ -75,8 +75,8 @@ type WebhookAuthorizer struct {
} }
// NewFromInterface creates a WebhookAuthorizer using the given subjectAccessReview client // NewFromInterface creates a WebhookAuthorizer using the given subjectAccessReview client
func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1Interface, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, metrics AuthorizerMetrics) (*WebhookAuthorizer, error) { func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1Interface, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, decisionOnError authorizer.Decision, metrics AuthorizerMetrics) (*WebhookAuthorizer, error) {
return newWithBackoff(&subjectAccessReviewV1Client{subjectAccessReview.RESTClient()}, authorizedTTL, unauthorizedTTL, retryBackoff, nil, metrics) return newWithBackoff(&subjectAccessReviewV1Client{subjectAccessReview.RESTClient()}, authorizedTTL, unauthorizedTTL, retryBackoff, decisionOnError, nil, metrics)
} }
// New creates a new WebhookAuthorizer from the provided kubeconfig file. // New creates a new WebhookAuthorizer from the provided kubeconfig file.
@ -98,19 +98,19 @@ func NewFromInterface(subjectAccessReview authorizationv1client.AuthorizationV1I
// //
// For additional HTTP configuration, refer to the kubeconfig documentation // For additional HTTP configuration, refer to the kubeconfig documentation
// https://kubernetes.io/docs/user-guide/kubeconfig-file/. // https://kubernetes.io/docs/user-guide/kubeconfig-file/.
func New(config *rest.Config, version string, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, matchConditions []apiserver.WebhookMatchCondition) (*WebhookAuthorizer, error) { func New(config *rest.Config, version string, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, decisionOnError authorizer.Decision, matchConditions []apiserver.WebhookMatchCondition) (*WebhookAuthorizer, error) {
subjectAccessReview, err := subjectAccessReviewInterfaceFromConfig(config, version, retryBackoff) subjectAccessReview, err := subjectAccessReviewInterfaceFromConfig(config, version, retryBackoff)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return newWithBackoff(subjectAccessReview, authorizedTTL, unauthorizedTTL, retryBackoff, matchConditions, AuthorizerMetrics{ return newWithBackoff(subjectAccessReview, authorizedTTL, unauthorizedTTL, retryBackoff, decisionOnError, matchConditions, AuthorizerMetrics{
RecordRequestTotal: noopMetrics{}.RecordRequestTotal, RecordRequestTotal: noopMetrics{}.RecordRequestTotal,
RecordRequestLatency: noopMetrics{}.RecordRequestLatency, RecordRequestLatency: noopMetrics{}.RecordRequestLatency,
}) })
} }
// newWithBackoff allows tests to skip the sleep. // newWithBackoff allows tests to skip the sleep.
func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, matchConditions []apiserver.WebhookMatchCondition, metrics AuthorizerMetrics) (*WebhookAuthorizer, error) { func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, unauthorizedTTL time.Duration, retryBackoff wait.Backoff, decisionOnError authorizer.Decision, matchConditions []apiserver.WebhookMatchCondition, metrics AuthorizerMetrics) (*WebhookAuthorizer, error) {
// compile all expressions once in validation and save the results to be used for eval later // compile all expressions once in validation and save the results to be used for eval later
cm, fieldErr := apiservervalidation.ValidateAndCompileMatchConditions(matchConditions) cm, fieldErr := apiservervalidation.ValidateAndCompileMatchConditions(matchConditions)
if err := fieldErr.ToAggregate(); err != nil { if err := fieldErr.ToAggregate(); err != nil {
@ -122,7 +122,7 @@ func newWithBackoff(subjectAccessReview subjectAccessReviewer, authorizedTTL, un
authorizedTTL: authorizedTTL, authorizedTTL: authorizedTTL,
unauthorizedTTL: unauthorizedTTL, unauthorizedTTL: unauthorizedTTL,
retryBackoff: retryBackoff, retryBackoff: retryBackoff,
decisionOnError: authorizer.DecisionNoOpinion, decisionOnError: decisionOnError,
metrics: metrics, metrics: metrics,
celMatcher: cm, celMatcher: cm,
}, nil }, nil

View File

@ -37,6 +37,7 @@ import (
utiltesting "k8s.io/client-go/util/testing" utiltesting "k8s.io/client-go/util/testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
authorizationv1 "k8s.io/api/authorization/v1" authorizationv1 "k8s.io/api/authorization/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
@ -209,7 +210,7 @@ current-context: default
if err != nil { if err != nil {
return fmt.Errorf("error building sar client: %v", err) return fmt.Errorf("error building sar client: %v", err)
} }
_, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, []apiserver.WebhookMatchCondition{}, noopAuthorizerMetrics()) _, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, authorizer.DecisionNoOpinion, []apiserver.WebhookMatchCondition{}, noopAuthorizerMetrics())
return err return err
}() }()
if err != nil && !tt.wantErr { if err != nil && !tt.wantErr {
@ -352,7 +353,7 @@ func newV1Authorizer(callbackURL string, clientCert, clientKey, ca []byte, cache
if err != nil { if err != nil {
return nil, fmt.Errorf("error building sar client: %v", err) return nil, fmt.Errorf("error building sar client: %v", err)
} }
return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, expressions, metrics) return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, authorizer.DecisionNoOpinion, expressions, metrics)
} }
func TestV1TLSConfig(t *testing.T) { func TestV1TLSConfig(t *testing.T) {

View File

@ -35,6 +35,7 @@ import (
"time" "time"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
authorizationv1beta1 "k8s.io/api/authorization/v1beta1" authorizationv1beta1 "k8s.io/api/authorization/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
authzconfig "k8s.io/apiserver/pkg/apis/apiserver" authzconfig "k8s.io/apiserver/pkg/apis/apiserver"
@ -196,7 +197,7 @@ current-context: default
if err != nil { if err != nil {
return fmt.Errorf("error building sar client: %v", err) return fmt.Errorf("error building sar client: %v", err)
} }
_, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, []authzconfig.WebhookMatchCondition{}, noopAuthorizerMetrics()) _, err = newWithBackoff(sarClient, 0, 0, testRetryBackoff, authorizer.DecisionNoOpinion, []authzconfig.WebhookMatchCondition{}, noopAuthorizerMetrics())
return err return err
}() }()
if err != nil && !tt.wantErr { if err != nil && !tt.wantErr {
@ -339,7 +340,7 @@ func newV1beta1Authorizer(callbackURL string, clientCert, clientKey, ca []byte,
if err != nil { if err != nil {
return nil, fmt.Errorf("error building sar client: %v", err) return nil, fmt.Errorf("error building sar client: %v", err)
} }
return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, []authzconfig.WebhookMatchCondition{}, noopAuthorizerMetrics()) return newWithBackoff(sarClient, cacheTime, cacheTime, testRetryBackoff, authorizer.DecisionNoOpinion, []authzconfig.WebhookMatchCondition{}, noopAuthorizerMetrics())
} }
func TestV1beta1TLSConfig(t *testing.T) { func TestV1beta1TLSConfig(t *testing.T) {