Skip to content

Commit 68e3ced

Browse files
authored
Merge pull request kubernetes#121822 from ritazh/webhookauthz-benchmark
[StructuredAuthz] Webhookauthz benchmark
2 parents 36930f4 + 7c5dfce commit 68e3ced

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed

staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_v1_test.go

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,212 @@ func TestStructuredAuthzConfigFeatureEnablement(t *testing.T) {
782782
}
783783
}
784784

785+
func BenchmarkNoCELExpressionFeatureOff(b *testing.B) {
786+
expressions := []apiserver.WebhookMatchCondition{}
787+
b.Run("compile", func(b *testing.B) {
788+
benchmarkNewWebhookAuthorizer(b, expressions, false)
789+
})
790+
b.Run("authorize", func(b *testing.B) {
791+
benchmarkWebhookAuthorize(b, expressions, false)
792+
})
793+
}
794+
795+
func BenchmarkNoCELExpressionFeatureOn(b *testing.B) {
796+
expressions := []apiserver.WebhookMatchCondition{}
797+
b.Run("compile", func(b *testing.B) {
798+
benchmarkNewWebhookAuthorizer(b, expressions, true)
799+
})
800+
b.Run("authorize", func(b *testing.B) {
801+
benchmarkWebhookAuthorize(b, expressions, true)
802+
})
803+
}
804+
func BenchmarkWithOneCELExpressions(b *testing.B) {
805+
expressions := []apiserver.WebhookMatchCondition{
806+
{
807+
Expression: "request.user == 'alice'",
808+
},
809+
}
810+
b.Run("compile", func(b *testing.B) {
811+
benchmarkNewWebhookAuthorizer(b, expressions, true)
812+
})
813+
b.Run("authorize", func(b *testing.B) {
814+
benchmarkWebhookAuthorize(b, expressions, true)
815+
})
816+
}
817+
func BenchmarkWithOneCELExpressionsFalse(b *testing.B) {
818+
expressions := []apiserver.WebhookMatchCondition{
819+
{
820+
Expression: "request.user == 'alice2'",
821+
},
822+
}
823+
b.Run("compile", func(b *testing.B) {
824+
benchmarkNewWebhookAuthorizer(b, expressions, true)
825+
})
826+
b.Run("authorize", func(b *testing.B) {
827+
benchmarkWebhookAuthorize(b, expressions, true)
828+
})
829+
}
830+
func BenchmarkWithTwoCELExpressions(b *testing.B) {
831+
expressions := []apiserver.WebhookMatchCondition{
832+
{
833+
Expression: "request.user == 'alice'",
834+
},
835+
{
836+
Expression: "request.uid == '1'",
837+
},
838+
}
839+
b.Run("compile", func(b *testing.B) {
840+
benchmarkNewWebhookAuthorizer(b, expressions, true)
841+
})
842+
b.Run("authorize", func(b *testing.B) {
843+
benchmarkWebhookAuthorize(b, expressions, true)
844+
})
845+
}
846+
func BenchmarkWithTwoCELExpressionsFalse(b *testing.B) {
847+
expressions := []apiserver.WebhookMatchCondition{
848+
{
849+
Expression: "request.user == 'alice'",
850+
},
851+
{
852+
Expression: "request.uid == '2'",
853+
},
854+
}
855+
b.Run("compile", func(b *testing.B) {
856+
benchmarkNewWebhookAuthorizer(b, expressions, true)
857+
})
858+
b.Run("authorize", func(b *testing.B) {
859+
benchmarkWebhookAuthorize(b, expressions, true)
860+
})
861+
}
862+
func BenchmarkWithManyCELExpressions(b *testing.B) {
863+
expressions := []apiserver.WebhookMatchCondition{
864+
{
865+
Expression: "request.user == 'alice'",
866+
},
867+
{
868+
Expression: "request.uid == '1'",
869+
},
870+
{
871+
Expression: "('group1' in request.groups)",
872+
},
873+
{
874+
Expression: "('key1' in request.extra)",
875+
},
876+
{
877+
Expression: "!('key2' in request.extra)",
878+
},
879+
{
880+
Expression: "('a' in request.extra['key1'])",
881+
},
882+
{
883+
Expression: "!('z' in request.extra['key1'])",
884+
},
885+
{
886+
Expression: "has(request.resourceAttributes) && request.resourceAttributes.namespace == 'kittensandponies'",
887+
},
888+
}
889+
b.Run("compile", func(b *testing.B) {
890+
benchmarkNewWebhookAuthorizer(b, expressions, true)
891+
})
892+
b.Run("authorize", func(b *testing.B) {
893+
benchmarkWebhookAuthorize(b, expressions, true)
894+
})
895+
}
896+
func BenchmarkWithManyCELExpressionsFalse(b *testing.B) {
897+
expressions := []apiserver.WebhookMatchCondition{
898+
{
899+
Expression: "request.user == 'alice'",
900+
},
901+
{
902+
Expression: "request.uid == '1'",
903+
},
904+
{
905+
Expression: "('group1' in request.groups)",
906+
},
907+
{
908+
Expression: "('key1' in request.extra)",
909+
},
910+
{
911+
Expression: "!('key2' in request.extra)",
912+
},
913+
{
914+
Expression: "('a' in request.extra['key1'])",
915+
},
916+
{
917+
Expression: "!('z' in request.extra['key1'])",
918+
},
919+
{
920+
Expression: "has(request.resourceAttributes) && request.resourceAttributes.namespace == 'kittensandponies1'",
921+
},
922+
}
923+
b.Run("compile", func(b *testing.B) {
924+
benchmarkNewWebhookAuthorizer(b, expressions, true)
925+
})
926+
b.Run("authorize", func(b *testing.B) {
927+
benchmarkWebhookAuthorize(b, expressions, true)
928+
})
929+
}
930+
931+
func benchmarkNewWebhookAuthorizer(b *testing.B, expressions []apiserver.WebhookMatchCondition, featureEnabled bool) {
932+
service := new(mockV1Service)
933+
service.statusCode = 200
934+
service.Allow()
935+
s, err := NewV1TestServer(service, serverCert, serverKey, caCert)
936+
if err != nil {
937+
b.Fatal(err)
938+
}
939+
defer s.Close()
940+
defer featuregatetesting.SetFeatureGateDuringTest(b, utilfeature.DefaultFeatureGate, features.StructuredAuthorizationConfiguration, featureEnabled)()
941+
942+
b.ResetTimer()
943+
for i := 0; i < b.N; i++ {
944+
// Create an authorizer with or without expressions to compile
945+
_, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), expressions)
946+
if err != nil {
947+
b.Fatal(err)
948+
}
949+
}
950+
b.StopTimer()
951+
}
952+
953+
func benchmarkWebhookAuthorize(b *testing.B, expressions []apiserver.WebhookMatchCondition, featureEnabled bool) {
954+
attr := authorizer.AttributesRecord{
955+
User: &user.DefaultInfo{
956+
Name: "alice",
957+
UID: "1",
958+
Groups: []string{"group1", "group2"},
959+
Extra: map[string][]string{"key1": {"a", "b", "c"}},
960+
},
961+
ResourceRequest: true,
962+
Namespace: "kittensandponies",
963+
Verb: "get",
964+
}
965+
service := new(mockV1Service)
966+
service.statusCode = 200
967+
service.Allow()
968+
s, err := NewV1TestServer(service, serverCert, serverKey, caCert)
969+
if err != nil {
970+
b.Fatal(err)
971+
}
972+
defer s.Close()
973+
defer featuregatetesting.SetFeatureGateDuringTest(b, utilfeature.DefaultFeatureGate, features.StructuredAuthorizationConfiguration, featureEnabled)()
974+
// Create an authorizer with or without expressions to compile
975+
wh, err := newV1Authorizer(s.URL, clientCert, clientKey, caCert, 0, noopAuthorizerMetrics(), expressions)
976+
if err != nil {
977+
b.Fatal(err)
978+
}
979+
980+
b.ResetTimer()
981+
for i := 0; i < b.N; i++ {
982+
// Call authorize may or may not require cel evaluations
983+
_, _, err = wh.Authorize(context.Background(), attr)
984+
if err != nil {
985+
b.Fatal(err)
986+
}
987+
}
988+
b.StopTimer()
989+
}
990+
785991
// TestV1WebhookMatchConditions verifies cel expressions are compiled and evaluated correctly
786992
func TestV1WebhookMatchConditions(t *testing.T) {
787993
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.StructuredAuthorizationConfiguration, true)()

0 commit comments

Comments
 (0)