def validate_testing_farm_request(): """ Validate testing farm token received in request with the one in packit-service.yaml Currently we use the same secret to authenticate both, packit service (when sending request to testing farm) and testing farm (when sending notification to packit service's webhook). We might later use a different secret for those use cases. :raises ValidationFailed """ if not config.testing_farm_secret: msg = "Testing farm secret not specified in config" logger.error(msg) raise ValidationFailed(msg) token = request.json.get("token") if not token: msg = "The notification doesn't contain any token" logger.info(msg) raise ValidationFailed(msg) if token == config.testing_farm_secret or ( config.internal_testing_farm_secret and token == config.internal_testing_farm_secret): return msg = "Invalid testing farm secret provided" logger.warning(msg) raise ValidationFailed(msg)
def validate_token(self): """ https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#secret-token """ if "X-Gitlab-Token" not in request.headers: if config.validate_webhooks: msg = "X-Gitlab-Token not in request.headers" logger.info(msg) self.create_confidential_issue_with_token() return else: # don't validate signatures when testing locally logger.debug("Ain't validating token.") return token = request.headers["X-Gitlab-Token"] if token in config.gitlab_webhook_tokens: logger.debug("Deprecation Warning: Old Gitlab tokens used.") return gitlab_token_secret = config.gitlab_token_secret if not gitlab_token_secret: msg = "'gitlab_token_secret' not specified in the config." logger.error(msg) raise ValidationFailed(msg) try: token_decoded = jwt.decode(token, config.gitlab_token_secret, algorithms=["HS256"]) except jwt.exceptions.InvalidSignatureError: msg_failed_signature = "Payload token does not match the project." logger.warning(msg_failed_signature) raise ValidationFailed(msg_failed_signature) except jwt.exceptions.DecodeError: msg_failed_error = "Payload token has invalid signature." logger.warning(msg_failed_error) raise ValidationFailed(msg_failed_error) project_data = json.loads(request.data)["project"] parsed_url = parse_git_repo(potential_url=project_data["http_url"]) token_namespace = token_decoded["namespace"] token_repo_name = token_decoded["repo_name"] if (token_namespace, token_repo_name) == ( parsed_url.namespace, parsed_url.repo, ): logger.debug("Payload signature is OK.") else: msg_failed_validation = "Signature of the payload token is not valid." logger.warning(msg_failed_validation) raise ValidationFailed(msg_failed_validation)
def validate_token(self): """ https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#secret-token """ if "X-Gitlab-Token" not in request.headers: if config.validate_webhooks: msg = "X-Gitlab-Token not in request.headers" logger.info(msg) self.create_confidential_issue_with_token() raise ValidationFailed(msg) else: # don't validate signatures when testing locally logger.debug("Ain't validating token.") return token = request.headers["X-Gitlab-Token"] gitlab_token_secret = config.gitlab_token_secret if not gitlab_token_secret: msg = "'gitlab_token_secret' not specified in the config." logger.error(msg) raise ValidationFailed(msg) try: token_decoded = jwt.decode(token, config.gitlab_token_secret, algorithms=["HS256"]) except ( jwt.exceptions.InvalidSignatureError, jwt.exceptions.DecodeError, ) as exc: msg_failed_error = "Can't decode X-Gitlab-Token." logger.warning(f"{msg_failed_error} {exc}") raise ValidationFailed(msg_failed_error) from exc project_data = json.loads(request.data)["project"] git_http_url = project_data.get( "git_http_url") or project_data["http_url"] parsed_url = parse_git_repo(potential_url=git_http_url) # "repo_name" might be missing in token_decoded if the token is for group/namespace if token_decoded["namespace"] != parsed_url.namespace or ( "repo_name" in token_decoded and token_decoded["repo_name"] != parsed_url.repo): msg_failed_validation = ( "Decoded X-Gitlab-Token does not match namespace[/project].") logger.warning(msg_failed_validation) logger.debug(f"decoded: {token_decoded}, url: {parsed_url}") raise ValidationFailed(msg_failed_validation) logger.debug("Payload signature is OK.")
def validate_testing_farm_request(): """ Validate testing farm token received in request with the one in packit-service.yaml :raises ValidationFailed """ if not config.testing_farm_secret: msg = "Testing farm secret not specified in config" logger.error(msg) raise ValidationFailed(msg) token = request.json.get("token") if not token: msg = "The request doesn't contain any token" logger.info(msg) raise ValidationFailed(msg) if token == config.testing_farm_secret: return msg = "Invalid testing farm secret provided" logger.warning(msg) raise ValidationFailed(msg)
def validate_token(): """ https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#secret-token """ if "X-Gitlab-Token" not in request.headers: if config.validate_webhooks: msg = "X-Gitlab-Token not in request.headers" logger.warning(msg) raise ValidationFailed(msg) else: # don't validate signatures when testing locally logger.debug("Ain't validating token.") return token = request.headers["X-Gitlab-Token"] # Find a better solution if token != config.gitlab_webhook_token: raise ValidationFailed("Payload token validation failed.") logger.debug("Payload token is OK.")
def validate_signature(): """ https://developer.github.com/webhooks/securing/#validating-payloads-from-github https://developer.github.com/webhooks/#delivery-headers """ if "X-Hub-Signature" not in request.headers: if config.validate_webhooks: msg = "X-Hub-Signature not in request.headers" logger.warning(msg) raise ValidationFailed(msg) else: # don't validate signatures when testing locally logger.debug("Ain't validating signatures.") return sig = request.headers["X-Hub-Signature"] if not sig.startswith("sha1="): msg = f"Digest mode in X-Hub-Signature {sig!r} is not sha1." logger.warning(msg) raise ValidationFailed(msg) webhook_secret = config.webhook_secret.encode() if not webhook_secret: msg = "'webhook_secret' not specified in the config." logger.error(msg) raise ValidationFailed(msg) signature = sig.split("=")[1] mac = hmac.new(webhook_secret, msg=request.get_data(), digestmod=sha1) digest_is_valid = hmac.compare_digest(signature, mac.hexdigest()) if digest_is_valid: logger.debug("Payload signature OK.") else: msg = "Payload signature validation failed." logger.warning(msg) logger.debug( f"X-Hub-Signature: {sig!r} != computed: {mac.hexdigest()}") raise ValidationFailed(msg)