avatarTeri Radichel

Summarize

Managing Application Code

ACM.231 Creating a directory structure, abstracting out common code, and testing deployments

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

⚙️ Check out my series on Automating Cybersecurity Metrics | Code.

🔒 Related Stories: Secure Code | GitHub | Application Security

💻 Free Content on Jobs in Cybersecurity | ✉️ Sign up for the Email List

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Working though deployment of resources for a static website hosted in S3.

In the last post, I created a test script to test a cross-account role that I’m going to use to deploy static websites in a remote account.

I started jumping into creating the next resource for my static websites but then I realized I had to backup a step and explain my environment structure a bit more and why I’m going it this way. I’m creating this on the fly and it may change over the course of the series. I’ve managed code this way before but always trying out new ideas.

Infrastructure Resources for Static Websites

There are a number of infrastructure components for static web sites that can use a common CloudFormation template. There’s no sense in writing a separate, repetitive template for every web site for all these things:

I’m going to write that common code and put it in my existing framework code.

Example: DNS Hosted Zone

The next resource I’m going to create is called a Route 53 DNS Hosted Zone. Stay tuned for that but essentially I’m going to create a new folder in my codebase for DNS.

For now I’ll add the usual in the DNS directory:

  • A cfn folder with a hosted zone CloudFormation template.
  • A functions script with Route 53 related functions.

What I’m leaving out is the deploy.sh script.

Application Specific Code

The specific applications and web sites I’m deploying are not relevant to everyone using a common framework. I’m going to separate those out and put them elsewhere.

In other words, I’m going to separate the application-specific code from the generic infrastructure code. The infrastructure code can be very common across applications. The application code needs to all work together and is specific to a particular application.

For example, I don’t want to check in all my static website code (html pages and images) for 2ndSightLab.com to my framework and you probably don’t want or need that code either.

The configuration of the hosted zone includes a domain name specific to the web site I’m deploying. I don’t want to put the domain names in my framework repository. However, I may be able to create a generic script with all the components required for a static website and pull them in from a configuration file or repository. TBD.

A repository for each site

As I wrote about each site has it’s own GitHub repository and I showed you how to automate creation of those repositories here:

Each website hosted on a separate domain will have it’s own repository. You could also put all the static websites in one repository with separate folders and change the code around accordingly if you are trying to limit repositories, but that will be more complicated to manage.

Leveraging Shared Code

How can I call use the hosted zone template and functions in the web site deploy script? I explained how to do that here and will further demonstrate as I deploy a static site.

I’ll grab the code from the web site repository and the framework in two folders in the same directory on my machine. I’ll source and use the files the same way I do within the directory itself.

I’m going to create a generic function to create a static websites:

/Apps/StaticWebsite/deploy_static_website.sh

This script can interact with site specific code or vice versa in the directories on the same machine.

In a future post I show you how I turn my repository creation script into a function to create a website in that script. I can also use the assume role functions I wrote about earlier to assume a cross-account role and deploy the resources required by the static site.

Different Versions and Environments

There are different ways to use GitHub. One way is to create a single repository and use branches. That’s the way most people use GitHub I think. I’m going to show you another option.

I’m going to create separate repositories for two environments for right now — dev and prod. I’ll right and test code and check it into the dev repository. When I’m ready to deploy that to production, I’m going to migrate it to the production repository and check it in. I’ve done this before and in fact, as mentioned, I used two different source code repository services that both leverage git for some class code I wrote.

This approach gives you the ability to better control separation of duties, though you can probably also do the same with branches. I find branches to be more complicated but you can certainly do that.

Enterprise environments

When I had a QA team we had the following repositories:

Dev > QA > Staging > Prod

Each developer could write and check in code to the dev repository. They could build and test their own components separately without affecting the rest of the team the way we designed our micro-service environment. Dev leads would manage deployments merged into the integrated team deployment. They also reviewed the code before pushing it to QA. When the dev lead was ready the code would get pushed from the Dev repository to the QA repository.

The QA team tested what was in QA. When that was ready it could be pushed to staging. Staging is supposed to match production and that’s the point you are testing your deploying — not before and hopefully not on the way to prod!

Once customers, beta testers, and a product manager approved the changes in the staging environment, the production operations team would deploy the code to production. The production operations team and processes should have no ability to change the code — only deploy it. That approach would have prevented the Solar Winds breach as I wrote about in this post that explains how to set up different access tokens with differnet permissions in GitHub.

A simple start — dev and prod

I don’t need all that just yet for me, myself, and I.

For my initial testing, I’m going to take a domain for a web site that already exists:

rainierrhododendrons.com

I’m going to create a repository named:

dev.rainierrhododendrons.com

I’m going to upload the static content to that repository. I wrote about syncing files in one of my posts on S3:

The concept is the same, but I’m going to copy the files into the repository directory and then check the code into my new GitHub repo.

So something like this pseudocode:

#run the script to create the repository in GitHub using the prior post

#move into the directory for the repository
cd ~/code/dev.rainierrhododendrons.com

#copy the files into the repository directory
aws s3 sync s3://rainierrhododenrons.com .

#check in the code
git add .
git commit -m "Adding static content"
git push

Once my code is in the repository I can use it to automate the deployment of a static website pretty easily.

I’ll create another repo called rainierrhododendrons.com. I can easily write a script to clone my dev directory less the git metadata files into my production repository directory and check it in.

Abstraction

As you can imagine, we can abstract out all the things that are the same between the two environments and create one script to deploy to both environments.

That will allow us to test our deployments not just functional code and follow the DRY principal.

I’ll leverage the same AWS CloudFormation template or the S3 bucket for each site, for example. I’ll pass in parameters for the things that vary. I can store those parameters with the code or in a separate repository if there’s something I don’t want developers managing. In this case, it’s just me so I’ll keep the configuration in each repository with the site it belongs to, less secrets.

Environment Specific Configurations and Secrets

Repeat after me:

I will NOT check secrets and sensitive data into GitHub.

Because the configurations will vary from site to site, I’ll want to have a way to populate the values that change for each environment in such a way that I won’t have to touch or change the code at the time of deployment. I want to make sure the code can be tested and the same across environments — independent of the configuration values.

In addition, there are values that I don’t want people from different environments changing. For example, developers should not have permission to change things in the QA environment. Neither dev nor QA should be able to change production configurations in production.

There are a lot of tools that can handle these types of problems or we can think of our own solution. I have something in mind that won’t cost me as much money as an additional tool, but need to test it out. More on that last point later.

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2023

About Teri Radichel:
~~~~~~~~~~~~~~~~~~~~
⭐️ Author: Cybersecurity Books
⭐️ Presentations: Presentations by Teri Radichel
⭐️ Recognition: SANS Award, AWS Security Hero, IANS Faculty
⭐️ Certifications: SANS ~ GSE 240
⭐️ Education: BA Business, Master of Software Engineering, Master of Infosec
⭐️ Company: Penetration Tests, Assessments, Phone Consulting ~ 2nd Sight Lab
Need Help With Cybersecurity, Cloud, or Application Security?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
🔒 Request a penetration test or security assessment
🔒 Schedule a consulting call
🔒 Cybersecurity Speaker for Presentation
Follow for more stories like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
❤️ Sign Up my Medium Email List
❤️ Twitter: @teriradichel
❤️ LinkedIn: https://www.linkedin.com/in/teriradichel
❤️ Mastodon: @teriradichel@infosec.exchange
❤️ Facebook: 2nd Sight Lab
❤️ YouTube: @2ndsightlab
Github
Appsec
DevOps
Security
Code
Recommended from ReadMedium