Skip to content

Commit

Permalink
Merge pull request #6 from amazeeio/AIOSEC-85-insecure-gitlab-project…
Browse files Browse the repository at this point in the history
…-delete

Aiosec 85 insecure gitlab project delete
  • Loading branch information
Schnitzel committed Dec 11, 2020
2 parents d4422e6 + 61e28e2 commit 1140289
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 8 deletions.
19 changes: 18 additions & 1 deletion node-packages/commons/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,23 @@ export async function getProjectByName(project: string): Promise<any> {
return result.project;
}

export const allProjectsInGroup = (groupInput: {
id?: string;
name?: string;
}): Promise<any[]> =>
graphqlapi.query(
`
query($groupInput: GroupInput!) {
allProjectsInGroup(input: $groupInput) {
...${projectFragment}
}
}
`,
{
groupInput
}
);

export async function getMicrosoftTeamsInfoForProject(
project: string, contentType = 'DEPLOYMENT'
): Promise<any[]> {
Expand Down Expand Up @@ -1456,4 +1473,4 @@ export const getProblemHarborScanMatches = () => graphqlapi.query(
regex
}
}`
);
);
20 changes: 20 additions & 0 deletions node-packages/commons/src/gitlabApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,26 @@ const options = {

const gitlabapi = axios.create(options);

export const secureGitlabSystemHooks = [
'group_create',
'group_rename',
'group_destroy',
'project_create',
'project_transfer',
'project_rename',
'project_update',
'project_destroy',
'user_create',
'user_rename',
'user_destroy',
'user_add_to_group',
'user_remove_from_group',
'user_add_to_team',
'user_remove_from_team',
'key_create',
'key_destroy',
];

class NetworkError extends Error {
constructor(message: string) {
super(message);
Expand Down
3 changes: 2 additions & 1 deletion services/webhook-handler/src/extractWebhookData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import uuid4 from 'uuid4';
import url from 'url';
import R from 'ramda';
import { IncomingMessage } from 'http';
import { secureGitlabSystemHooks } from '@lagoon/commons/dist/gitlabApi';

import type { RawData, WebhookRequestData } from './types';

Expand Down Expand Up @@ -45,7 +46,7 @@ export function extractWebhookData(req: IncomingMessage, body: string): WebhookR
giturl = R.path(['project', 'git_ssh_url'], bodyObj);

// This is a system webhook
if (!giturl) {
if (R.contains(event, secureGitlabSystemHooks)) {
// Ensure the system hook came from gitlab
if (!('x-gitlab-token' in req.headers) || req.headers['x-gitlab-token'] !== process.env.GITLAB_SYSTEM_HOOK_TOKEN) {
throw new Error('Gitlab system hook secret verification failed');
Expand Down
33 changes: 28 additions & 5 deletions services/webhooks2tasks/src/handlers/gitlabProjectDelete.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import R from 'ramda';
import { sendToLagoonLogs } from '@lagoon/commons/dist/logs';
import { deleteProject } from '@lagoon/commons/dist/api';
import { allProjectsInGroup, deleteProject, sanitizeGroupName } from '@lagoon/commons/dist/api';

import { WebhookRequestData } from '../types';

Expand All @@ -9,23 +10,45 @@ export async function gitlabProjectDelete(webhook: WebhookRequestData) {
event,
uuid,
body,
body: { path: name }
body: { path: projectName, path_with_namespace }
} = webhook;

try {
const meta = {
project: name
project: projectName
};

await deleteProject(name);
const groupName = sanitizeGroupName(path_with_namespace.replace(`/${projectName}`, ''));
const projectsInGroup = await allProjectsInGroup({ name: groupName });
const projectExists = R.pipe(
R.prop('allProjectsInGroup'),
R.pluck('name'),
R.contains(projectName),
// @ts-ignore
)(projectsInGroup);

if (projectExists) {
await deleteProject(projectName);

sendToLagoonLogs(
'info',
'',
uuid,
`${webhooktype}:${event}:handled`,
meta,
`deleted project ${projectName}`
);

return;
}

sendToLagoonLogs(
'info',
'',
uuid,
`${webhooktype}:${event}:handled`,
meta,
`deleted project ${name}`
`project "${projectName}" not a member of group "${groupName}"`
);

return;
Expand Down
5 changes: 4 additions & 1 deletion services/webhooks2tasks/src/processQueue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import R from 'ramda';
import { ChannelWrapper } from 'amqp-connection-manager';
import { ConsumeMessage } from 'amqplib';
import { secureGitlabSystemHooks } from '@lagoon/commons/dist/gitlabApi';
import { processProjects } from './webhooks/projects';
import { processDataSync } from './webhooks/dataSync';
import { processBackup } from './webhooks/backup';
Expand All @@ -11,13 +13,14 @@ export async function processQueue (rabbitMsg: ConsumeMessage, channelWrapperWeb

const {
webhooktype,
event,
giturl,
} = webhook;

// GitLab supports System Hooks which trigger on changes like creating new
// organizations or users. Since these don't have associated projects, they
// must be handled separately.
if (webhooktype == 'gitlab' && !giturl) {
if (webhooktype == 'gitlab' && R.contains(event, secureGitlabSystemHooks)) {
processDataSync(rabbitMsg, channelWrapperWebhooks);
} else if (webhooktype == 'resticbackup') {
processBackup(rabbitMsg, channelWrapperWebhooks);
Expand Down

0 comments on commit 1140289

Please sign in to comment.