Using Schema Enforcer with Docker and CI

Blog Detail

Recently Network to Code open sourced schema-enforcer, and immediately my mind turned to integrating this tool in with CI pipelines. The goal is to have fast, repeatable, and reusable pipelines that ensure the integrity of the data stored in Git repositories. We will be accomplishing repeatability and reusability by packaging schema-enforcer with Docker and publishing to a common Docker registry.

Why integrate with CI pipelines?

By integrating repositories containing structured data with a CI pipeline that enforces schema you are better able to predict the repeatability of the downstream automation that consumes the structured data. This is critical when using the data as a source of truth for automation to consume. It also helps to react faster to an incorrect schema before this is used by a configuration tool, such as Ansible. Imagine being able to empower other teams to make chages to data repositories and trust the automation is performing the checks an engineer manually does today.

How containers can speed up CI execution.

Containers can be a catalyst to speeding up the process of CI execution for the following reasons:

  1. Having purpose built containers in CI allows for standardized pipelines with little setup time.
  2. Sourcing from a pre built image to execute a single test command removes the need to build an image or manage a virtual environment per repository.
  3. Reducing build times from using pre-built images allows for faster running pipeline and helps to shorten the feedback loop to the end user.

Example with privately hosted GitLab.

For today’s example I am using my locally hosted GitLab and Docker Registry. This was done to showcase the power of building internal resources that can be easily integrated with on-premise solutions. This example could easily be adapted to run in GitHub & Travis CI with the same level of effectiveness and speed of execution.

Building a container to use in CI.

Click Here for documentation on Dockerfile construction and docker build commands. The Dockerfile is starting with python:3.8 as a base. We then set the working directory, install schema-enforcer, and lastly setting the default entrypoint and command for the container image.

Dockerfile

FROM python:3.8

WORKDIR /usr/src/app

RUN python -m pip install schema-enforcer

ENTRYPOINT ["schema-enforcer"]

CMD ["validate", "--show-pass"]

Publishing schema-enforcer container to private registry.

Click Here for documentation on hosting a private docker registry. If using Docker Hub, the image tag would change to <namespace>/<container name>:tag. If I was to push this to my personal Docker Hub namespace, the image would be whitej6/schema-enforcer:latest.

docker build -t registry.whitej6.com/ntc/docker/schema-enforcer:latest .

docker push registry.whitej6.com/ntc/docker/schema-enforcer:latest

Integrating GitLab Runner with data repo.

For the first use case, we are starting with example1 in the schema-enforcer repository located here. We then add a docker-compose.yml, where we mount in the full project repo into the previously built container and create a pipeline with two stages in .gitlab-ci.yml, which is triggered on every commit.

➜  schema-example git:(master) ✗ tree -a -I '.git' 
.
├── .gitlab-ci.yml
├── chi-beijing-rt1
│   ├── dns.yml # This will be the offending file in the failing CI pipeline.
│   └── syslog.yml
├── docker-compose.yml
├── eng-london-rt1
│   ├── dns.yml
│   └── ntp.yml
└── schema
    └── schemas
        ├── dns.yml # This will be the schema definition that triggers in the failure.
        ├── ntp.yml
        └── syslog.yml

4 directories, 9 files

Click Here for documentation on docker-compose and structuring the docker-compose.yml file. We are defining a single service called schema that uses the image we just publish to the Docker registry and are mounting in the current working directory of the pipeline execution into the container at /usr/scr/app. We are using the default entrypoint and cmd specified in the Dockerfile as schema-enforcer validate --show-pass but this could be overwritten in the service definition. For instance, if we would like to enable the strict flag, we would add command: ['validate', '--show-pass', '--strict'] inside the schema service. Keep in mind the command attribute of a service overwrites the CMD directive in the Dockerfile.

---
version: "3.8"
services:
  schema:
    # Uncomment the next line to enable strict on schema-enforcer
    # command: ['validate', '--show-pass', '--strict']
    image: registry.whitej6.com/ntc/docker/schema-enforcer:latest
    volumes:
      - ./:/usr/src/app/

Click Here for documentation on structuring the .gitlab-ci.yml file. We are defining two stages in the pipeline, and each stage has one job. The first stage ensures we have the most up to date container image for schema-enforcer and next we run schema service from the docker-compose.yml file. By specifiying --exit-code-from schema we are passing the exit code from the schema to the docker-compose command. The commands specified in the script are used to determine whether the job runs successfully. If the schema service returns a non-zero exit code, the job and pipeline will be marked as failed. The second stage ensures we are good tenants of docker and clean up after ourselves, docker-compose down will ensure we remove any containers or networks associated with this project.

---
stages:
  - test
  - clean

test:
  stage: test
  script:
    - docker-compose pull
    - docker-compose up --exit-code-from schema schema

clean:
  stage: clean
  script:
    - docker-compose down || true
  when: always

Failing.

In this example chi-beijing-rt1/dns.yml has a boolean value instead of an IPv4 address as specified in the schema/schemas/dns.yml. As you can see, the container returned a non-zero exit code, failing the pipeline and blocking the merge into a protected branch.

chi-beijing-rt1/dns.yml

# jsonschema: schemas/dns_servers
---
dns_servers:
  - address: true # This is a boolean value and we are expecting a string value in an IPv4 format
  - address: "10.2.2.2"

schema/schemas/dns.yml

---
$schema: "http://json-schema.org/draft-07/schema#"
$id: "schemas/dns_servers"
description: "DNS Server Configuration schema."
type: "object"
properties:
  dns_servers:
    type: "array"
    items:
      type: "object"
      properties:
        name:
          type: "string"
        address: # This is the specific property that will be used in the failed example.
          type: "string"
          format: "ipv4"
        vrf:
          type: "string"
      required:
        - "address"
      uniqueItems: true
required:
  - "dns_servers"

Runner output.

We see exactly which file and attribute fails the pipeline along with the runtime of the pipeline in seconds. 

Blocked Merge Request.

When sourcing from a branch with a failing pipeline, GitLab has the ability to block merging until the pipeline succeeds. By having the pipeline triggered on each commit we can resolve the issue on the next commit, which then triggers a new pipeline. Once the issue has been resolved, we will see the Merge button is no longer greyed out and can be merged into the target branch.

Passing.

Now the previous error has been corrected and a new commit has been made on the same branch. GitLab has then rerun the same pipeline with the new commit and upon passing the branch can be merged into the protected branch.

chi-beijing-rt1/dns.yml

# jsonschema: schemas/dns_servers
---
dns_servers:
  - address: "10.2.2.3" # This is the value that has been updated to align with the schema definition.
  - address: "10.2.2.2"

Runner output,

With the issue resolved and committed, we now see the previously offending file is passing the pipeline. 

Fixed Merge Request.

The merge request is now able to be merged into the target branch.

As a network engineer by trade that has come into automation, it at times has been difficult to trust the machine that was building the machine let alone trusting others eager to collaborate. Building safe guards for schema into my early pipelines would have saved me a tremendous amount of time and headache.

Friends don't let friends merge bad data.



ntc img
ntc img

Contact Us to Learn More

Share details about yourself & someone from our team will reach out to you ASAP!

NetDevOps Concepts – Infrastructure as Code

Blog Detail

Welcome to the third in our series of posts about NetDevOps concepts! We have previously done an introductory post, as well as one on the concept of Minimum Viable Product, so be sure to check those out if you haven’t already!

In this post we’re going to dive into the concept of Infrastructure as Code or IaC, and how it can be applied to your network.

Infrastructure as Code is a commonly used DevOps term for managing or provisioning equipment in your infrastructure via an automated and repeatable process. This means that your infrastructure is always maintained in a known and pre-defined state, which allows you to utilize and enforce best practices across your entire infrastructure with ease.

In addition, adhering to Infrastructure as Code principles ensures that your infrastructure is less prone to unexpected or unplanned changes. Even if someone did change the infrastructure manually, and cause a negative impact, you are able easily and immediately re-apply the known/good state to restore service.

Your security team will thank you as well, because being able to uniformly ensure that good, secure, configurations are in place on your equipment makes their jobs tremendously easier.

The Pillars of Infrastructure as Code

In order to build an Infrastructure as Code based NetDevOps solution in your own network, it is essential to understand the key underlying components, or pillars, of Infrastructure as Code. A firm grasp on the pillars, how they interact, and which tools belong in which pillar, will allow you to craft a powerful and robust IaC solution in your environment.

Infrastructure as Code is usually built upon four key pillars.

  1. Source of Truth (SoT) – SoT is often a combination of the following components:
  2. CI/CD – CI/CD stands for Continuous Integration and Continuous Deployment or Delivery and describes systems used to manage and execute the changes to, or deployment of, your infrastructure.
  3. Tests – Tests allow you to go forward with the faith that changes executed by this process will be successful and not cause unwanted or unintended changes to your infrastructure.
  4. Deployment and Configuration Tools – These tools are varied and can take many forms depending on the IaC system being built. For NetDevOps these will frequently be tools or systems that can talk to the management plane of the network (via SSH or HTTPS) to implement changes.

If we were building the Infrastructure as Code “house”, consider Source of Truth to be the blueprints. The CI/CD system is the Foreman or General Contractor overseeing construction, and Tests are the Building Inspector. Your Deployment and Configuration Tools are the Electrician, Plumber, and Carpenter who build the house!

There are many potential combinations of Source of Truth, CI/CD, Testing and Deployment tools, so don’t worry if the possibilities initially seem overwhelming. For example, Source of Truth and CI/CD will have entire dedicated articles in this series. To assist with becoming more familiar with the tools available to you, at the end of this post we have collected an Appendix called “Lay of the Land” with tools in each of these pillars and links for further research.

An Example of the Pillars in Action

If we think about the IaC pillars, we can construct an example scenario using them to illustrate each pillar’s purpose in an overall Infrastructure as Code deployment.

A system built on these pillars often utilizes configuration and metadata files, kept in a Source Control system such as Git, to generate device configurations based on facts kept in a System of Record/DCIM such as NetBox. Together these elements form the Source of Truth for a portion of the infrastructure. Engineers would make changes to a file or files in Git to describe the desired changes to the state of the infrastructure. Prior to these changes being implemented on the infrastructure, they would require a peer review, and for any tests run by the CI/CD system to pass.

When these proposed changes are made to the relevant area of your Source of Truth, a CI/CD tool such as Jenkins will detect or be notified of the changes. The CI/CD tool will then execute a series of steps (often called a “pipeline”) to properly test these proposed changes to the infrastructure.

Inside the pipeline, tests are executed before any infrastructure changes are made, to validate their potential for success and any impact they may cause. Simple tests are commonly used to validate (or “lint”) that the changed files themselves are syntactically and logically valid. In addition, in a Network IaC pipeline, tests are often run with a tool such as Batfish which can analyze and understand network device configuration. These advanced tests allow you to validate potential changes will not affect an unexpected element of your network. They allow you to, in advance of touching the network itself, be confident that these changes will not cause adverse impact or unintended security policy changes. Pass or fail, the status of these tests are reported back to Git for display, or can be passed to a chat platform such as Slack.

If the tests are successful, and in this example the changes are approved and merged in Git, the changes are then able to implemented via a Deployment Tool, such as Terraform or Ansible (or both), or even plain Python. This step does not have to happen immediately, and the pipeline in your CI/CD tool can easily be made to wait until a pre-determined change window to execute the pending changes. Once the pipeline is ready to deploy the changes or infrastructure itself, the Deployment Tool will deploy or configure elements of your infrastructure based upon the changes recorded, approved, and tested, from the Source of Truth.

And finally, tests are executed once again to determine the success of the deployment actions. If these tests fail, they can either rollback the executed changes, or alert an engineer that some sort of intervention is needed via a message in Slack.

Network Infrastructure as Code

When speaking specifically about bringing Infrastructure as Code into the NetDevOps world, there are two common types of use cases.

The first type is utilizing IaC to deploy virtual network infrastructure itself. This would include for example, automatically provisioning an AWS VPC to terminate VPNs for your organization or spinning up a virtual firewall appliance in ESX.

The second type is utilizing IaC to deploy configurations to your existing network infrastructure (including physical equipment). This could be keeping the list of your BGP peers in a file in Source Control, and then applying the appropriate configuration to the routers in your network when changes are made to this file.

Determining which of these two areas you wish to work on first will be up to you, although most commonly in enterprise networks we see the later pursued (configuration of physical equipment) as it is the largest opportunity to have an impact on day-to-day operations. Removing the need to manually configure VLANs, and simply making a change to a file under Source Control with a CI/CD tool doing the rest, is extremely attractive to many organizations.

Infrastructure as Code and You

If you are feeling a little dazed and confused by all the ways that you can potentially bring Infrastructure as Code principles into your network, you’re not alone. There are many websites, blogs, or YouTube videos that can take you through the next steps on your NetDevOps journey. Or, you could always drop an email to us here at Network to Code as this is our bread and butter, and we’d be more than happy to help you take the next steps.

-Brett


Appendix: Lay of the Land

This is a listing (in no specific order) of commonly used tools in each of pillar to help you begin to organize them in your mind. It is worth noting two things about the below list. First, this is by no means exhaustive and intended simply to help you orient yourself among the plethora of tools that exist in each pillar. Wikipedia has long lists of common Source Control softwareopen-source configuration management tools, and other Infrastructure as Code Tools if you wish to dive deeper.

Secondly, some tools (such as Github or GitLab) appear in multiple pillars below as they provide multiple areas of functionality. This has happened more often in the past few years as, for example, closer integrations of Source Control and CI/CD have become standard features. Nothing is written in stone that says simply because you utilize GitHub for Source Control, you also have to utilize it for CI/CD. Evaluate each tool based on its strengths as well as you and your organization’s experience/familiarity with it.

Source of Truth

Given that a Source of Truth in practice is usually aggregated from several places, I’ve broken it out below into sections for Source Control and for Systems of Record. The relevant Systems of Record in an enterprise environment are often CMDB/DCIM (Configuration Management Database/Data Center Infrastructure Management) tools, so those are covered below.

Source Control

While Git is, by far, the most commonly used Source Control system (with many different services and implementations as shown below), it is good to understand some of the other Source Control tools available as well.

System of Record

Frequently in the System of Record category, there will be multiple of these inside a large organization. Not all elements of the network infrastructure are represented in each system, and some may be syncing data between themselves. In addition, while a CMDB or a DCIM serve different purposes in an environment, there is overlap in the data they may have, and thus can fill some of the same role in an Infrastructure as Code deployment. Some large enterprises have even built their own DCIM or CMDB tools in house, and integration with those tools will vary widely.

CI/CD

There is no clear winner in the CI/CD pillar, so we would recommend learning if one of the below is in existing use inside your organization and attempt to leverage it for your purposes.

Deployment and Configuration Tools

This pillar is very diverse, as the Deployment and Configuration tool you choose largely depends upon your use cases. It can be driven by what type of infrastructure you’re wishing to deploy/configure, how you wish to configure it, or even existing familiarity with a given tool.

It is worth calling out that there are a series of Python tools/libraries that are commonly utilized (frequently in combination) for building custom configuration tools for network equipment as well:

Testing Tools and Frameworks

Testing can take on many varieties and flavors, but for Network Infrastructure as Code the tools you use largely fall into three camps.

First are tools that lint/validate the configuration or code files themselves statically. That means tools which examine the contents of each file and insure, for example that the file claiming to be YAML formatted, really is valid YAML.

Second are tools that spin up infrastructure to allow you to test a simulacrum of your network. These tools, commonly used for training and educational opportunities, were traditionally the main way network changes were validated before the third category appeared.

Third, and the most exciting, are tools that validate the logic of the configuration changes you are attempting to make. These tools will actually analyze the change you are making and it’s potential impact to other elements of your infrastructure.



ntc img
ntc img

Contact Us to Learn More

Share details about yourself & someone from our team will reach out to you ASAP!

NetDevOps Concepts – An Introduction

Blog Detail

As the networking industry moves to embrace NetDevOps, there are often many terms used that network practitioners are unfamiliar with. This can lead to many people feeling unsure about what role a new technology could play in their organization, or even being afraid to ask for clarity about a discussed concept. In fact, there are a few questions we see asked time and time again.

“What is CI/CD, why would it have a pipeline, and what does that have to do with my network?”

“What does IaC or SoT mean?”

Or even, “What is NetDevOps anyway and why should I care?”

In this series of blog posts, we will delve into NetDevOps in a way that ensures you have familiarity and a basic understanding of what NetDevOps is, as well as some of the key components. We will also talk briefly about how, and why, you might apply a some of these concepts to operating your network.

What is NetDevOps?

Many fantastic blog posts and presentations discussing what NetDevOps is as a philosophy exist, and I won’t revisit all of their points here. Suffice to say that NetDevOps brings key concepts from the DevOps movement, which we’ll talk about deeply in subsequent blog posts, and applies them to operating and building networks.

With the proper application of NetDevOps concepts, you no longer have to think about your network as static, rigid, and fragile. Instead, you can start to treat it as something flexible and responsive to your desires or business needs. Some examples of these concepts include:

  • Continuous Integration/Continuous Deployment (CI/CD)
  • Infrastructure as Code (IaC)
  • Source of Truth (SoT)
  • Minimum Viable Product (MVP)
  • ChatOps

As for seeing these concepts in action, let us say that you need to deploy a new site to your corporate VPN. Without a NetDevOps approach to managing your network, you could spend a week fighting by hand to build the proper IKE/ISAKMP settings for the tunnel and documenting the site in your systems, applying changes, and then testing to ensure everything is functional.

However, if you are using a few key NetDevOps concepts to manage your network, your process could look more like this:

  • Message new vpn site to @my_netdevops_bot in your chat application (Slack/MS Teams/Webex Teams)
  • Fill in the site name, equipment type, and other metadata as prompted by the bot.
  • @my_netdevops_bot uses that information to:
    • Create the site in your Source of Truth (SoT)
    • Merge a Jinja template with the relevant data from your SoT
    • Present you with the rendered configuration in chat application
  • Upon approval of the change, @my_netdevops_bot will connect to the devices, and deploy these configuration changes
  • @my_netdevops_bot then queries the network (or other systems such as monitoring systems) to determine if the change was successful and present you with confirmation in chat.
    • If the change failed for some reason, @my_netdevops_bot can then start to troubleshoot some basic things on your behalf and present that information to you as well.

This is not a far-fetched or cutting edge example, this is just one of the many ways in which we see the application of NetDevOps concepts on a daily basis across all types of organizations.

“But…”

Usually, about this point in the conversation, there is a “But…” lurking off in the wings. Some greatest hits include, “But my network is too old” or “But my network is too unique.” My personal favorites are, “But my network is too large/too small!” as if there was a mythical Goldilocks zone where these concepts apply. The list goes on, but for almost every exception raised, there is an answer. Most of these can be addressed by two main responses.

First, no one is suggesting that you go directly from zero to the scenario described above. Embracing a NetDevOps mentality and approach to your network operations is an iterative process. Applying just a few of these concepts (and not all of them) to a single small element of your network is the best way to begin your NetDevOps journey. Even small, simple steps can pay large dividends. If you are manually generating device configurations, start to look at building a templating system for your device configurations and keeping it as code in a Git repository. This first step of only generating the configurations, leaving the engineer to actually qualify and apply them, can pave the way for many other steps in the future. Even in and of itself, simple configuration generation from a template can provide time savings and operational wins by removing human error and ensuring there is a single standard configuration.

Secondly, no network is too special to take advantage of these concepts. Is your network very large and complicated? Is literally every single component unique? Pick a single place in your network to start implementing a Source of Truth (such as NetBox). Having the data in an easily accessible API and/or GUI, and in a known standard format, will show value immediately for any other concepts you wish to apply. Does your network lack coherent standards? Start to enforce them on a single item of configuration, such as the AAA configuration, via Infrastructure as Code principals. Ensuring that the AAA configuration on all devices is a known/expected value at all times is extremely valuable from an operational and security perspective. Your compliance auditors will thank you!

Each of the above strategies relies on the concept of a Minimum Viable Product. When you start to embrace NetDevOps concepts for operating your network, do not expect to solve all of your problems in the first try. Pick one straightforward problem to solve. Build your solutions and tooling to solve that problem, then begin using it in your day-to-day work. If it is successful, look at adapting your tools to solve additional problems. As described above, perhaps you tackle only the AAA configuration first. When that is fully managed in a Source of Truth, and as code instead of raw device configuration, you can expand to managing the SNMP configuration on all your devices as well. Next, you could tackle management ACLs to your devices or NTP and DNS settings, really it’s up to what makes sense in your network. In this way you will rapidly expand the portions of your network that are being managed via NetDevOps.

Next Steps

This is the first in a series of posts on NetDevOps concepts, and I highly recommend staying tuned for the subsequent posts where we dive into some of these concepts in greater detail. We’ll have use cases and examples for each of them, including how to tie these all together into a coherent network automation strategy in the end.


Conclusion

If you’re impatient, you can always reach out to info@networktocode.com for more information on our services and training to help you take the next steps on your NetDevOps journey.

-Brett



ntc img
ntc img

Contact Us to Learn More

Share details about yourself & someone from our team will reach out to you ASAP!