avatarTeri Radichel

Summarize

Configuration and Abstraction

Reduce your code base and improve code integrity

One of my post that may later become a book on Secure Code. Also one of my posts on Application Security and The Principle of Abstraction.

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

When you need to deploy code to multiple environments, do you find yourself manually making changes to code at the point of deployment? Do you need to rebuild containers or recompile libraries to deploy to production? When you write code to deploy infrastructure to cloud environments do you write separate code for each region (AWS), subscription (Azure), or project (GCP) for the same application or applications with similar infrastructure requirements? Do you have to make any modifications to your code when you deploy it or test it?

If you answered yes to any of the above, you have a potential security issue. First, you may have repetitive code. I already explained in another post how that can cause security problems.

Additionally, you have a situation where people are manually editing code. Any time someone has to change code, they could introduce an inadvertent or malicious change that causes a security problem. An analysis of data breaches in the UK showed that 88% of data breaches involved human error. You may remember a large AWS S3 outage in 2017. The company reported this was caused by human error. The more you can reduce the potential for human error the more you reduce your cybersecurity risk.

Once you write code in a development environment, it should not change again. When your QA team tests the code in their own environment, they should not have to change the code to deploy it. When they test the code they test not only the functionality of the code but the ability to deploy it without errors or alterations. When deployed to production the code should be the same exact code the developers wrote with no changes.

If you allow code to change after it leaves a development environment, how do you know the QA team has not altered it to introduce a security problem or a bug? If you allow the code to change as it gets deployed to production, how do you know that the code the QA team tested and verified is what actually runs in production? How do you know attackers have not inserted code as they did in the Solar Winds breach? The only way you can know for sure that what they tested is what is running in production is if you can verify the code hasn’t changed. If you have to change the code to deploy it, there’s no way you can know that for sure.

Abstraction for Configurations

If you find yourself changing your code manually when you deploy it, how do you fix it? Here we have another scenario where the concept of abstraction can help. You can abstract out the things that remain the same and separate out the things that change.

When you review code that requires changes in each environment, pull out the things that you have to manually edit into a configuration file, or better yet, a system that stores parameters in different environments.

For example, you may have a different server name, file path, or database name in development, QA, staging, and production environments. Those details change in each environment, but the code that functionally executes your application should remain consistent.

Rather than editing the code at the time of deployment, run the code with a parameter that indicates where the application should retrieve its configuration. When your team deploys the code, it should be able to read the parameters that change in each environment with the same exact code that ran in every other environment. No one should be able to touch or change the code the developers delivered.

Here are a few examples of how you can separate your configuration from your code to avoid changes when you deploy to different environments. I’ll probably have working code samples and more examples in the book but this should give you enough information to get started fixing your code if you have this problem.

Moving changing values to a configuration file

You could use a configuration file to allow an application to read in configuration. Let’s say that you are using a bash file to run an application on Linux. You could pass a configuration file in on the command line. Note that this is pseudo-code. It will not run as-is. I’ll probably flesh this out further in the actual book, but this gives you the concept for how to write code that does not require modification to deploy to different environments.

./run.sh config.txt

In your bash file, you may run an application like this where app.py is the application you want to run and config.txt contains the configuration values that are different in each environment.

#!/usr/bin/python3
app.py config.txt

In your app.py file you have some code that reads the configuration file and sets parameters with the values stored in the file:

config_file = [config file parameter passed in to application]
#attributes that change in each environment
attribute1 = None
attribute2 = None
with open(config_file, 'r') as input_file:
   for line in input_file:
        [read each line and set the corresponding attribute value]
[program uses attributes without having to edit the code]

Now you can execute the code in each environment without changing it. Instead, provide a config.txt file with the values specific to the environment where you deploy the code. Someone can edit a configuration file in one environment without knowing the values in another environment. That’s useful when an organization does not want all the developers and the QA team to know the values that are used in the production environment. As a developer, I didn’t want to know production information! That way I wouldn’t be blamed if secret values in production got exposed.

Parameters in cloud environments

When deploying code in cloud environments, you can write code once that deploys in other environments without modification. Once again, abstract out the code that remains the same in each environment. The code should be able to pull in the parameters it needs without modification.

Cloud environments typically provide something called pseudo parameters that allow you to retrieve information about the environment to which you are deploying. For example, let’s say you are trying to deploy to two different regions on AWS and you have a value in the code that requires the region name.

You can create a CloudFormation template that allows you to pass in the region name. The concept is the same as the last example where you can pass a file into an application.

Parameters:   
    RegionParameter:     
      Type: String     

Now execute the cloud formation and pass in the parameter. Let’s say the region name is us-west-2. You could use the AWS CLI, for example, to execute the template and pass in the region us-west-2 as shown below:

aws cloudformation create-stack --stack-name stack 
--template-body [your template] 
--parameters ParameterKey=RegionParameter,ParameterValue=us-west-2

Alternatively, you could use a pseudo parameter that sets the default value for the parameter. The value of AWS::Region will be the region where the code executes. When you execute the template in the us-west-2 region, the value of the RegionParameter will be us-west-2. When you execute the parameter in the us-east-2 region that region name will be the value of the RegionParameter. Now you have a template you can run in any region.

Parameters:   
    RegionParameter:     
      Type: String
      Default: !Ref "AWS::Region"

When you run code in different regions you may dynamically generate the name of a resource. The cloud environment may not allow you to use the same name in different regions. In that case, you can dynamically generate the name and make it unique by adding the region to the name. You can use a pseudo-parameter to get the current region name.

Those are just a few examples of how you can change your code to create a single template that runs in any cloud region.

AWS, Azure, and GCP have ways to retrieve information about the deployment environment:

By the way, you’re struggling to learn AWS CloudFormation I wrote a blog about that here:

Next steps

  • Find out where your deployments require manually altering code to deploy to different environments.
  • Refactor your code to abstract out the things that remain consistent between environments.
  • Move the code that changes to a configuration file or some other means of storing the changing parameters.**
  • Use environment or pseudo parameters in cloud environments where possible to prevent mistakes.
  • Test your deployments to ensure you can deploy to any environment without altering the code.

** I will explain how to do this securely in my next post.

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2022

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
Secure Code
Application Security
Appsec
Cybersecurity
Secure Programming
Recommended from ReadMedium