Add schema validation to all external trigger types

This commit is contained in:
Joseph Schorr 2015-09-21 17:46:50 -04:00
parent bf578420f0
commit 272326ae18
3 changed files with 297 additions and 6 deletions

View file

@ -1,8 +1,10 @@
import logging import logging
import re import re
from jsonschema import validate
from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException, from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException,
TriggerDeactivationException, TriggerStartException, TriggerDeactivationException, TriggerStartException,
InvalidPayloadException,
determine_build_ref, raise_if_skipped_build, determine_build_ref, raise_if_skipped_build,
find_matching_branches) find_matching_branches)
@ -18,11 +20,172 @@ logger = logging.getLogger(__name__)
_BITBUCKET_COMMIT_URL = 'https://bitbucket.org/%s/commits/%s' _BITBUCKET_COMMIT_URL = 'https://bitbucket.org/%s/commits/%s'
_RAW_AUTHOR_REGEX = re.compile(r'.*<(.+)>') _RAW_AUTHOR_REGEX = re.compile(r'.*<(.+)>')
BITBUCKET_WEBHOOK_PAYLOAD_SCHEMA = {
'type': 'object',
'properties': {
'repository': {
'type': 'object',
'properties': {
'full_name': {
'type': 'string',
},
},
'required': ['full_name'],
},
'push': {
'type': 'object',
'properties': {
'changes': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'new': {
'type': 'object',
'properties': {
'target': {
'type': 'object',
'properties': {
'hash': {
'type': 'string'
},
'message': {
'type': 'string'
},
'date': {
'type': 'string'
},
'author': {
'type': 'object',
'properties': {
'user': {
'type': 'object',
'properties': {
'username': {
'type': 'string',
},
'links': {
'type': 'object',
'properties': {
'html': {
'type': 'object',
'properties': {
'href': {
'type': 'string',
},
},
'required': ['href'],
},
'avatar': {
'type': 'object',
'properties': {
'href': {
'type': 'string',
},
},
'required': ['href'],
},
},
'required': ['html', 'avatar'],
},
},
'required': ['username'],
},
},
'required': ['user'],
},
'links': {
'type': 'object',
'properties': {
'html': {
'type': 'object',
'properties': {
'href': {
'type': 'string',
},
},
'required': ['href'],
},
},
'required': ['html'],
},
},
'required': ['hash', 'message', 'date'],
},
},
'required': ['target'],
},
},
},
},
},
'required': ['changes'],
},
},
'actor': {
'type': 'object',
'properties': {
'username': {
'type': 'string',
},
'links': {
'type': 'object',
'properties': {
'html': {
'type': 'object',
'properties': {
'href': {
'type': 'string',
},
},
'required': ['href'],
},
'avatar': {
'type': 'object',
'properties': {
'href': {
'type': 'string',
},
},
'required': ['href'],
},
},
'required': ['html', 'avatar'],
},
},
'required': ['username'],
},
'required': ['push', 'repository'],
}
BITBUCKET_COMMIT_INFO_SCHEMA = {
'type': 'object',
'properties': {
'node': {
'type': 'string',
},
'message': {
'type': 'string',
},
'timestamp': {
'type': 'string',
},
'raw_author': {
'type': 'string',
},
},
'required': ['node', 'message', 'timestamp']
}
def get_transformed_commit_info(bb_commit, ref, default_branch, repository_name, lookup_author): def get_transformed_commit_info(bb_commit, ref, default_branch, repository_name, lookup_author):
""" Returns the BitBucket commit information transformed into our own """ Returns the BitBucket commit information transformed into our own
payload format. payload format.
""" """
# TODO(jschorr): Validate commit JSON try:
validate(bb_commit, BITBUCKET_COMMIT_INFO_SCHEMA)
except Exception as exc:
raise InvalidPayloadException(exc.message)
commit = JSONPathDict(bb_commit) commit = JSONPathDict(bb_commit)
config = SafeDictSetter() config = SafeDictSetter()
@ -51,7 +214,10 @@ def get_transformed_webhook_payload(bb_payload, default_branch=None):
""" Returns the BitBucket webhook JSON payload transformed into our own payload """ Returns the BitBucket webhook JSON payload transformed into our own payload
format. If the bb_payload is not valid, returns None. format. If the bb_payload is not valid, returns None.
""" """
# TODO(jschorr): Validate payload JSON try:
validate(bb_payload, BITBUCKET_WEBHOOK_PAYLOAD_SCHEMA)
except Exception as exc:
raise InvalidPayloadException(exc.message)
payload = JSONPathDict(bb_payload) payload = JSONPathDict(bb_payload)
change = payload['push.changes[-1].new'] change = payload['push.changes[-1].new']

View file

@ -3,11 +3,12 @@ import os.path
import base64 import base64
from app import app, github_trigger from app import app, github_trigger
from jsonschema import validate
from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException, from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException,
TriggerDeactivationException, TriggerStartException, TriggerDeactivationException, TriggerStartException,
EmptyRepositoryException, ValidationRequestException, EmptyRepositoryException, ValidationRequestException,
SkipRequestException, SkipRequestException, InvalidPayloadException,
determine_build_ref, raise_if_skipped_build, determine_build_ref, raise_if_skipped_build,
find_matching_branches) find_matching_branches)
@ -21,12 +22,82 @@ from github import (Github, UnknownObjectException, GithubException,
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
GITHUB_WEBHOOK_PAYLOAD_SCHEMA = {
'type': 'object',
'properties': {
'ref': {
'type': 'string',
},
'head_commit': {
'type': 'object',
'properties': {
'id': {
'type': 'string',
},
'url': {
'type': 'string',
},
'message': {
'type': 'string',
},
'timestamp': {
'type': 'string',
},
'author': {
'type': 'object',
'properties': {
'username': {
'type': 'string'
},
'html_url': {
'type': 'string'
},
'avatar_url': {
'type': 'string'
},
},
'required': ['username'],
},
'committer': {
'type': 'object',
'properties': {
'username': {
'type': 'string'
},
'html_url': {
'type': 'string'
},
'avatar_url': {
'type': 'string'
},
},
'required': ['username'],
},
},
'required': ['id', 'url', 'message', 'timestamp'],
},
'repository': {
'type': 'object',
'properties': {
'ssh_url': {
'type': 'string',
},
},
'required': ['ssh_url'],
},
},
'required': ['ref', 'head_commit', 'repository'],
}
def get_transformed_webhook_payload(gh_payload, default_branch=None, lookup_user=None): def get_transformed_webhook_payload(gh_payload, default_branch=None, lookup_user=None):
""" Returns the GitHub webhook JSON payload transformed into our own payload """ Returns the GitHub webhook JSON payload transformed into our own payload
format. If the gh_payload is not valid, returns None. format. If the gh_payload is not valid, returns None.
""" """
# TODO(jschorr): Validate payload JSON try:
validate(gh_payload, GITHUB_WEBHOOK_PAYLOAD_SCHEMA)
except Exception as exc:
raise InvalidPayloadException(exc.message)
payload = JSONPathDict(gh_payload) payload = JSONPathDict(gh_payload)
config = SafeDictSetter() config = SafeDictSetter()

View file

@ -2,10 +2,11 @@ import logging
from app import app from app import app
from jsonschema import validate
from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException, from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException,
TriggerDeactivationException, TriggerStartException, TriggerDeactivationException, TriggerStartException,
EmptyRepositoryException, ValidationRequestException, EmptyRepositoryException, ValidationRequestException,
SkipRequestException, SkipRequestException, InvalidPayloadException,
determine_build_ref, raise_if_skipped_build, determine_build_ref, raise_if_skipped_build,
find_matching_branches) find_matching_branches)
@ -18,12 +19,65 @@ import gitlab
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
GITLAB_WEBHOOK_PAYLOAD_SCHEMA = {
'type': 'object',
'properties': {
'ref': {
'type': 'string',
},
'checkout_sha': {
'type': 'string',
},
'repository': {
'type': 'object',
'properties': {
'git_ssh_url': {
'type': 'string',
},
},
'required': ['git_ssh_url'],
},
'commits': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'url': {
'type': 'string',
},
'message': {
'type': 'string',
},
'timestamp': {
'type': 'string',
},
'author': {
'type': 'object',
'properties': {
'email': {
'type': 'string',
},
},
'required': ['email'],
},
},
'required': ['url', 'message', 'timestamp'],
},
'minItems': 1,
}
},
'required': ['ref', 'checkout_sha', 'repository'],
}
def get_transformed_webhook_payload(gl_payload, default_branch=None, lookup_user=None): def get_transformed_webhook_payload(gl_payload, default_branch=None, lookup_user=None):
""" Returns the Gitlab webhook JSON payload transformed into our own payload """ Returns the Gitlab webhook JSON payload transformed into our own payload
format. If the gl_payload is not valid, returns None. format. If the gl_payload is not valid, returns None.
""" """
# TODO(jschorr): Validate payload JSON try:
validate(gl_payload, GITLAB_WEBHOOK_PAYLOAD_SCHEMA)
except Exception as exc:
raise InvalidPayloadException(exc.message)
payload = JSONPathDict(gl_payload) payload = JSONPathDict(gl_payload)
config = SafeDictSetter() config = SafeDictSetter()