Skip to content

DevSecOps Architecture

Griffin Kiesecker edited this page Nov 3, 2024 · 17 revisions

DevSecOps Architecture

General Overview

The DevOps repo is where I create all of the resources needed to interlink my three repos (software, ami, infrastructure).

One of the most important things that the CDK does in my DevOps repo is this: it creates codecommit repos for the 3 repos I just mentioned. The reason for using codecommit is because it plays very nicely with both IAM Identity Center as well as EC2 Instance Profiles. Both play a critical role in my infrastructure and specifically the DevOps architecture I made.

Codepipeline and Codebuild are used to deploy all of the resources I need to either build the software, make an ami, or deploy my finalized infrastructure.

The pipeline structure is simple and works a lots like falling dominoes: each pipeline finishes and creates an artifact so sort. The creation of that artifact then triggers the next pipeline. Here is a picture describing the overall architecture of what the devops repo creates, and how the pipelines interlink:

DEVOPS WORKFLOW DIAGRAM

Implementation Overview

config.json specifications

{
    "stack_base_name": "TekPossible-Stratagem",
    "stack_name": "TekPossible-Stratagem-DevOps",
    "region": "us-east-2",
    "infrastructure_site_branches": [
        "main",
        "qa",
        "production"
    ],
    "repos": [
       {
            "name": "tekpossible-gem-ami",
            "desc": "TekPossible STRATAGEM Image Repository",
            "type": "ami",
            "email_poc": "image-cm@tekpossible.com"
        },
        {
            "name": "tekpossible-gem-software",
            "desc": "TekPossible STRATAGEM Software Repository",
            "type": "software",
            "email_poc": "software-gem@tekpossible.com"
        },
        {
            "name": "tekpossible-gem-infrastructure",
            "desc": "TekPossible STRATAGEM Infrastructure Repository",
            "type": "infrastructure",
            "email_poc": "infrastructure-gem@tekpossible.com"
        },
        {
            "name": "tekpossible-gem-devops-infrastructure",
            "desc": "TekPossible STRATAGEM DevOps Infrastructure Repository",
            "type": "devops",
            "email_poc": "devops-gem@tekpossible.com"
        }
    ],
    "ami_source_image": "ami-078cbc4c2d057c244"
}

Above you is an example config.json file for the DevOps repo. There are many fields, and here is a list of each one and what it means to the DevOps CDK Stack:

  • stack_base_name -> This is the CDK Stack base name. This field needs to be the across all of the CDK repo and their config.json in the tekpossible-ha project. This variable is the prefix that is the same across all of the CDK deployed stacks. The reason for this is so that I can guess the names of the deployed stacks, as well as create resources that might be created by one stack, but are not specific to just it.

  • stack_name -> This is the name of your DevOps stack. It must include the stack_base_name and needs to be completely unique in your AWS account.

  • region -> This is the region where you want to deploy the tekpossible ha project. At the moment, all of the components of tekpossible ha must be in the same region. That will hopefully change in the future, when I change my AMI automation.

  • infrastructure_site_branches -> on the repos in the repos struct, these are the branches for which CI/CD pipelines are created. When I wrote this, I used main as my development environment, qa as my green (or test) environment, and production as my blue (or ops) environment. Only put branches in this list that you want to spin off a complete infrastructure from. Eventually, I hope to create user specific branches here too, but have not completed the development for that yet.

  • repos -> A list of repos that you want to create in codecommit for the tekpossible-ha project. Each repo in the list of repos contains a few fields. name is the aws name of the repo - it cannot contain spaces. desc is the human readable description of the repo. email_poc is the email point of contact for CI/CD pipeline approvals. Finally, type is the type of repo that you are going to create. There are 4 types of repos that I created and the CDK automation I wrote depends on:

    • 'software' -> This is a software repo. This is for custom software that you want to build/deploy to your custom AMI
    • 'ami' -> This is the repo housing OS compliance and configuration information. Things such as bash and ansible should go here.
    • 'infrastructure' -> This is the repo housing the code to actually deploy EC2 instances and what is considered the real infrastructure that tekpossible ha deploys. It is a CDK repo that will include some bash scripts for instance startup.
    • 'devops' -> This is this repo's type. It mainly includes all of the pipeline code and miscellaneous components that hook it all together.

    At the moment, there can only be one (thanks Highlander) type of each repo. However, you can create your own buildspecs in codebuild to pull in other repos if you need to. Think of these repos as each being the cornerstone repos that actually need pipelines to deploy attached to them.

  • ami_source_image -> This is the AMI source image that the EC2 Image Builder pipeline uses as its source. At the moment, this needs to be a x86-64 based RHEL 9.x image. This is because the AMI automation I wrote depends on it being RHEL 9.x. See the AMI specific page for info on EC2 Image Builder and why RHEL.

DevOpsStack Constructor

export class DevopsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, config: any, props?: cdk.StackProps) {
    super(scope, id, props);

  // Creation of repos is needed first so that the pipelines can trigger eachother
    create_repos(this, config.region, config);

  // Creation of transitional s3 bucket to link the pipelines
    create_s3_transition_bucket(this, config.region, config);

  // The following functions create the overall development workflow
  // Software Pipeline -> Image Pipeline -> Infrastructure Pipeline
    create_software_workflow(this, config.region, config);

  // Create AMI Repo and Pipeline
    create_image_workflow(this, config.region, config);

  // Create Infrastructure Repo and Pipeline
    create_infrastructure_workflow(this, config.region, config);

  }
}

I broke up the constructor into a few functions:

  1. create_repos -> This function creates the codecommit repos specified in config.json. It also creates SSM Parameters for each repo's clone url that we will use. For our DevOps infrastructure, we will use the GRC clone url due to its native integration with IAM.
  2. create_s3_transition_bucket -> In order to link the output of the software repo, and the EC2 Image Builder's need for the software TAR file, I needed to create a global s3 bucket. This function does just that, and it also creates an SSM parameter so that I can access the name of the bucket from my AMI repo.
  3. create_software_workflow -> This is the software ci/cd pipeline function. Though the CDK code for the pipeline is held here in the devops repo, I will discuss it in the software architecture page.
  4. create_image_workflow -> With this function I create 2 pipelines an codepipeline CI/CD pipeline, and a EC2 Image Builder pipeline that is triggered by the CI/CD pipeline. These pipelines will be discussed more in the AMI automation page.
  5. create_infrastructure_workflow -> This a standard CI/CD pipeline but it has 2 codebuild steps. The first one is for linting and the second one is to use the cdk command to deploy the infrastructure. More info about this pipeline as well as the infrastructure that is deployed can seen in the infrastructure architecture page.

One thing that these repos have in common is that they are triggered via pushes to their codecommit repo. When there is a chain reaction for the CI/CD pipeline, they are autotrigged via cloning down the repo of the next ci/cd pipeline and committing either the location of the external file, or the id of the external object. This is important to understand before reading about the specific pipelines as they rely heavily on codecommit as their trigger.