Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/api-v2.authz.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,24 @@ describe('API V2 authz tests', () => {
ingress: { mode: 'AllowAll' },
},
})
const createIngressAllowOnlyNetpol = (fromLabelValue: string, toLabelValue = 'frontend') =>
createTeamResource('AplTeamNetworkControl', {
ruleType: {
type: 'ingress',
ingress: {
mode: 'AllowOnly',
toLabelName: 'app',
toLabelValue,
allow: [
{
fromNamespace: 'team1',
fromLabelName: 'app',
fromLabelValue,
},
],
},
},
})

describe('Platform Admin', () => {
test('platform admin can get all network policies', async () => {
Expand All @@ -1401,6 +1419,48 @@ describe('API V2 authz tests', () => {
.expect(200)
})

test('rejects multiline network policy label values', async () => {
const netpol = createIngressAllowOnlyNetpol('foo\nbar')

const response = await agent
.post('/v2/teams/team1/netpols')
.send(netpol)
.set('Authorization', `Bearer ${teamMemberToken}`)

expect(response.status).toBe(400)
})

it.each(['foo\nbar', 'foo\r\nbar', '{{ malicious }}', 'foo: bar', 'foo bar', '---'])(
'rejects invalid label value %p',
Comment thread
dennisvankekem marked this conversation as resolved.
async (fromLabelValue) => {
const response = await agent
.post('/v2/teams/team1/netpols')
.send(createIngressAllowOnlyNetpol(fromLabelValue))
.set('Authorization', `Bearer ${teamMemberToken}`)

expect(response.status).toBe(400)
},
)

it.each(['app', 'my-app', 'my_app', 'my.app', 'APP123', ''])(
'accepts Kubernetes label value %p',
async (fromLabelValue) => {
await agent
.post('/v2/teams/team1/netpols')
.send(createIngressAllowOnlyNetpol(fromLabelValue))
.set('Authorization', `Bearer ${teamMemberToken}`)
.expect(200)
},
)

test('rejects invalid to-label value on ingress selector', async () => {
await agent
.post('/v2/teams/team1/netpols')
.send(createIngressAllowOnlyNetpol('frontend', 'foo\nbar'))
.set('Authorization', `Bearer ${teamMemberToken}`)
.expect(400)
})

test('team member can get team network policies', async () => {
await agent.get('/v2/teams/team1/netpols').set('Authorization', `Bearer ${teamMemberToken}`).expect(200)
})
Expand Down
8 changes: 8 additions & 0 deletions src/openapi/definitions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,14 @@ kms:
labels:
$ref: '#/annotations'
description: A set of labels.
kubernetesLabelName:
type: string
maxLength: 63
pattern: '^(?![\s\S]*[\r\n])[A-Za-z0-9](?:[-._A-Za-z0-9]{0,61}[A-Za-z0-9])?$'
kubernetesLabelValue:
type: string
maxLength: 63
pattern: '^(?:$|(?![\s\S]*[\r\n])[A-Za-z0-9](?:[-._A-Za-z0-9]{0,61}[A-Za-z0-9])?)$'
Comment thread
dennisvankekem marked this conversation as resolved.
logLevel:
title: Log Level
type: string
Expand Down
8 changes: 4 additions & 4 deletions src/openapi/netpol.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ ruleType:
type: object
properties:
toLabelName:
type: string
$ref: 'definitions.yaml#/kubernetesLabelName'
title: Selector label name
description: 'The name of the Pod selector label.'
example: app
toLabelValue:
type: string
$ref: 'definitions.yaml#/kubernetesLabelValue'
title: Selector label value
description: 'The value of the Pod selector label.'
example: my-app
Expand All @@ -79,12 +79,12 @@ ruleType:
title: Namespace name
description: 'The name of the namespace.'
fromLabelName:
type: string
$ref: 'definitions.yaml#/kubernetesLabelName'
title: Selector label name
description: 'The name of the Pod selector label.'
example: app
fromLabelValue:
type: string
$ref: 'definitions.yaml#/kubernetesLabelValue'
title: Selector label value
description: 'The value of the Pod selector label.'
example: my-app
Expand Down
59 changes: 59 additions & 0 deletions src/patterns.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ const redosCases: Record<string, string[]> = {

k8sName: [`${'a-'.repeat(50_000)}!`],

kubernetesLabelValue: [`${'a-'.repeat(50_000)}!`, `${'a.'.repeat(50_000)}!`],

kubernetesLabelName: [`${'a-'.repeat(50_000)}!`, `${'a.'.repeat(50_000)}!`],

idName: [`${'a-'.repeat(50_000)}!`],

settingsName: [`${'aB'.repeat(50_000)}!`, `${'a-'.repeat(50_000)}!`],
Expand Down Expand Up @@ -147,6 +151,8 @@ describe('OpenAPI definition regex patterns', () => {
'email',
'hostPort',
'k8sName',
'kubernetesLabelValue',
'kubernetesLabelName',
'idName',
'quantityCpu',
'quantityMem',
Expand Down Expand Up @@ -242,6 +248,59 @@ describe('OpenAPI definition regex patterns', () => {
})
})

describe('kubernetesLabelValue', () => {
it('accepts valid Kubernetes label values', () => {
expectValid('kubernetesLabelValue', ['', 'app', 'my-app', 'my_app', 'my.app', 'APP123', 'a'.repeat(63)])
})

it('rejects invalid Kubernetes label values', () => {
expectInvalid('kubernetesLabelValue', [
'-app',
'app-',
'.app',
'app.',
'_app',
'app_',
'app value',
'foo\nbar',
'foo\r\nbar',
'app\n',
'app\r\n',
'{{ malicious }}',
'foo: bar',
'---',
'a'.repeat(64),
])
Comment thread
Copilot marked this conversation as resolved.
})
})

describe('kubernetesLabelName', () => {
it('accepts valid Kubernetes label names', () => {
expectValid('kubernetesLabelName', ['app', 'my-app', 'my_app', 'my.app', 'APP123', 'a'.repeat(63)])
})

it('rejects invalid Kubernetes label names', () => {
expectInvalid('kubernetesLabelName', [
'',
'-app',
'app-',
'.app',
'app.',
'_app',
'app_',
'app name',
'foo\nbar',
'foo\r\nbar',
'app\n',
'app\r\n',
'{{ malicious }}',
'foo: bar',
'---',
'a'.repeat(64),
])
Comment thread
Copilot marked this conversation as resolved.
})
})

describe('idName', () => {
it('accepts valid ID names', () => {
expectValid('idName', ['a', 'secret', 'secret-name', 'secret1'])
Expand Down
Loading