BPL Logo Banner
CareersContact

In our ongoing series exploring the Department of Defense’s Continuous Authorization to Operate (cATO) model, we now turn our attention to two critical components: the Secure Software Supply Chain (SSSC) and DevSecOps practices. These elements form the backbone of a robust cATO implementation, ensuring both security and agility in software development and deployment.

Continuous Authorization to Operate (cATO) is changing the way organizations approach cybersecurity and compliance in dynamic IT environments. By embedding security directly into development and operational workflows, cATO enables real-time assessment, assurance, and authorization, promoting agility without compromising security.  An environment with effective personnel and processes is critical to achieving the intended goals and objectives of a cATO.


1. The Need for Continuous ATO in Modern Software Development

As software systems grow increasingly complex and interdependent, static and periodic compliance assessments fall short of ensuring security. Threats evolve faster than traditional systems and accreditation processes can adapt, creating vulnerabilities or weaknesses in the software supply chain and operational lifecycle.

The cATO approach addresses these challenges by shifting from static, point-in-time approvals to a dynamic, continuous assessment and authorization model. This shift requires integrating SSSC and DevSecOps as critical enablers of security, resilience, and agility.

Why Secure Software Supply Chains Matter

The software supply chain encompasses all components, dependencies, and processes involved in developing, deploying, and maintaining software applications. A compromised supply chain can lead to breaches that affect downstream systems, organizations, and even national security, as seen in incidents like the SolarWinds attack (SolarWinds, 2021) and XY/libzma.

Key principles for securing the software supply chain include:

  1. Transparency and Traceability: Ensuring visibility into every component, dependency, and contributor in the supply chain.
  2. Validation and Verification: Implementing mechanisms like digital signatures, cryptographic checks, and automated testing for integrity.
  3. Continuous Monitoring: Using real-time analytics and monitoring tools to detect and mitigate threats early.

[1] https://github.com/tukaani-project/xz/commit/e93e13c8b3bec925c56e0c0b675d8000a0f7f754

DevSecOps integrates security into every stage of the software development lifecycle (SDLC), fostering a culture of “secure by design.” By automating security practices and embedding them into CI/CD pipelines, DevSecOps enables organizations to meet cATO requirements effectively.

The Role of DevSecOps in cATO

Key DevSecOps practices include:


2. Integrating SSSC and DevSecOps for cATO Competency

The intersection of SSSC and DevSecOps represents the synergy required for achieving cATO competency. Here’s how organizations can align these practices to enable secure, compliant, and resilient IT systems:

A. Building a Secure Software Supply Chain

  1. Adopt a Zero-Trust Model: Assume every component in the supply chain is potentially compromised until proven otherwise.
  2. Utilize Software Bills of Materials (SBOMs): Maintain comprehensive SBOMs for all software assets to track dependencies and vulnerabilities.
  3. Leverage Automation: Use tools like dependency scanners and vulnerability management systems to identify and mitigate risks continuously.

B. Embedding DevSecOps Practices

  1. Shift Left: Engage security teams early in the SDLC to identify issues before deployment.
  2. Automate Compliance: Build compliance-as-code policies to ensure adherence to standards like NIST SP 800-53 or ISO 27001.
  3. Enable Continuous Feedback: Implement feedback loops between development, security, and operations teams for iterative improvements.


3. Benefits of cATO with SSSC and DevSecOps

When organizations integrate SSSC and DevSecOps into their cATO strategies, they unlock several benefits:


4. Challenges and Solutions

Challenges

  1. Cultural Resistance: Shifting to a DevSecOps mindset requires breaking silos and fostering collaboration.
  2. Tool Overload: Integrating numerous tools can overwhelm teams and complicate workflows.
  3. Skill Gaps: Teams may lack the expertise needed for advanced automation and security practices.

Solutions


5. Conclusion

As organizations navigate increasingly complex cybersecurity landscapes, the adoption of cATO frameworks, supported by secure software supply chains and DevSecOps practices, is no longer optional—it’s essential. By embedding security into every layer of development and operations, organizations can achieve continuous assurance and resilience while staying compliant with evolving regulations.

With the right combination of people, processes, and technologies, cATO empowers organizations to innovate securely, keeping pace with the demands of modern IT ecosystems.

References

  1. National Institute of Standards and Technology (NIST). (2021). NIST Cybersecurity Framework. Retrieved from NIST.gov.
    Referenced for zero-trust model and compliance automation in sections 2A and 2B.
  2. OWASP. (2023). Software Assurance Maturity Model (SAMM). Retrieved from OWASP.org.
    Referenced for secure coding, DevSecOps practices, and addressing cultural challenges in sections 1, 2B, and 4.
  3. Gartner. (2022). Best Practices for Securing Software Supply Chains. Retrieved from Gartner.com.
    Referenced for software supply chain transparency and challenges in sections 1, 2A, and 4.
  4. SolarWinds. (2021). Post-Breach Analysis and Learnings. Retrieved from SolarWinds.com.
    Referenced for insights on supply chain attacks and their risks in sections 1 and 3.
  5. IBM. (2022). DevSecOps Best Practices. Retrieved from IBM.com.
    Referenced for tools, automation, and addressing tool overload challenges in sections 1, 2, 3, and 4

The Django 2.1 ORM is quite capable. Though it does not cover every conceivable use case, it handles nearly all simple queries and many more complex queries as well. Still, there are times when I wish the ORM had some capability that it doesn’t. That’s happened a couple times this year as I’ve been learning Django. This post tells about a new QuerySet method we developed that’s been useful to us.

The Django ORM allows you to attach data to objects returned from a QuerySet using annotate() and aggregate(). These methods often do exactly what you need. However, there are cases that the Django ORM doesn’t handle. For example, what if I want to attach data that isn’t part of the model or a related model to an object? Perhaps the data is queried from another database or a web API. Maybe the data I need is in an unrelated model and for whatever reason I’m not at liberty to add a relationship. Or perhaps attaching the data via annotate() is theoretically possible but is cumbersome and would be much easier to do in Python code. Another case is attaching data obtained from a raw SQL query: Django has no way to join the result of a raw SQL query to a QuerySet.

From what I can tell, the standard technique in these cases is to use values() to make the QuerySet return a dictionary and then use Python code to add to that dictionary. This can work fine, but I may not want to convert the returned model instances into a dictionary. One example of this is when working with the Django REST Framework, where my serializer expects object instances. Another case is when I want to later call methods on the returned objects, which won’t work once they’ve been converted to dictionaries.

We kept running into situations like this, so I decided to look for a clear and easy to use solution. The result of my search was AugmentableQuerySet. This subclass of QuerySet has a single new public method augment() available. Let me give a trivial example of how to use it.

[code language="py"]
class Product(models.Model):
     name = models.CharField(max_length=255)
     description = models.TextField()
     model_number = IntegerField()
     base_price = models.DecimalField(max_digits=8, decimal_places=2)
     tax_class = CharField(max_length=1)

     objects = AugmentableQuerySet().as_manager()

def format_name_and_model(product):
     return f'{product.name} model {product.model_number}'

products = Product.objects.augment(name_and_model=format_name_and_model)

for prod in products:
    print(prod.name_and_model)
[/code]

This silly task could be accomplished with annotate(), but it gives an idea of how augment() works: it takes one or more keyword arguments, where the argument name is the field name to be added to the object and the argument value is a function that is called on the object to calculate the value for the new field. It can be anything that is callable: a function, a lambda or a class with a __call__ method. The callable must take a single argument, which is the object (or dictionary) returned by the QuerySet.

Here is a more realistic example that shows you can attach multiple fields to the object.

[code language="py"]

def WarrantyLookup(user):
    def lookup(obj):
        params = {'country': user.address.country,
                  'model_number': getattr(obj, 'model_number')}
        r = requests.get(WARRANTY_URL, param=params)
        return r.json()['period']

    return lookup

def product_price(product, user, tax_table):
    return complex_calculation_of_tax(product.base_price,
                                      product.tax_class,
                                      user.address.zip_code,       
                                      tax_table)

products = Product.objects 
    .augment(warranty_period=WarrantyLookup(request.user),
             price=lambda p: product_price(p, request.user, tax_table))

for prod in products:
    print(prod.name, prod.warranty_period, prod.price)
[/code]

The WarrantyLookup is in upper camel case to fit the Django convention for query expressions. (For example, Sum or ExpressionWrapper.) Neither warrant_period nor price are part of the model, but the Product instances returned by the augmented QuerySet have both of those fields.

Below is the implementation of AugmentableQuerySet. It works with QuerySets that return model object instances or dictionaries. It could be modified to handle tuples returned by values_list(). Note that if you call the values() method on the QuerySet to generate dictionaries, the call to augment() must come after it. This is because values() replaces the QuerySet iterator that augment() has wrapped, so the call to augment() will have no effect.

[code language="py"]
class AugmentableQuerySet(models.QuerySet):
    @staticmethod
    def _make_iterable(iterable, expressions):
        class AugmentIterable(iterable):
            def __iter__(self):
                for row in super().__iter__():
                    for field, func in expressions.items():
                        if isinstance(row, dict):
                            row[field] = func(row)
                        else:
                           setattr(row, field, func(row))
                     yield row
         return AugmentIterable

    def augment(self, **expressions):
        clone = self._chain()
        clone._fields = tuple(expressions)
        clone._iterable_class = self._make_iterable(self._iterable_class, expressions)
        return clone

    objects = AugmentableQuerySet().as_manager()[/code]

augment() adds a new field to all objects returned by a queryset, the value of which is the result of applying a function to the object. The implementation is fairly simple, though you don’t need to understand the code above to use augment(). One potential issue is that _iterable_class is not a documented part of Django 2.1, so a new version of Django might break our code. We have some simple tests around the AugmentableQuerySet class that should catch any problems.

We created AugmentableQuerySet to make our Django code shorter and easier to understand. It has been working well for us so far. We may improve the implementation as we gain more experience with it, or perhaps we’ll find a better way to accomplish what we want. For now, though, this has been a successful addition to our Django toolbox.

This video provides a crash course introduction to Linux for security analysts. It is common for security analysts to enter the field with their Linux skills lacking. Linux provides a security analysts with such powerful data analysis capabilities using built-in utilities (Grep, Sed, Awk, Egrep, Sort, Uniq, etc.).

This video hopefully gives someone new to Linux a few jumping off points by showing some useful examples (analyzing pcap, parsing nmap, simple for loop automation, and parsing HTML). The video ends with a quick proof of concept example of how to enumerate *most* of Facebook’s public infrastructure using a single bash command.

Check it out below:

chevron-down