diff --git a/examples/advanced-web-service/__snapshots__/chart.test.ts.snap b/examples/advanced-web-service/__snapshots__/chart.test.ts.snap index f239eda..fb5ae7b 100644 --- a/examples/advanced-web-service/__snapshots__/chart.test.ts.snap +++ b/examples/advanced-web-service/__snapshots__/chart.test.ts.snap @@ -82,15 +82,17 @@ server { gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; location / { - proxy_pass http://application; - proxy_http_version 1.1; - - proxy_set_header Connection $connection_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + + } location /livez { access_log off; @@ -106,6 +108,8 @@ server { allow 172.16.0.0/12; deny all; } + + } ", "samesite.conf": "# Implements SameSite cookie flags to ensure that our Login Server cookies are flagged as \`SameSite=None\` and \`Secure\`. @@ -185,7 +189,7 @@ proxy_cookie_path / "/$cookie_path_patches"; "region": "local", "service": "advanced-development-local", }, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", "namespace": "advanced-test", }, }, @@ -617,7 +621,7 @@ proxy_cookie_path / "/$cookie_path_patches"; { "configMap": { "defaultMode": 292, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", }, "name": "nginx-config", }, @@ -711,15 +715,17 @@ server { gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; location / { - proxy_pass http://application; - proxy_http_version 1.1; - - proxy_set_header Connection $connection_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + + } location /livez { access_log off; @@ -735,6 +741,8 @@ server { allow 172.16.0.0/12; deny all; } + + } ", "samesite.conf": "# Implements SameSite cookie flags to ensure that our Login Server cookies are flagged as \`SameSite=None\` and \`Secure\`. @@ -814,7 +822,7 @@ proxy_cookie_path / "/$cookie_path_patches"; "region": "local", "service": "advanced-development-local", }, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", "namespace": "advanced-test", }, }, @@ -1103,7 +1111,7 @@ proxy_cookie_path / "/$cookie_path_patches"; { "configMap": { "defaultMode": 292, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", }, "name": "nginx-config", }, @@ -1466,7 +1474,7 @@ proxy_cookie_path / "/$cookie_path_patches"; { "configMap": { "defaultMode": 292, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", }, "name": "nginx-config", }, @@ -1560,15 +1568,17 @@ server { gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; location / { - proxy_pass http://application; - proxy_http_version 1.1; - - proxy_set_header Connection $connection_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + + } location /livez { access_log off; @@ -1584,6 +1594,8 @@ server { allow 172.16.0.0/12; deny all; } + + } ", "samesite.conf": "# Implements SameSite cookie flags to ensure that our Login Server cookies are flagged as \`SameSite=None\` and \`Secure\`. @@ -1663,7 +1675,7 @@ proxy_cookie_path / "/$cookie_path_patches"; "region": "local", "service": "advanced-development-local", }, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", "namespace": "advanced-test", }, }, @@ -2095,7 +2107,7 @@ proxy_cookie_path / "/$cookie_path_patches"; { "configMap": { "defaultMode": 292, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", }, "name": "nginx-config", }, @@ -2189,15 +2201,17 @@ server { gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; location / { - proxy_pass http://application; - proxy_http_version 1.1; - - proxy_set_header Connection $connection_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + + } location /livez { access_log off; @@ -2213,6 +2227,8 @@ server { allow 172.16.0.0/12; deny all; } + + } ", "samesite.conf": "# Implements SameSite cookie flags to ensure that our Login Server cookies are flagged as \`SameSite=None\` and \`Secure\`. @@ -2292,7 +2308,7 @@ proxy_cookie_path / "/$cookie_path_patches"; "region": "local", "service": "advanced-development-local", }, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", "namespace": "advanced-test", }, }, @@ -2580,7 +2596,7 @@ proxy_cookie_path / "/$cookie_path_patches"; { "configMap": { "defaultMode": 292, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", }, "name": "nginx-config", }, @@ -2943,7 +2959,7 @@ proxy_cookie_path / "/$cookie_path_patches"; { "configMap": { "defaultMode": 292, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", }, "name": "nginx-config", }, @@ -3037,15 +3053,17 @@ server { gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; location / { - proxy_pass http://application; - proxy_http_version 1.1; - - proxy_set_header Connection $connection_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + + } location /livez { access_log off; @@ -3061,6 +3079,8 @@ server { allow 172.16.0.0/12; deny all; } + + } ", "samesite.conf": "# Implements SameSite cookie flags to ensure that our Login Server cookies are flagged as \`SameSite=None\` and \`Secure\`. @@ -3140,7 +3160,7 @@ proxy_cookie_path / "/$cookie_path_patches"; "region": "local", "service": "advanced-development-local", }, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", "namespace": "advanced-test", }, }, @@ -3571,7 +3591,7 @@ proxy_cookie_path / "/$cookie_path_patches"; { "configMap": { "defaultMode": 292, - "name": "nginx-config-82htd5f6t7", + "name": "nginx-config-g87b2gc9mg", }, "name": "nginx-config", }, diff --git a/lib/web-service/nginx-util.ts b/lib/web-service/nginx-util.ts index f43b93f..9833c45 100644 --- a/lib/web-service/nginx-util.ts +++ b/lib/web-service/nginx-util.ts @@ -29,6 +29,15 @@ interface NginxConfigMapProps { * @default false */ readonly includeSameSiteCookiesConfig?: boolean; + + /** + * Whether to include a config that patches Set-Cookies header to include `Partitioned` + * For further details on partitioned cookies visit: + * + * https://developer.mozilla.org/en-US/docs/Web/Privacy/Privacy_sandbox/Partitioned_cookies + * @default undefined + */ + readonly usePartionedCookiesLocations?: string[]; } /** @@ -39,7 +48,11 @@ function createConfigMap( props: NginxConfigMapProps, data: { [key: string]: string } = {}, ): ConfigMap { - if (props.includeDefaultConfig) { + const usePartitionedCookies = + props.usePartionedCookiesLocations && + props.usePartionedCookiesLocations.length > 0; + + if (props.includeDefaultConfig || usePartitionedCookies) { data["default.conf"] = getDefaultConfig(props); } @@ -60,7 +73,10 @@ function createConfigMap( * The output of this function is used with `createConfigMap` with `includeDefaultConfig` enabled. */ function getDefaultConfig( - props: Pick, + props: Pick< + NginxConfigMapProps, + "applicationPort" | "nginxPort" | "usePartionedCookiesLocations" + >, ): string { const { applicationPort, nginxPort } = props; @@ -72,10 +88,21 @@ function getDefaultConfig( throw new Error("Application and nginx ports must be different"); } + const defaultRouteLocation = createProxyRouteConfig( + "/", + "http://application", + ); + + const partitionedCookieLocations = getPartitionedCookiesConfig( + props.usePartionedCookiesLocations, + ); + return fs .readFileSync(resolvePath("nginx/default.conf"), "utf8") .replaceAll("{{applicationPort}}", applicationPort.toString()) - .replaceAll("{{nginxPort}}", nginxPort.toString()); + .replaceAll("{{nginxPort}}", nginxPort.toString()) + .replaceAll("{{defaultRouteLocation}}", defaultRouteLocation) + .replaceAll("{{partitionedCookieLocations}}", partitionedCookieLocations); } /** @@ -88,6 +115,41 @@ function getSameSiteCookiesConfig(): string { return fs.readFileSync(resolvePath("nginx/samesite.conf"), "utf8"); } +function getPartitionedCookiesConfig(locations?: string[]): string { + if (!locations) { + return ""; + } + + return locations + .map((location) => + createProxyRouteConfig(location, "http://application", [ + `proxy_cookie_path / "/; Partitioned";`, + ]), + ) + .join("\n\n"); +} + +function createProxyRouteConfig( + location: string, + proxyPath: string, + additionalSettings?: string[], +): string { + const additional = additionalSettings ? additionalSettings.join("\n") : ""; + + return `location ${location} { + proxy_pass ${proxyPath}; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + ${additional} + }`; +} + export const nginxUtil = { createConfigMap, getDefaultConfig, diff --git a/lib/web-service/nginx/default.conf b/lib/web-service/nginx/default.conf index a3a891e..56d37f0 100644 --- a/lib/web-service/nginx/default.conf +++ b/lib/web-service/nginx/default.conf @@ -16,16 +16,7 @@ server { gzip_comp_level 4; gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; - location / { - proxy_pass http://application; - proxy_http_version 1.1; - - proxy_set_header Connection $connection_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + {{defaultRouteLocation}} location /livez { access_log off; @@ -41,4 +32,6 @@ server { allow 172.16.0.0/12; deny all; } + + {{partitionedCookieLocations}} } diff --git a/test/web-service/__snapshots__/nginx-util.test.ts.snap b/test/web-service/__snapshots__/nginx-util.test.ts.snap index 738ade4..ba170e4 100644 --- a/test/web-service/__snapshots__/nginx-util.test.ts.snap +++ b/test/web-service/__snapshots__/nginx-util.test.ts.snap @@ -45,15 +45,17 @@ server { gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; location / { - proxy_pass http://application; - proxy_http_version 1.1; - - proxy_set_header Connection $connection_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + + } location /livez { access_log off; @@ -69,6 +71,8 @@ server { allow 172.16.0.0/12; deny all; } + + } ", }, @@ -77,7 +81,7 @@ server { "labels": { "prunable": "true", }, - "name": "test-nginx-config-c88fe926-tbmmh76262", + "name": "test-nginx-config-c88fe926-9d5ctddt9h", }, }, ] @@ -107,15 +111,17 @@ server { gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; location / { - proxy_pass http://application; - proxy_http_version 1.1; - - proxy_set_header Connection $connection_upgrade; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + + } location /livez { access_log off; @@ -131,6 +137,8 @@ server { allow 172.16.0.0/12; deny all; } + + } ", }, @@ -139,7 +147,7 @@ server { "labels": { "prunable": "true", }, - "name": "test-nginx-config-c88fe926-6992742cdt", + "name": "test-nginx-config-c88fe926-7b7f6cfmf4", }, }, ] @@ -164,6 +172,173 @@ exports[`nginx-util > createConfigMap > Empty 1`] = ` ] `; +exports[`nginx-util > createConfigMap > Partitioned cookies config 1`] = ` +[ + { + "apiVersion": "v1", + "data": { + "default.conf": "map $http_upgrade $connection_upgrade { + default "upgrade"; + "" ""; +} + +upstream application { + server localhost:8080; + keepalive 256; +} + +server { + listen 80; + server_name localhost; + + gzip on; + gzip_comp_level 4; + gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; + + location / { + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + + } + + location /livez { + access_log off; + add_header Content-Type text/plain; + return 200 'OK'; + } + + location /nginx_status { + stub_status on; + access_log off; + allow 127.0.0.1; + allow 10.0.0.0/8; + allow 172.16.0.0/12; + deny all; + } + + location /api/oidclogin { + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_cookie_path / "/; Partitioned"; + } +} +", + }, + "kind": "ConfigMap", + "metadata": { + "labels": { + "prunable": "true", + }, + "name": "test-nginx-config-c88fe926-99528m62bg", + }, + }, +] +`; + +exports[`nginx-util > createConfigMap > Partitioned cookies config with multiple locations 1`] = ` +[ + { + "apiVersion": "v1", + "data": { + "default.conf": "map $http_upgrade $connection_upgrade { + default "upgrade"; + "" ""; +} + +upstream application { + server localhost:8080; + keepalive 256; +} + +server { + listen 80; + server_name localhost; + + gzip on; + gzip_comp_level 4; + gzip_types text/html text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; + + location / { + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + + } + + location /livez { + access_log off; + add_header Content-Type text/plain; + return 200 'OK'; + } + + location /nginx_status { + stub_status on; + access_log off; + allow 127.0.0.1; + allow 10.0.0.0/8; + allow 172.16.0.0/12; + deny all; + } + + location /api/oidclogin { + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_cookie_path / "/; Partitioned"; + } + +location /api/auth/login { + proxy_pass http://application; + proxy_http_version 1.1; + + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_cookie_path / "/; Partitioned"; + } +} +", + }, + "kind": "ConfigMap", + "metadata": { + "labels": { + "prunable": "true", + }, + "name": "test-nginx-config-c88fe926-mdm92m6fhh", + }, + }, +] +`; + exports[`nginx-util > createConfigMap > Same site cookies config 1`] = ` [ { diff --git a/test/web-service/nginx-util.test.ts b/test/web-service/nginx-util.test.ts index 6ce65bf..b71a369 100644 --- a/test/web-service/nginx-util.test.ts +++ b/test/web-service/nginx-util.test.ts @@ -95,5 +95,27 @@ describe("nginx-util", () => { const results = Testing.synth(chart); expect(results).toMatchSnapshot(); }); + + test("Partitioned cookies config", () => { + const chart = Testing.chart(); + nginxUtil.createConfigMap(chart, { + applicationPort: 8080, + nginxPort: 80, + usePartionedCookiesLocations: ["/api/oidclogin"], + }); + const results = Testing.synth(chart); + expect(results).toMatchSnapshot(); + }); + + test("Partitioned cookies config with multiple locations", () => { + const chart = Testing.chart(); + nginxUtil.createConfigMap(chart, { + applicationPort: 8080, + nginxPort: 80, + usePartionedCookiesLocations: ["/api/oidclogin", "/api/auth/login"], + }); + const results = Testing.synth(chart); + expect(results).toMatchSnapshot(); + }); }); });