Project: Checkov (Provisioning / Security & Compliance)
File: Contribute New Bitbucket Policies.md

layout: default published: true title: Contribute New Bitbucket configuration policy nav_order: 5 In this example, we'll add support for a new Bitbucket configuration check. We are going to add a new check that will examine how branch protection rules are configured and validate we enforce protection rules on admin users too. First, we will validate if the Bitbucket API call that GETs the branch protection current state exists in `checkov/bitbucket/dal.py`. If not it can be added to that file like the following example: ```python class Bitbucket(BaseVCSDAL) ... ... def getbranchrestrictions(self): if self.current_repository: branchrestrictions = self.request( endpoint=f"repositories/{self.current_repository}/branch-restrictions") return branch_restrictions return None def persistbranchrestrictions(self): branchrestrictions = self.getbranch_restrictions() if branch_restrictions: BaseVCSDAL.persist(path=self.bitbucketbranchrestrictionsfilepath, conf=branch_restrictions) def persistallconfs(self): if strtobool(os.getenv("CKVBITBUCKETCONFIGFETCHDATA", "True")): self.persistbranchrestrictions() ``` Go to `checkov/bitbucket/checks` and add `enforcebranchprotectiononadmins.py`: ```python from checkov.bitbucket.basebitbucketconfiguration_check import BaseBitbucketCheck from checkov.bitbucket.schemas.branchrestrictions import schema as branchrestrictions_schema from checkov.common.models.enums import CheckCategories, CheckResult from checkov.json_doc.enums import BlockType class MergeRequestRequiresApproval(BaseBitbucketCheck): def init(self): name = "Merge requests should require at least 2 approvals" id = "CKVBITBUCKET1" categories = [CheckCategories.SUPPLY_CHAIN] super().init( name=name, id=id, categories=categories, supported_entities=["*"], block_type=BlockType.DOCUMENT ) def scanentityconf(self, conf): if branchrestrictionsschema.validate(conf): for value in conf.get("values", []): if value.get('kind', '') == 'requireapprovalsto_merge': if value.get('value', 0) >= 2: return CheckResult.PASSED, conf return CheckResult.FAILED, conf check = MergeRequestRequiresApproval() ``` And also add the JSON schema to validate the Bitbucket API response `/checkov/bitbucket/schemas/branch_protection.py`: ```python from checkov.common.vcs.vcs_schema import VCSSchema class BranchRestrictionsSchema(VCSSchema): def init(self): schema = \ { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "pagelen": { "type": "integer" }, "values": { "type": "array", "items": [ { "type": "object", "properties": { "kind": { "type": "string" }, "users": { "type": "array", "items": {} }, "links": { "type": "object", "properties": { "self": { "type": "object", "properties": { "href": { "type": "string" } }, "required": [ "href" ] } }, "required": [ "self" ] }, "pattern": { "type": "string" }, "branchmatchkind": { "type": "string" }, "groups": { "type": "array", "items": {} }, "type": { "type": "string" }, "id": { "type": "integer" } }, "required": [ "kind", "users", "links", "pattern", "branchmatchkind", "groups", "type", "id" ] }, { "type": "object", "properties": { "kind": { "type": "string" }, "users": { "type": "array", "items": {} }, "links": { "type": "object", "properties": { "self": { "type": "object", "properties": { "href": { "type": "string" } }, "required": [ "href" ] } }, "required": [ "self" ] }, "pattern": { "type": "string" }, "branchmatchkind": { "type": "string" }, "groups": { "type": "array", "items": {} }, "type": { "type": "string" }, "id": { "type": "integer" } }, "required": [ "kind", "users", "links", "pattern", "branchmatchkind", "groups", "type", "id" ] }, { "type": "object", "properties": { "kind": { "type": "string" }, "users": { "type": "array", "items": {} }, "links": { "type": "object", "properties": { "self": { "type": "object", "properties": { "href": { "type": "string" } }, "required": [ "href" ] } }, "required": [ "self" ] }, "pattern": { "type": "string" }, "branchmatchkind": { "type": "string" }, "groups": { "type": "array", "items": {} }, "type": { "type": "string" }, "id": { "type": "integer" } }, "required": [ "kind", "users", "links", "pattern", "branchmatchkind", "groups", "type", "id" ] } ] }, "page": { "type": "integer" }, "size": { "type": "integer" } }, "required": [ "pagelen", "values", "page", "size" ] } super().init(schema=schema) schema = BranchRestrictionsSchema() ``` follow the examples in `tests/bitbucket/test_runner.py` and add a test to the new check So there you have it! A new check will be scanned once your contribution is merged!