/
/
Securing the Software Supply Chain with Open Policy Agent: Policies for Pull Requests and Beyond

Securing the Software Supply Chain with Open Policy Agent: Policies for Pull Requests and Beyond

April 21, 2023
Profile Icon

Jason Franscisco

In the world of supply chain management, it’s crucial to ensure that code changes are adequately reviewed and tested before being integrated into the main codebase. Pull requests play a critical role in this process as they allow developers to review and ensure that the code adheres to established coding standards and best practices. The significance of this process cannot be overstated, as even minor errors or bugs can have far-reaching consequences for the entire supply chain.

A successful supply chain management strategy involves not only reviewing pull requests, but also incorporating automated testing and continuous integration as crucial components. Automated testing enables the early detection of bugs and errors, while continuous integration ensures that changes are integrated into the main codebase as soon as possible. Open Policy Agent (OPA) can be used to automate policy enforcement, making it easier to implement. Developers can define policies that warrants code changes adhere to established coding standards and other best practices. By enforcing these policies automatically, OPA can help guarantee that the codebase remains consistent and maintainable, minimizing the risk of errors and bugs that could harm the entire supply chain. OPA allows organizations to enforce policies that govern the software supply chain, By implementing these policies, organizations can establish a secure and transparent supply chain, which is crucial for maintaining the integrity and authenticity of software artifacts. This, in turn, helps in minimizing the risk of supply chain attacks.

OPA - Solution Architecture

Below is a Git action workflow for pull requests designed to integrate OPA into testing against policies. The workflow is triggered by various pull request events, such as opening, editing, and labeling.

name: Workflow for Pull Request OPA Policy 
on: 
  pull_request: 
    types: [opened, edited, labeled] 
 
jobs: 
  opa_review_policy: 
    runs-on: ubuntu-latest 
    steps: 
    - name: Checkout Code 
      uses: actions/checkout@v3 
    - name: Installation of OPA 
      run: | 
      curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64 
      chmod 755 ./opa 
    - name: Check Pull Request 
      run: | 
      ./opa eval -i ${GITHUB_EVENT_PATH}  -d repo/policy.rego
} 

Below are some policies that can be enforced with Open Policy Agent (OPA) to establish a secure software supply chain.

Code Review Policies:
Two-person review is an industry best practice for catching mistakes and deterring bad behavior, and it is also a part of `SLSA L4(https://slsa.dev/spec/v0.1/levels)`. This can be achieved using the Rego policy, which can be written to ensure that a certain number of reviewers review all pull request changes before they are merged.

package pr_review_policy 
min_reviewers = 2   
default allow = false  
allow[msg]{ 
    reviewers := input.review.approved_reviewers 
    num_reviewers := count(reviewers) 
    num_reviewers >= min_reviewers 
    msg := "reviewers not satisfied" 
}             

It sets a minimum number of reviewers required for a pull request to be approved, which is 2 in this case. The default value for allowing a pull request is set to false. The policy also defines an "allow" rule with an error message that will be displayed if the number of approved reviewers is less than the minimum required. The rule checks the number of approved reviewers and compares it with the minimum required number. If the minimum criteria are met, the rule allows the pull request to be merged.

Access Control Policies:
Access control policies are a crucial aspect of any secure system. They define the users or groups are authorized to perform specific actions and those that are not. Without access control policies, any user be able to perform any action, making the system vulnerable to security threats. For example, it's important to ensure that only authorized users can create, merge, or approve pull requests. Access control policies can be used to manage users or groups with permission to perform these actions.

Let's write a policy that govern who has access to review and merge pull requests.  

 
package pr_access_control 
default allow = false 
allowed_reviewers = ["r1", "r2"] 
allowed_approvers = ["a1", "a2"] 

allow { 
    event := input.pull_request 
    input.action == "opened" 
    event.merged == false 
    event.requested_reviewers[_].login == allowed_reviewers[_] 
    event.head.repo.owner.login == event.base.repo.owner.login 
    approver := event.requested_reviewers[_].login 
    approver == allowed_approvers[_] 
} 
 

The policy then defines two arrays, "allowed_reviewers" and "allowed_approvers", which contain the usernames of the reviewers and approvers who are allowed to access the pull request. The "allow" rule is defined with a set of conditions that must be met for the pull request to be allowed. The conditions check to see if

  1. the requested reviewers are in the "allowed_reviewers"
  2. the owner of the head repository is the same as the owner of the base repository, and
  3. the approvers are in the "allowed_approvers"

Security Impact Assessment Policy:
Rego can be used for defining policies that specify the criteria that must be met to pass a security impact assessment. These policies can include rules that check for various security requirements, such as

  1. encryption requirements
  2. compliance with regulatory requirements and secure coding practices
  3. protection of sensitive data, and
  4. detection and response to security incidents

Below policy that can detect the usage of deprecated or vulnerable libraries and configuration changes in a pull request.

package pr_security_policy 
 deny[msg] { 
    input.type == "pull_request" 
    lib := input.files[_].name 
    deprecated_libs := ["lib1", "lib2", "lib3"] 
    vulnerable_libs := ["lib4", "lib5", "lib6"] 
    lib in deprecated_libs 
    lib in vulnerable_libs 
    msg := sprintf("use of deprecated/vulnerable library %v", [lib]) 
} 
deny[msg] { 
    input.type == "pull_request" 
    infra_config_files := ["network_security.yaml", "database_config.yaml"] 
    infra_config_files[_] == input.files[_].name 
    msg := "changes to infrastructure config" 
} 
deny[msg] { 
    input.type == "pull_request" 
    auth_files := ["auth.py", "auth_config.yaml"] 
    auth_files[_] == input.files[_].name 
    authz_files := ["authz.py", "authz_config.yaml"] 
    authz_files[_] == input.files[_].name 
    msg := "changes to auth code are not allowed" 
}  
}

Explanation:

The pr_security_policy is a sample policy that denies pull requests that include the use of deprecated or vulnerable libraries, changes to infrastructure config files, or changes to auth code. It provides error messages to indicate why the pull request was denied.

We should develop a new Rego policy to identify any occurrences of sensitive data disclosure in code. This policy will leverage a code review tool to review the changes made in pull requests and provide a verdict.

package pr_sensitive_data 
default allow = false 
allow { 
    input.action == "opened" 
    not sensitive_data_found 
} 
deny[msg] { 
    input.action == "opened" 
    sensitive_data_found 
    msg = "sensitive data found in pr" 
 } 
 
sensitive_data_found { 
    scan_request := sprintf("YOUR_TOOL_API=%v", [input.pull_request.number]) 
    response := http.send({ 
        "method": "GET", 
        "url": scan_request, 
    }) 
    response.status_code == 200 
    response.raw_body == "sensitive_info_response"
    response.body.sensitive_data_found == true 
} 

*you will need to replace the YOUR_TOOL_API  with the URL of your code scanning tool.

Explanation:

The "sensitive_data_found" rule defines a method to scan the pull request using a tool API and checks whether the response contains sensitive information. If the response contains sensitive data, the rule sets the "sensitive_data_found" variable to true, which triggers the "deny" rule and rejects the pull request. This policy can help prevent sensitive data leaks and ensure that pull requests are secure before they are merged into the main codebase.


Compliance Policies:

OPA can be used to set compliance policies, such as restricting access to sensitive data to authorized users and policies that ensure that pull requests comply with relevant regulations and standards, such as data privacy regulations.

Let us write a policy based on best practice that checks that artifacts are signed by a trusted entity before deployment.  

package pr_signing_policy 
default allow = false 
allow { 
    input.pull_request.base.ref == "main" 
    input.artifacts[_].signed_by == "trusted_entity" 
} 
deny { 
    input.pull_request.base.ref == "main" 
    not input.artifacts[_].signed_by == "trusted_entity" 
} 

In conclusion, having policies for code review, access control, security impact assessment, and compliance is crucial for ensuring that pull requests are properly vetted before they are merged into the codebase. These policies help to prevent unauthorized changes, reduce the risk of security vulnerabilities, and ensure compliance with relevant regulations and standards. By leveraging OPA, organizations can improve their overall development processes and ensure that their code is secure, compliant, and of the highest quality. In addition, OPA provides a flexible and scalable way to define and enforce policies across the entire infrastructure, making it easier to maintain a secure and compliant supply chain.  

References

Author:

Pruthvi T - Lead Security Researcher, Loginsoft

Explore Cybersecurity Platforms

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros.

Learn more
white arrow pointing top right

Subscribe to our Reports

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

IN-HOUSE EXPERTISE

Latest Articles

Get practical solutions to real-world challenges, straight from experts who conquered them.

View all our articles