|
6 | 6 | "context" |
7 | 7 | "encoding/json" |
8 | 8 | "fmt" |
| 9 | + "strings" |
9 | 10 | "time" |
10 | 11 |
|
11 | 12 | v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" |
@@ -1197,6 +1198,86 @@ var _ = Describe("Proxy", func() { |
1197 | 1198 | }) |
1198 | 1199 | }) |
1199 | 1200 | }) |
| 1201 | + |
| 1202 | + When("creating and getting a large configmap through the proxy", func() { |
| 1203 | + // This test validates both gzip failure paths: |
| 1204 | + // 1. The workflow engine path (WriteToKube in activity.go): a large CREATE |
| 1205 | + // response is gzip-encoded by kube; without the fix, WriteToKube would |
| 1206 | + // forward Accept-Encoding from the client, preventing the REST transport |
| 1207 | + // from auto-decompressing, and the client receives raw gzip bytes. |
| 1208 | + // 2. The reverse proxy path (Director in server.go): a large GET response |
| 1209 | + // is gzip-encoded by kube; without the fix, FilterResp receives gzip |
| 1210 | + // bytes and fails to decode them as JSON. |
| 1211 | + BeforeEach(func() { |
| 1212 | + createConfigMap := proxyrule.Config{Spec: proxyrule.Spec{ |
| 1213 | + Locking: proxyrule.OptimisticLockMode, |
| 1214 | + Matches: []proxyrule.Match{{ |
| 1215 | + GroupVersion: "v1", |
| 1216 | + Resource: "configmaps", |
| 1217 | + Verbs: []string{"create"}, |
| 1218 | + }}, |
| 1219 | + Update: proxyrule.Update{ |
| 1220 | + CreateRelationships: []proxyrule.StringOrTemplate{{ |
| 1221 | + // testresource view = viewer + creator, so this grants |
| 1222 | + // the creator permission to view the configmap below. |
| 1223 | + Template: "testresource:{{namespacedName}}#creator@user:{{user.name}}", |
| 1224 | + }}, |
| 1225 | + }, |
| 1226 | + }} |
| 1227 | + |
| 1228 | + getConfigMap := proxyrule.Config{Spec: proxyrule.Spec{ |
| 1229 | + Matches: []proxyrule.Match{{ |
| 1230 | + GroupVersion: "v1", |
| 1231 | + Resource: "configmaps", |
| 1232 | + Verbs: []string{"get"}, |
| 1233 | + }}, |
| 1234 | + Checks: []proxyrule.StringOrTemplate{{ |
| 1235 | + Template: "testresource:{{namespacedName}}#view@user:{{user.name}}", |
| 1236 | + }}, |
| 1237 | + }} |
| 1238 | + |
| 1239 | + matcher, err := rules.NewMapMatcher([]proxyrule.Config{ |
| 1240 | + createNamespace(), |
| 1241 | + createConfigMap, |
| 1242 | + getConfigMap, |
| 1243 | + }) |
| 1244 | + Expect(err).To(Succeed()) |
| 1245 | + *proxySrv.Matcher = matcher |
| 1246 | + }) |
| 1247 | + |
| 1248 | + It("handles gzip-encoded responses from the workflow engine and reverse proxy", func(ctx context.Context) { |
| 1249 | + // Create namespace via proxy (goes through workflow engine). |
| 1250 | + Expect(CreateNamespace(ctx, paulClient, paulNamespace)).To(Succeed()) |
| 1251 | + |
| 1252 | + // 300KB is large enough to trigger kube's gzip encoding (threshold ~128KB). |
| 1253 | + const dataSize = 300 * 1024 |
| 1254 | + cmName := names.SimpleNameGenerator.GenerateName("large-cm-") |
| 1255 | + |
| 1256 | + // CREATE the large configmap through the proxy. |
| 1257 | + // This goes through the workflow engine (WriteToKube in activity.go). |
| 1258 | + // kube gzip-encodes the ~300KB 201 Created response; without the fix |
| 1259 | + // in WriteToKube, the client receives raw gzip bytes and fails to decode. |
| 1260 | + _, err := paulClient.CoreV1().ConfigMaps(paulNamespace).Create(ctx, &corev1.ConfigMap{ |
| 1261 | + ObjectMeta: metav1.ObjectMeta{ |
| 1262 | + Name: cmName, |
| 1263 | + Namespace: paulNamespace, |
| 1264 | + }, |
| 1265 | + Data: map[string]string{ |
| 1266 | + "payload": strings.Repeat("x", dataSize), |
| 1267 | + }, |
| 1268 | + }, metav1.CreateOptions{}) |
| 1269 | + Expect(err).To(Succeed()) |
| 1270 | + |
| 1271 | + // GET the large configmap through the proxy. |
| 1272 | + // This goes through the reverse proxy (Director + FilterResp in server.go). |
| 1273 | + // kube gzip-encodes the ~300KB response; without the fix in Director, |
| 1274 | + // FilterResp receives gzip bytes and cannot decode them as JSON. |
| 1275 | + cm, err := paulClient.CoreV1().ConfigMaps(paulNamespace).Get(ctx, cmName, metav1.GetOptions{}) |
| 1276 | + Expect(err).To(Succeed()) |
| 1277 | + Expect(cm.Name).To(Equal(cmName)) |
| 1278 | + Expect(cm.Data["payload"]).To(HaveLen(dataSize)) |
| 1279 | + }) |
| 1280 | + }) |
1200 | 1281 | }) |
1201 | 1282 | }) |
1202 | 1283 |
|
|
0 commit comments