TAG post by members of TAG security including Marina Moore, Michael Lieberman, John Kjell, James Carnegie, and Luca Bandini
Reviewers: Emily Fox, Andrés Vega, Andrew McNamara, Andrew Block, Jon Zeolla, Andrew Martin
Introduction
Software supply chain policy describes the required components and processes that govern the production and consumption of software artifacts. Policies enable automated reasoning for the steps in the supply chain by detailing the roles of different actors and the sequence of actions they should perform. These policies serve as a framework to ensure security and conformance with the intended process for releasing software.
Our discussion on software supply chain security policy is informed by an understanding of the current landscape, including the prevalent practices, challenges, and practical solutions within this domain. However, while we acknowledge the current state, our focus is on the overarching concepts and strategies rather than a deep dive into the specific details of present practices. Our aim is to provide a framework and guidance that can be applied within this evolving field.
Scope This document concentrates on the creation, dissemination, implementation, and evaluation of policies that bolster security in the software supply chain. We delve into how technical policies, which often stem from compliance requirements, can be effectively mapped onto engineering requirements. These are then operationalized as specific “procedures” within the supply chain environment. While acknowledging the influence of broader government and corporate policies on software supply chain security, our analysis is specifically tailored to these technical policies and their practical implementation. We also focus on policy for the software supply chain, and exclude discussion of runtime policy.
Policy-as-code
“Policy-as-Code” is a modern approach to policy management that blends software engineering principles with the creation and evaluation of operational and security guidelines. This method shifts away from traditional, static policy documentation to a dynamic framework where policies are codified, versioned, and automatically and consistently evaluated across an organization’s digital assets. It enhances compliance, consistency, and efficiency by leveraging centrally managed policies for the evaluation of distributed software artifacts and their configuration. Automated policy decisions ensure consistency, reducing the likelihood of error which can be caused by outdated policies or human error.
In the context of the software supply chains, particularly with the exponential growth of open-source software usage, Policy-as-Code becomes increasingly crucial. Ensuring the provenance and integrity of software assets, especially those built using open-source packages and libraries, is important to understand their risk profile. By leveraging Policy-as-Code, organizations can reason holistically about their quality, compliance, and regulatory objectives and visualize conformance across their systems. Our exploration of Policy-as-Code for software supply chain security focuses on the authoring, distributing, and evaluating policies for software supply chains that utilize open source packages and libraries.
For clarity, it’s important to distinguish how the term ‘policy’ is used in this document. Here, ‘policy’ refers specifically to concrete implementations within software systems, rather than the broader policies typically outlined in corporate documents. They are a set of formal, executable rules that are integrated into software applications as well as their supporting infrastructure. These rules govern aspects such as user access levels and resource utilization. Their primary purpose is to ensure alignment with specified security standards and functional objectives.
Attestations enable enriched policy decisions by providing additional cryptographically-signed evidence from tools and processes within the supply chain. Attestations are records of actions that occurred in the software supply chain, offering transparency, accountability, and verifiability for these actions. While it may be common for policy engines to extend trust to the build platforms via the automated attestations generated during the artifact’s lifecycle, manually created attestations can also be used. By incorporating attestations into the decision making process, policies should ensure that the identity of the author has been appropriately protected and that the author is authorized to make the specified specific claims.
Policy Implementation Across Domains
In a software supply chain, policy evaluation can be applied to various domains of a software architecture, including the below, each offering a different degree of granularity and control. In this context, a domain is a part of the software stack, but is not hierarchical or mutually exclusive. Implementing policies across multiple domains is essential for achieving end-to-end evaluation, as it ensures that each domain’s unique challenges and risks are addressed comprehensively.
Policy Domains
- Infrastructure: Policies focus on the configuration and management of infrastructure components, like servers, networks, and storage systems. Policies ensure secure and compliant environments are used for developing, deploying and orchestrating software components throughout the supply chain.
- Platform: Policies establish guidelines for development platforms and tools, such as CI/CD pipelines. They standardize and improve secure development practices and reduce vulnerabilities by setting conformance standards for the components used to build the platform.
- Source: Policies specify requirements on the source code, setting security standards, desired behaviors, and compliance with regulatory requirements. They act as a critical security gate to ensure trust and integrity within application code [1].
- Build: Policies govern the build procedures, stipulating that specific tools are used for compiling and building software, managing dependencies, and ensuring code provenance. These play a key role in maintaining the integrity of the build environment.
- Execution: Policies mandate the secure operation of the build and continuous integration machinery during its execution phase (rather than the target production environment). They enforce specific behaviors, including resource allocation and security access controls, tailored to the build environment. These also encompass monitoring and logging strategies to promptly detect and respond to operational or security issues, and provide a dynamic and adaptive behavior to remediate anomalies and deviations against the specified policy intent.
Reflecting on Domain Intersections
While the above categorization is useful, it’s important to acknowledge that modern development practices like Infrastructure as Code (IaC) and reproducible builds result in domain convergences. The distinctions between infrastructure, platform, and source domains blur as the entire stack often gets treated with the same ‘pipeline mentality.’ To uphold the integrity of the supply chain, one must consider a holistic approach where infrastructure can be redeployed with the same rigor and predictability as applications. This integration reflects a more mature understanding of the supply chain, where policy evaluation is seamless and cohesive across all domains.
Scaling Policy Management: Strategies for Maintaining Control as the Number of Policies Grow
The following considerations are not confined to individual domains, but apply to the overarching policy framework that spans the entire software supply chain. While policies may vary in their specific implementation, the principles governing their creation, deployment, and maintenance remain consistent throughout.
- Clarity and Expressiveness: Policies must be clearly written and understood, with a well-defined scope and functionality. Adequate commenting within the code enhances understanding and maintainability.
- Visible: Policies should be stored in a source control management system and be accessible to the organization. This transparency allows for the identification of gaps, mistakes, continuous improvement, and facilitates integration and interoperability with other projects, vendors, and suppliers.
- Versioned: Policies should follow a versioning scheme to allow tracking of changes. Different versions of policies must be tracked unambiguously (such as by using cryptographic hashes), so that a policy file cannot be silently edited or replaced.
- Consumability and Update Mechanisms: Treat policies as software dependencies to enable automated updates through tools like Dependabot, Renovate, or Mend. This ensures policies remain current with automatic pull requests, testing, and merging.
- Granularity: Specific, granular policies offer greater control, but these should not become so complex as to be unmanageable. Balancing policy detail and practicality is key.
- Reusable: Policies should be adaptable to new and evolving technologies, security requirements, technology stacks, and infrastructure changes. Adhering to best practices in code quality promotes modularity and reusability.
- Testable: Policies, much like any other software component, must be thoroughly tested to ensure consistency and prevent unintended behaviors.
- Measurable: Implementation of policies should yield clear metrics or pass/fail results, enabling the quantification of compliance and effectiveness.
- Cross-cutting Concerns: Policies should be generalized for multiple stakeholders as their enforcement may have implications across various aspects of the organization, the software stack, operators, and end users.
Designing and Evaluating Effective Policies
An effective policy enables its author to fulfill their requirements across three broad categories: accuracy, evaluation, and confidence.
- Accuracy: How well the policy adheres to the range of technical requirements inthe aforementioned domains. For example: a supply chain policy requires the exact code, with no modifications, cloned from a git repository which is then provided as input into a build process.
- Evaluation: Policy that is not evaluated has no value. The evaluation will require access to the attestations.
- Confidence: Testing increases users’ certainty of the policy’s correctness. As software and infrastructure as code (IAC) is tested, a policy may also be tested. Test cases and artifacts should support validating passing, failing, and potential edge case scenarios.
Distribution and Evaluation
With a clear definition of policy across each domain, the focus now shifts to the distribution and evaluation of these policies. Distribution involves ensuring policies reach the appropriate entities within each domain, while evaluation verifies attestations and confirms that the designated procedures have been executed by the expected actors within the software supply chain.
A critical initial step is to establish trust in the policies themselves. It is important to delineate the authors of a policy and those that sanction its use as a security control. The approval typically comes from a different entity, which we will refer to as the policy root of trust. This entity is responsible for validating the policy definition. Given the role that policy plays in supply chain verification, establishing this trust is sensitive and requires careful deliberation. The trust establishment mechanism should include provisions for key revocation in the event of a compromise and key rotation as a matter of security best practice. There is more detail about policy roles in other documents [2].
While policies come from a trusted source, they should undergo a multiparty review and approval process, ensuring transparency and mitigating the risk of tampering. In essence, the degree of trust should be more robustly placed on the attestations and the integrity of the policy root of trust, rather than solely on the policy or its signatory.
Over time, policies inevitably evolve and adapt to changing requirements. When new policy versions are developed or progressively deployed, the policy root of trust should endorse these updates. To prevent policy verifiers from relying on outdated or potentially less secure versions, the policies should be distributed with safeguards against rollback attacks. Rollback attacks occur when an attacker is able to convince a user to use old, previously valid policy instead of the current policy [3]. They can be prevented through guarantees that a verifier always applies the most recent policy.
As policies are versioned, various versions may be simultaneously active across different environments, or applied to distinct software assets in parallel. This variability necessitates a flexible, yet secure, approach to policy distribution and evaluation. [4]
There are parallels between secure policy distribution and other secure distribution challenges, such as those faced in software delivery and updates. Tools for secure software distribution can be repurposed to harden the distribution of policies, linking a policy directly to individual software assets. Once the policy is distributed, the application can verify it against any attestations to confirm adherence.
Conclusion
Policy-as-code is a valuable tool for creating, enforcing, and improving policy for software supply chains. This method facilitates continuous improvement of policy to comply with new regulations and best practices. Teams can test their supply chain as code, using a defined policy that sets clear expectations. Policy as code can be applied to define policies at each domain, and also between domains, enabling each entity in the software supply chain to detect and prevent compromises. This interaction between entities in the supply chain mirrors the communication between software teams, and enforcing this can improve communication.
To expand your understanding and application of these tools within your organization:
- Read the Software Supply Chain Whitepaper.
- Support and contribute to the development of policy tooling, including the open source tools below.
- Reflect on the current policies within your systems, considering how they might be enhanced or expanded.
- Stay informed on emerging policy trends and best practices to continuously refine your approach by following work from the open source community, including TAG Security and other CNCF efforts.
- Come join the TAG Security software supply chain WG!
Tools for Policy Implementation and Evaluation
A range of specialized open source solutions is available to effectively implement and evaluate policies, each serving a distinct role. These lists are not exhaustive and are intended to serve as a reference.
Policy Engines:
- Gatekeeper
- Kyverno
- Sigstore policy-controller
- Checkov
- jsPolicy
- Enterprise Contract
- roxctl
- Pepr
- OpenFPGA
Policy Languages/schemas:
- Rego
- Cue
- CEL
- Cedar
- in-toto
Enforcement Points:
- Artifact Ingress/Artifact ingestion
- CI/CD Pipelines
- Admission Control
- Execution/runtime
- Auditing
- Background Resource Scanning
Secure policy distribution:
- The Update Framework (TUF)
References
[1] – For more on gates in the Source Domain, see the DevOps Automated Governance Reference Architecture from IT Revolution.
[2] – https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-204B.pdf, https://github.com/kubernetes/sig-security/blob/main/sig-security-docs/papers/policy/kubernetes-policy-management.md#policy-architecture
[3] – Mercury: Bandwidth-Effective Prevention of Rollback Attacks Against Community Repositories
[4] – Nesbitt-Smith, Chris. “Policy As [Versioned] Code.” Presented at the Linux Foundation’s Critical Software Summit Europe 2022.