Skip to content
This repository was archived by the owner on Jun 17, 2024. It is now read-only.

Commit d0912a4

Browse files
authored
Merge pull request #76 from Azure/dev
Fixing issue with invalid header names
2 parents cb41e92 + af4b391 commit d0912a4

File tree

7 files changed

+86
-11
lines changed

7 files changed

+86
-11
lines changed

AutomationScripts/5-deployEasyAuthProxy.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ do
2121
echo ""
2222
kubectl get svc,deploy,pod
2323
echo ""
24-
INPUT_STRING=$(kubectl get svc,deploy,pod -o=jsonpath='{.items[3].status.containerStatuses[0].ready}')
24+
INPUT_STRING=$(kubectl get svc,deploy,pod -o=jsonpath='{.items[2].status.containerStatuses[0].ready}')
2525
sleep 10
2626
if [ "$n" == "0" ]; then
2727
echo "ERROR. INFINITE LOOP in 4-EasyAuthProxy.sh."

charts/easyauth-proxy/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ type: application
1515
# This is the chart version. This version number should be incremented each time you make changes
1616
# to the chart and its templates, including the app version.
1717
# Versions are expected to follow Semantic Versioning (https://semver.org/)
18-
version: 0.1.0
18+
version: 1.0.2
1919

2020
# This is the version number of the application being deployed. This version number should be
2121
# incremented each time you make changes to the application. Versions are not expected to
2222
# follow Semantic Versioning. They should reflect the version the application is using.
23-
appVersion: 1.16.0
23+
appVersion: 1.0.2

charts/easyauth-proxy/templates/deployment.yaml renamed to charts/easyauth-proxy/templates/statefulset.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
apiVersion: apps/v1
2-
kind: Deployment
2+
kind: StatefulSet
33
metadata:
44
name: {{ include "easyauth-proxy.fullname" . }}
55
labels:
@@ -8,6 +8,7 @@ spec:
88
{{- if not .Values.autoscaling.enabled }}
99
replicas: {{ .Values.replicaCount }}
1010
{{- end }}
11+
serviceName: {{ include "easyauth-proxy.fullname" . }}
1112
selector:
1213
matchLabels:
1314
{{- include "easyauth-proxy.selectorLabels" . | nindent 6 }}

charts/easyauth-proxy/values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ image:
1212
repository: ghcr.io/azure/easyauthfork8s/easy-auth-proxy
1313
pullPolicy: Always
1414
# Overrides the image tag whose default is the chart appVersion.
15-
tag: master
15+
tag: v1.0.2
1616

1717
imagePullSecrets: []
1818
nameOverride: ""

src/EasyAuthForK8s.Web/Models/ModelExtensions.cs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ namespace EasyAuthForK8s.Web.Models;
1616

1717
internal static class ModelExtensions
1818
{
19+
//from rfc7230 US-ASCII visual characters not allowed in a token (DQUOTE and "(),/:;<=>?@[\]{}")
20+
private static int[] invalid_token_chars = new int[] { 34,40,41,44,47,58,59,60,61,62,63,64,91,92,93,123,125 };
21+
const string EMPTY_HEADER_NAME = "illegal-name";
22+
1923
public static EasyAuthState EasyAuthStateFromHttpContext(this HttpContext context)
2024
{
25+
2126
//see if state exists in property bag, and return it
2227
if (context.Items.ContainsKey(Constants.StateCookieName))
2328
{
@@ -176,7 +181,7 @@ internal static void AppendResponseHeaders(this UserInfoPayload payload, IHeader
176181

177182
void addHeader(string name, string value)
178183
{
179-
string headerName = SanitizeHeaderName($"{configOptions.ResponseHeaderPrefix}{name}");
184+
string headerName = SanitizeHeaderName($"{configOptions.ResponseHeaderPrefix}{ClaimNameFromUri(name)}");
180185
string encodedValue = EncodeValue(value, configOptions.ClaimEncodingMethod);
181186

182187
//nginx will only forward the first header of a given name,
@@ -240,16 +245,42 @@ private static string EncodeValue(string value, EasyAuthConfigurationOptions.Enc
240245
_ => value,
241246
};
242247
}
243-
private static string SanitizeHeaderName(string name)
248+
//strips out any illegal characters
249+
internal static string SanitizeHeaderName(string name)
244250
{
245251
if (string.IsNullOrEmpty(name))
246252
{
247253
throw new ArgumentNullException("name");
248254
}
249255

250-
string clean = new string(name.Where(c => c >= 32 && c < 127).ToArray());
256+
string clean = new string(name.Where(c => c >= 32 && c < 127 && !invalid_token_chars.Contains(c)).ToArray());
251257

252-
return clean.Replace('_', '-').ToLower();
258+
//edge case: the original name contains ZERO valid characters
259+
//just return a default. there's no reason to throw when the app may ignore this header anyway
260+
if (clean.Length == 0)
261+
return EMPTY_HEADER_NAME;
262+
else
263+
return clean.Replace('_', '-').ToLower();
264+
}
265+
//while this is not entirely necessary, and might lead to name-uniqueness conflicts
266+
//it seems like a reasonable compromize to create a more "friendly" header name
267+
internal static string ClaimNameFromUri(string name)
268+
{
269+
if (string.IsNullOrEmpty(name))
270+
{
271+
throw new ArgumentNullException("name");
272+
}
273+
if (name.Contains("/"))
274+
{
275+
var split = name.Split('/', StringSplitOptions.RemoveEmptyEntries);
276+
if (split.Length > 1)
277+
return split[split.Length - 1];
278+
else
279+
//edge case: the original name contains nothing but forward slashes
280+
return EMPTY_HEADER_NAME;
281+
}
282+
else
283+
return name;
253284
}
254285
}
255286

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using EasyAuthForK8s.Web.Helpers;
2+
using EasyAuthForK8s.Web.Models;
3+
using Microsoft.AspNetCore.Builder;
4+
using Microsoft.AspNetCore.Hosting;
5+
using Microsoft.AspNetCore.TestHost;
6+
using Microsoft.Extensions.Hosting;
7+
using System;
8+
using System.Text.RegularExpressions;
9+
using System.Threading.Tasks;
10+
using Xunit;
11+
12+
namespace EasyAuthForK8s.Tests.Web
13+
{
14+
15+
public class ModelTests
16+
{
17+
[Theory]
18+
[InlineData("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "httpschemas.xmlsoap.orgws200505identityclaimsnameidentifier")]
19+
[InlineData("(),/:;<=>?@[\\]{}\"foo", "foo")]
20+
//input contains no legal characters, default is returned
21+
[InlineData("(),/:;<=>?@[\\]{}\"", "illegal-name")]
22+
//input is legal, converted to lowercase
23+
[InlineData("FOO", "foo")]
24+
//complete list of valid characters should all remain, all lower case and underscore converted to "-"
25+
[InlineData(" !#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~", " !#$%&'*+-.0123456789abcdefghijklmnopqrstuvwxyz^-`abcdefghijklmnopqrstuvwxyz|~")]
26+
public void Sanitize_Header_Names(string input, string expected)
27+
{
28+
var sanitized = ModelExtensions.SanitizeHeaderName(input);
29+
Assert.Equal(expected, sanitized);
30+
}
31+
32+
[Theory]
33+
[InlineData("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", "nameidentifier")]
34+
[InlineData("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier/", "nameidentifier")]
35+
[InlineData("///////", "illegal-name")]
36+
public void Uri_Claim_Names(string input, string expected)
37+
{
38+
var nameFromUri = ModelExtensions.ClaimNameFromUri(input);
39+
Assert.Equal(expected, nameFromUri);
40+
}
41+
42+
}
43+
}

test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ bash ./main.sh -a $A -c $C -r $R -e $E -l $L -t $T -s $S -z $Z -g
5454

5555
APP_NAME="$A.$L.cloudapp.azure.com"
5656
WEBPAGE=https://$APP_NAME
57-
echo "Grabbed homepage: " $WEBPAGE ". Sleeping for 10 seconds..."
58-
sleep 10
57+
echo "Grabbed homepage: " $WEBPAGE ". SLEEPING for 60 seconds..."
58+
sleep 60
5959
RESPONSE_CODE=$(curl -s -o /dev/null -w "%{http_code}" $WEBPAGE)
6060
echo "response code: " $RESPONSE_CODE
6161

0 commit comments

Comments
 (0)