Article series: DevOps part 2 of 3

DevOps - Plan to Test

In this article, we describe the first half of a Software Development Lifecycle (SDLC) inspired by the eight parts of the DevOps loop, mapping out development and security activities to each part.

OP-devops.png

DevOps

The "correct" DevOps loop

Plan 

When planning your application, it is important to talk about the privacy, accuracy and accessibility (CIA) requirements that are relevant to you: 

  • Creation (e.g. input validation) 

  • Processing (e.g. integrity checking and performance) 

  • Storage (e.g. location and access controls) 

  • Transmission (e.g. encryption, control of sender/receiver) 

  • Destruction (e.g. secure removal and physical destruction) 

Conduct threat modelling to identify and address potential security and privacy-related threats in your proposed architecture/solution. Threat modelling can be as simple as asking your team the following questions: 

  • What are we working on? 

  • What can go wrong? 

  • What can we do about it? 

  • Did we do a good job? (feedback loop) 

Alternatively, you can use a method that is designed to provide value without being too time-consuming, such as Rapid Threat Model Prototyping. For more information on threat modelling, see the Threat Modelling Manifesto.

Work to limit the attack surface against your application. This could be not activating/installing features that will not be used or closing ports that do not need to be open. 

Remember the security principles of "don't rely on input", "minimum authority" and "defence in depth". 

Code 

Do not check secrets (passwords, connection strings, api keys) that are in the code or in configuration files. Use a solution to store secrets such as HashiCorp Vault, Azure Key Vault or AWS Secrets Manager. 

Configure "branch protection" for your code repository so that a pull request is required to check in code. Feel free to complement your pull request procedure with a more formal peer review where someone else on the team looks at the code from different perspectives. Perhaps you have agreed on a peer review checklist where there are a number of security aspects you look for. The review should certainly be lightweight and not feel extensive or time-consuming. If you are working with pair programming, the requirement for peer review comes as a bonus. 

To achieve even better code delivery capabilities, consider working with trunk-based development with short-lived branches (one day, max two) instead of long-lived feature/release branches. 

Use the built-in support for stricter controls in the development tool if available, e.g. compile with highest warning level, treat warnings as errors, enable linting in your IDE, etc. 

Validate input and "escaping" output in your application. Use Allow lists instead of Deny lists, if possible. More information on input validation can be found in the OWASP Cheat Sheet series on input validation.

Implement application logging so that it can be used by yourself in the event of an incident where you need to look at the logs to answer what really happened. More information on application logging can be found in the OWASP Cheat Sheet series on application logging

Make it a habit to create unit tests for all new features/methods you write. 

Remember the security principles of "don't trust the input", "minimum permissions", and "defense in depth" even when coding. 

Build 

Use an automated CI/CD pipeline. Integrate code frequently (daily if possible), do not work with long-lived branches in the code. 

Scan the code for old or vulnerable external components. Preferably with a tool that is integrated into your build pipeline. 

Make sure to create a BoM (bill of material) listing all the external components you use (you can almost always get such a list from the tool you use above to scan the code). This list can be useful if a vulnerability appears in a component and you need to be able to answer whether you are using that particular component. 

Scan the code you write yourself for dangerous or vulnerable coding patterns with a SAST (Static Application Security Testing) tool. The tool can either be integrated into your build pipeline or into the developers' IDE.  

Test 

Automate as many test cases as possible. These test cases together with pull request/peer review are the foundation that gives you the confidence to release often and eventually fully automatically. 

Derive test cases from your threat modelling to ensure that your protective measures really work.  

Consider fuzz testing of parameters and APIs to ensure they are resistant to erroneous or random input. 

Conduct automated tests with a DAST (Dynamic Application Security Testing) tool, e.g. by running the OWASP ZAP baseline scan as part of releasing to a test environment or by running a longer test overnight.