<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Csaba Boros</title>
    <description>The latest articles on Forem by Csaba Boros (@boroscsaba).</description>
    <link>https://forem.com/boroscsaba</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F911094%2Fe2a6ad96-fe93-4e0d-8f05-f517e06f470b.jpeg</url>
      <title>Forem: Csaba Boros</title>
      <link>https://forem.com/boroscsaba</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/boroscsaba"/>
    <language>en</language>
    <item>
      <title>Simple way to play around with terraform locally without any cloud account</title>
      <dc:creator>Csaba Boros</dc:creator>
      <pubDate>Sat, 23 Dec 2023 11:23:59 +0000</pubDate>
      <link>https://forem.com/boroscsaba/simple-way-to-play-around-with-terraform-locally-without-any-cloud-account-12k5</link>
      <guid>https://forem.com/boroscsaba/simple-way-to-play-around-with-terraform-locally-without-any-cloud-account-12k5</guid>
      <description>&lt;p&gt;I don't want to live under a bridge or on the streets. For this reason when I was learning terraform I was stressed about messing up something and getting a huge bill from aws or gcp. &lt;br&gt;
Fortunately I found an easy way to start playing around with terraform locally without using any cloud account or any complicated local kubernetes setup.&lt;/p&gt;

&lt;p&gt;As you probably already know terraform is a tool that lets you provision and manage infrastructure resources. Things like virtual machines, EC2 instances, IAM users and so on... &lt;br&gt;
Basically terraform is able to create and manage any type of resources if there is a Provider written for it. There are separate providers for aws, gcp, digital ocean, you name it. You can browse the list of available Providers or you can even write your own. Here is the official &lt;a href="https://registry.terraform.io/browse/providers" rel="noopener noreferrer"&gt;list of providers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this tutorial we will be using the &lt;a href="https://registry.terraform.io/providers/hashicorp/local/latest" rel="noopener noreferrer"&gt;local&lt;/a&gt; Provider as this can provision local files without needing any other setup. &lt;/p&gt;

&lt;h2&gt;
  
  
  Install terraform
&lt;/h2&gt;

&lt;p&gt;Step 0 is to configure terraform on your machine. This is very easy to do, you just need to download a binary and set up its path in the path system variable. &lt;br&gt;
Download and unzip the terraform binary from the &lt;a href="https://developer.hashicorp.com/terraform/install" rel="noopener noreferrer"&gt;terraform website&lt;/a&gt;. I will place it in a newly created C:/terraform folder.&lt;br&gt;
Next step is to add the location of the terraform.exe file to your PATH system variable. &lt;br&gt;
Go to System properties:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fortm71tqn9cvg746jqcj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fortm71tqn9cvg746jqcj.png" alt="System properties"&gt;&lt;/a&gt;&lt;br&gt;
And select "Environment Variables..."&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb16rtbb56kk9bl7lki2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb16rtbb56kk9bl7lki2o.png" alt="Environment properties"&gt;&lt;/a&gt;&lt;br&gt;
In the "System variables" section find the "Path" variable and click "Edit..."&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwnj9yk62z0oe6jalcwj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flwnj9yk62z0oe6jalcwj.png" alt="Add terraform env variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Write some terraform
&lt;/h2&gt;

&lt;p&gt;Open up vs code (or any other IDE) in an empty folder and create a new file and name it main.tf&lt;br&gt;
First we need to specify the providers we will be using and then we can specify the resources we want to create. Here is an example terraform file that will create a hello.txt file with the content of "hello world".&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

terraform {
    required_providers {
      local = {
        source = "hashicorp/local"
      }
    }
}

resource "local_file" "hello" {
    content = "hello world"
    filename = "hello.txt"
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It's always a good idea to check the &lt;a href="https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file" rel="noopener noreferrer"&gt;documentation of the provider&lt;/a&gt; as it will tell us what resources it can create and what are the options we can set.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26p1f7ksuj4j59xg3o7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26p1f7ksuj4j59xg3o7k.png" alt="terraform docs"&gt;&lt;/a&gt;&lt;br&gt;
As you can see the local provider has a resource called local file and it has a required filename property. Optionally we can also specify the content of the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform commands
&lt;/h2&gt;

&lt;p&gt;Open a new terminal and run &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

terraform init


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will Prepare your working directory and download all the necessary files for the provider.&lt;br&gt;
Next run &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

terraform validate


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This command will validate the syntax of your code.&lt;br&gt;
And now the fun part, let's run &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

terraform plan


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The plan command will output the list of changes that need to be made to reach the infrastructure described in your code. In this case the plan should be to create one new file.&lt;br&gt;
And now let's run&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

terraform apply 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The apply command will persist the planned changes. In this case it will create the file. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcy9d8iivrkz7k46as7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqcy9d8iivrkz7k46as7y.png" alt="terraform file"&gt;&lt;/a&gt;&lt;br&gt;
You can remove the file by running the destroy command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

terraform destroy


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now you can play around with it and see what happens if you modify your code and plan and apply it again or what happens if you modify the file manually. Have fun!&lt;/p&gt;

&lt;p&gt;This tutorial is also available on youtube: &lt;a href="https://www.youtube.com/watch?v=nb6onGm970k" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=nb6onGm970k&lt;/a&gt;&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>iac</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Encryption at rest using EF</title>
      <dc:creator>Csaba Boros</dc:creator>
      <pubDate>Sat, 15 Jul 2023 12:28:43 +0000</pubDate>
      <link>https://forem.com/boroscsaba/encryption-at-rest-using-ef-4mgf</link>
      <guid>https://forem.com/boroscsaba/encryption-at-rest-using-ef-4mgf</guid>
      <description>&lt;p&gt;Encryption at rest can come in handy when we have some sensitive data that we need to store in our database and we don't want to store it in plain text for everyone to see.&lt;/p&gt;

&lt;p&gt;In my case I needed to store some API keys in the database. The keys are inputted by the app users and the app later uses these keys for accessing some external services.&lt;/p&gt;

&lt;p&gt;In this tutorial I will show you a seamless way to use encryption at rest in your .NET application using EF &lt;a href="https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions"&gt;value converters&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it will work
&lt;/h2&gt;

&lt;p&gt;First we will create a ValueConverter that encrypts values on write and decrypts on read. We will also create an attribute, EncryptedAttribute, and apply the value converter to each of the properties that has the EncryptedAttribute.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hlPj8-W9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mu2uy8z7s5xg5jvd0eig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hlPj8-W9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mu2uy8z7s5xg5jvd0eig.png" alt="Image description" width="405" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The value converter class
&lt;/h3&gt;

&lt;p&gt;We will need a string-string value converter that can encrypt on write and decrypt on read. For this we will use AES encryption and we will need an encryption key. This key is a simple base64 string but we need to store it securely (in Azure Key Vault for example). I won't go in detail here, but we well also need a unique IV (initialization vector) key that will basically ensure that we always get different ciphers even if the input string is the same. Because the IV value is also needed when we decrypt the data we will just append the IV value to the cipher and store it in the database as part of the encrypted value. Here is the source code of my value converter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using System.Security.Cryptography;
using System.Text;

namespace EncryptionAtRest.Database.Encryption
{
  public class EncryptedConverter : ValueConverter&amp;lt;string, string&amp;gt;
  {

    public EncryptedConverter(string encryptionSecretKey)
    : base(
        v =&amp;gt; Encrypt(v, encryptionSecretKey),
        v =&amp;gt; Decrypt(v, encryptionSecretKey))
    { }

    private static string Encrypt(string inputString, string encryptionSecretKey)
    {
      using var aes = Aes.Create();
      using var encryptor = aes.CreateEncryptor(Encoding.UTF8.GetBytes(encryptionSecretKey), aes.IV);
      using var memoryStream = new MemoryStream();
      using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
      using (var streamWriter = new StreamWriter(cryptoStream))
      {
        streamWriter.Write(inputString);
      }

      var cipher = memoryStream.ToArray();
      // append the IV to the start of the cipher
      var result = new byte[aes.IV.Length + cipher.Length];
      Buffer.BlockCopy(aes.IV, 0, result, 0, aes.IV.Length);
      Buffer.BlockCopy(cipher, 0, result, aes.IV.Length, cipher.Length);

      return Convert.ToBase64String(result);
    }

    private static string Decrypt(string cipherText, string encryptionSecretKey)
    {
      using var aes = Aes.Create();

      var cipherByteArray = Convert.FromBase64String(cipherText);
      var iv = new byte[aes.IV.Length];
      var cipher = new byte[cipherByteArray.Length - aes.IV.Length];
      // get the IV from the start of the cipher
      Buffer.BlockCopy(cipherByteArray, 0, iv, 0, iv.Length);
      Buffer.BlockCopy(cipherByteArray, iv.Length, cipher, 0, cipher.Length);

      using var decryptor = aes.CreateDecryptor(Encoding.UTF8.GetBytes(encryptionSecretKey), iv);
      using var memoryStream = new MemoryStream(cipher);
      using var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
      using var streamReader = new StreamReader(cryptoStream);

      return streamReader.ReadToEnd();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Encrypted attribute
&lt;/h3&gt;

&lt;p&gt;We will create an attribute and write some logic to apply the converter to the properties that use this attribute.&lt;br&gt;
The source code for the attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class EncryptedAttribute : Attribute
{
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is the code that will apply the converter based on the attribute. I will place this static method inside my converter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static void Apply(ModelBuilder builder, string encryptionSecretKey)
{
    var entityTypes = builder.Model.GetEntityTypes();
    var properties = entityTypes.SelectMany(entity =&amp;gt; entity.GetProperties());

    foreach (var property in properties)
    {
        var attributes = property.PropertyInfo?.GetCustomAttributes(typeof(EncryptedAttribute), true);
        if (attributes != null &amp;amp;&amp;amp; attributes.Any())
        {
            property.SetValueConverter(new EncryptedConverter(encryptionSecretKey));
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the final step is to call the EncryptedConverter.Apply function from the OnModelCreating method of our db context:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using EncryptionAtRest.Database.Encryption;
using EncryptionAtRest.Database.Models;
using Microsoft.EntityFrameworkCore;

namespace EncryptionAtRest.Database
{
  public class AppDbContext : DbContext
  {
    public DbSet&amp;lt;Api&amp;gt; Apis { get; set; } = null!;
    private readonly string _encryptionSecretKey;

    public AppDbContext(string connectionString, string encryptionSecretKey)
      : base(new DbContextOptionsBuilder().UseNpgsql(connectionString).Options)
    {
      _encryptionSecretKey = encryptionSecretKey ?? throw new ArgumentNullException(nameof(encryptionSecretKey));
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
      base.OnModelCreating(modelBuilder);
      EncryptedConverter.Apply(modelBuilder, _encryptionSecretKey);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ready to go
&lt;/h3&gt;

&lt;p&gt;Now we just need to add the [Encrypted] attribute to the properties we want to store in an encrypted form. Your DbContext will work as usually, you can write and read your plain text properties but in the underlaying database table the data will be encrypted. &lt;/p&gt;

&lt;p&gt;You can also find the source code and a working example in this repository: &lt;a href="https://github.com/boros-csaba/encryption-at-rest-with-property-attribute"&gt;https://github.com/boros-csaba/encryption-at-rest-with-property-attribute&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Architecture of my portfolio website</title>
      <dc:creator>Csaba Boros</dc:creator>
      <pubDate>Sun, 19 Mar 2023 12:22:39 +0000</pubDate>
      <link>https://forem.com/boroscsaba/architecture-of-my-portfolio-website-mdg</link>
      <guid>https://forem.com/boroscsaba/architecture-of-my-portfolio-website-mdg</guid>
      <description>&lt;p&gt;Initially I just created a simple static HTML and CSS page with some images to serve as my portfolio page - no frameworks, (almost) no javascript - why over complicate it?&lt;br&gt;
After some time I decided that I would also write a few blog posts and tutorials on my portfolio website, but again, I didn't want to over engineer my website.&lt;br&gt;
At first I thought that maybe I would just copy and paste a new page for each article.&lt;br&gt;
This sounds stupid but if you consider that I will only write about one article a month and I will not redesign my site too often, this use-case doesn't really justify the overhead of a back-end and database with more complicated and pricier hosting...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VzDyaI_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0d0tehv5qb942j3e494.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VzDyaI_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a0d0tehv5qb942j3e494.jpg" alt="Image description" width="700" height="376"&gt;&lt;/a&gt;&lt;br&gt;
But you wouldn't hire me if I did this!&lt;br&gt;
So here is what I did instead:&lt;/p&gt;
&lt;h2&gt;
  
  
  11ty
&lt;/h2&gt;

&lt;p&gt;I converted my website to be compatible with 11ty. 11ty is a static site generate and it can generate static pages from template files. Basically I just had to configure a few things and create a nunjucks template file for my articles. I created a separate file for each of my articles with only the content of the of the post and some metadata for the nunjucks template. Now my website is still just a static site but the design and structure of the article pages is managed from a single template file.&lt;/p&gt;
&lt;h2&gt;
  
  
  Amazon S3
&lt;/h2&gt;

&lt;p&gt;The website is hosted in an Amazon S3 bucket. For technical reason there are actually two buckets. One contains the actual website file the other bucket just points to the first one. This is needed to support both the www and non-www version of the site.&lt;/p&gt;
&lt;h2&gt;
  
  
  Amazon CloudFront
&lt;/h2&gt;

&lt;p&gt;The S3 bucket is exposed through a CloudFront distribution. This makes the website load faster and also makes it possible to set up HTTPS.&lt;/p&gt;
&lt;h2&gt;
  
  
  AWS Certificate Manager
&lt;/h2&gt;

&lt;p&gt;The certificate for HTTPS is provided by AWS Certificate Manager. The certificate is free and is easy to set up with CloudFront.&lt;/p&gt;
&lt;h2&gt;
  
  
  Amazon Route 53
&lt;/h2&gt;

&lt;p&gt;I've bought my domain from a different registrar but I've set up my domain to use the name servers from my Route53 hosted zone. Using Route53 makes it easy to point the domain to the CloudFront distribution.&lt;/p&gt;
&lt;h2&gt;
  
  
  Github Actions
&lt;/h2&gt;

&lt;p&gt;Because I didn't want to manually upload my website to S3 every time I make a change or write a new article I've set up a pipeline to run the 11ty build and upload the website to S3 every time there is a commit to the master branch.&lt;br&gt;
Here is the yml file that does all this magic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;on:
  push:
    branches:
      - master

jobs:
  deploy:
    name: Deploy to S3
    runs-on: ubuntu-latest
    steps:

      - name: Checkout code
        uses: actions/checkout@v3

      - name: Install packages
        run: npm ci

      - name: Build
        run: npm run build

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${% raw %}{{ secrets.AWS_ACCESS_KEY_ID }}{% endraw %}
          aws-secret-access-key: ${% raw %}{{ secrets.AWS_SECRET_ACCESS_KEY }}{% endraw %}
          aws-region: us-west-1

      - name: Deploy to S3
        run: aws s3 sync ./dist s3://www.boroscsaba.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AWS credentials are stored as secrets in the repository settings.&lt;/p&gt;

&lt;p&gt;Your feedback is welcome! Please let me know if you think there is something important that should be included in this post or if you find anything wrong!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>s3</category>
      <category>ym</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>SSL Certificates - an easy to understand guide</title>
      <dc:creator>Csaba Boros</dc:creator>
      <pubDate>Sat, 24 Dec 2022 15:39:46 +0000</pubDate>
      <link>https://forem.com/boroscsaba/ssl-certificates-an-easy-to-understand-guide-1g2a</link>
      <guid>https://forem.com/boroscsaba/ssl-certificates-an-easy-to-understand-guide-1g2a</guid>
      <description>&lt;p&gt;As with any technology, I think it's very important that first we understand the problem that this technology is trying to solve. Let's try to understand the problem through an example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem with sending messages in plain text
&lt;/h2&gt;

&lt;p&gt;We are operating a website where we are selling some fancy coffee. For completing purchases we need payment information from our customers. Our customer, Bob, is sitting in a coffee shop and is trying to buy our newest product on sale. He just connected his laptop to a shady public Wi-Fi that is controlled by a hacker who can read the traffic that goes through this network. If we are sending the payment information in plain text the hacker is able to intercept the traffic and can easily read the payment information that is sent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encryption to the rescue
&lt;/h2&gt;

&lt;p&gt;(Encryption is a very big topic on its own and I am over simplifying things in this section, but this is enough for us to understand the big picture.) &lt;/p&gt;

&lt;p&gt;The simplest and quickest form of encryption that we can use is symmetric encryption. In this case there is a single key that can both encrypt (lock) and decrypt (unlock) messages.&lt;br&gt;
In our story Bobs laptop can generate a random key and send it to our website. After both the website and Bobs laptop agreed on this shared key all the following communication can be encrypted with it and there would be no more plain text messages to capture.&lt;/p&gt;

&lt;p&gt;BUT! What if the hacker also intercepted Bobs first message, the one that contained the secret key? In this case the hacker would also know the key and would be able to decrypt the messages.&lt;/p&gt;
&lt;h2&gt;
  
  
  Asymmetric encryption
&lt;/h2&gt;

&lt;p&gt;When using asymmetric encryption we have a pair of keys - a private and a public key. If something is encrypted with one of the keys it can only be decrypted with the other one and vice versa. &lt;br&gt;
The beauty of this setup is that the website server can share its public key freely. By doing this the clients can encrypt messages using the public key of the website and be sure that only the website can read the message.&lt;/p&gt;

&lt;p&gt;In our example Bobs browser would not send the symmetric key it generated in plain text, but instead it would encrypt it using the websites public key. Because this messages can only be decrypted by using the private key we can be sure that only the website can read this message.&lt;/p&gt;

&lt;p&gt;So to recap: The client (Bobs browser) generates a (symmetric) key. Encrypts it using the public key of the web server and sends it. The web server can decrypt the message using its private key. Now both the web server and the client have the key that will be used for further communication.&lt;/p&gt;

&lt;p&gt;And finally we can send those credit card information... BUT! What if we are dealing with a really skilled hacker?&lt;/p&gt;
&lt;h2&gt;
  
  
  Man-in-the-Middle Attack
&lt;/h2&gt;

&lt;p&gt;Our setup is still vulnerable. The problem is that a skilled hacker that controls the Wi-Fi network could intercept all the messages from the client and impersonate the web server. In this case the hacker could send its own public key to the client, acting as the real website. The hacker can act as a middle-man, forwarding the content between the client and the original website. In this case the client would have no way to know that he is not talking with the real website.&lt;br&gt;
Since the public key is just a very big random number it doesn't carry any more information about its source. When the client receives a public key it cannot be sure that this key really belongs to the website he is trying to connect to.&lt;br&gt;
SSL Certificates were invented to solve this problem. &lt;/p&gt;
&lt;h2&gt;
  
  
  SSL Certificates
&lt;/h2&gt;

&lt;p&gt;An SSL Certificate in its most basic form works just like an identity card. The ID card certifies that the information from the ID card belongs to the person from the photo. You trust the information on an identity card because you trust the issuer of the card, the government. &lt;br&gt;
A SSL Certificate certifies that a given public key belongs to a given domain or IP address and it is signed by a third party (CA - Certificate Authority) organization. If you trust the authority who signed it, then you can trust the certificate.&lt;/p&gt;

&lt;p&gt;These formal definitions like, "certificate" and "authority" may seem overwhelming, bug there is nothing complicated about SSL Certificates. A certificate is just a piece of data with a standard format (X.509 is the name of the standard).&lt;/p&gt;
&lt;h3&gt;
  
  
  What is a certificate?
&lt;/h3&gt;

&lt;p&gt;The most important information of a certificate are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validity (the period during which the certificate is vaid)&lt;/li&gt;
&lt;li&gt;domain name of the subject (CN)&lt;/li&gt;
&lt;li&gt;more information about the subject (company name, county, etc)&lt;/li&gt;
&lt;li&gt;public key of the subject&lt;/li&gt;
&lt;li&gt;information about the issuer of the certificate (CA)&lt;/li&gt;
&lt;li&gt;signature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The certificate is sent to the client in base 64 encoded format and it looks similar to the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----BEGIN CERTIFICATE-----
MIICKzCCAZSgAwIBAgIBAzANBgkqhkiG9w0BAQQFADA3MQswCQYDVQQGEwJVUzER
MA8GA1UEChMITmV0c2NhcGUxFTATBgNVBAsTDFN1cHJpeWEncyBDQTAeFw05NzEw
MTgwMTM2MjVaFw05OTEwMTgwMTM2MjVaMEgxCzAJBgNVBAYTAlVTMREwDwYDVQQK
EwhOZXRzY2FwZTENMAsGA1UECxMEUHViczEXMBUGA1UEAxMOU3Vwcml5YSBTaGV0
dHkwgZ8wDQYJKoZIhvcNAQEFBQADgY0AMIGJAoGBAMr6eZiPGfjX3uRJgEjmKiqG
7SdATYazBcABu1AVyd7chRkiQ31FbXFOGD3wNktbf6hRo6EAmM5/R1AskzZ8AW7L
iQZBcrXpc0k4du+2Q6xJu2MPm/8WKuMOnTuvzpo+SGXelmHVChEqooCwfdiZywyZ
NMmrJgaoMa2MS6pUkfQVAgMBAAGjNjA0MBEGCWCGSAGG+EIBAQQEAwIAgDAfBgNV
HSMEGDAWgBTy8gZZkBhHUfWJM1oxeuZc+zYmyTANBgkqhkiG9w0BAQQFAAOBgQBt
I6/z07Z635DfzX4XbAFpjlRl/AYwQzTSYx8GfcNAqCqCwaSDKvsuj/vwbf91o3j3
UkdGYpcd2cYRCgKi4MwqdWyLtpuHAH18hHZ5uvi00mJYw8W2wUOsY0RC/a/IDy84
hW3WWehBUqVK5SY4/zJ4oTjx7dwNMdGwbWfpRqjd1A==
-----END CERTIFICATE-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, so the server instead of just sending its public key it sends a certificate that contains the public key, some extra information and a signature from a third party (CA - Certificate Authority).&lt;/p&gt;

&lt;h4&gt;
  
  
  Can the hacker just send its own public key along with the signature of the web server?
&lt;/h4&gt;

&lt;p&gt;The hacker can get the certificate of the web server - it is public information. And since the certificate is just a block of information - the hacker could send the its own public key together with the signature from the certificate of the web server. So this is a valid question...&lt;/p&gt;

&lt;p&gt;The trick is that the signature of the certificate is created by hashing all of the data from the certificate and encrypting it using the private key of the Certificate Authority.&lt;br&gt;
When Bobs browser receives the certificate it will decrypt the signature using the public key of the Certificate authority and it will compare the data from the signature with the content of the certificate. In this case the browser would notice that the public key from the certificate doesn't match with the one that was encrypted in the signature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who can sign a certificate?
&lt;/h2&gt;

&lt;p&gt;Basically anyone... A certificate is basically singed by a private key. This signing private key in turn has a public key and also a  certificate of the public key. And in turn this certificate is also signed, forming a chain of certificates. &lt;br&gt;
A certificate can also be self-signed, this would be the root certificate.&lt;br&gt;
A certificate is trusted by the browser if it trusts the root certificate. The operating system and the browser have lists of pre-installed Certificate Authority certificates they trust (such as DigiCert, Go Daddy, Let's Encrypt, etc.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Here is a short summary of what happens when Bob needs to send his credit card information to our web server securely using a public wifi.&lt;/p&gt;

&lt;p&gt;Our web server has a public and a private key and we have a certificate about the public key from Let's Encrypt. When Bob tries to connect to our website we first send him our certificate. Bobs browser looks at the root certificate of our certificate and decides that it can trust it. It can trust it since the certificate of the CA (Let's Encrypt in our case) is trusted by the browser. Bobs browser decrypts the signature of our certificate using the public key of the CA and compares it to the content of our certificate. After the certificate is found to be valid Bobs laptop generates a secret key. Encrypts this secret key using our public key from our certificate and sends it to our web server. From now on all the communication between us will be encrypted using this secret key - our communication is secure. &lt;/p&gt;

&lt;p&gt;Your feedback is welcome! Please let me know if you think there is something important that should be included in this post or if you find anything wrong!&lt;/p&gt;

</description>
      <category>security</category>
      <category>sslcertificate</category>
      <category>ssl</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Adding business days to a date using SQL</title>
      <dc:creator>Csaba Boros</dc:creator>
      <pubDate>Thu, 18 Aug 2022 14:10:17 +0000</pubDate>
      <link>https://forem.com/boroscsaba/adding-business-days-to-a-date-using-sql-26pb</link>
      <guid>https://forem.com/boroscsaba/adding-business-days-to-a-date-using-sql-26pb</guid>
      <description>&lt;p&gt;Recently I had a task that seemed very simple at first. I had a table with billing start dates and number of business days to bill. The task was to calculate the end date for each row. Basically to calculate the start date + number of business days without having to worry about holidays.&lt;/p&gt;

&lt;p&gt;I was surprised that there is no built-in solution for this seemingly common problem. Here is my own take on the problem.&lt;/p&gt;

&lt;p&gt;The logic is quite simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;for each 5 working days add an entire calendar week to the starting date&lt;/li&gt;
&lt;li&gt;after adding the whole weeks add the remaining days (for example adding 8 days means adding 1 week and 3 days)&lt;/li&gt;
&lt;li&gt;if the resulting date is a Saturday then add 2 more days&lt;/li&gt;
&lt;li&gt;if the resulting date is a Saturday then add 1 more day&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here is the resulting code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

create function addWorkingDays(@startDate datetime, @workingDays int)
returns datetime
as begin
    if @workingDays = 0
        return @startDate

    declare @calendarDays int = 
        (@workingDays / 5) * 7 +  -- add whole weeks 
        (@workingDays % 5) -- add remaining days

    declare @resultDate datetime = dateadd(d, @calendarDays, @startDate)

    declare @dayOfWeek int = ((datepart(DW, @resultdate) - 1) + @@datefirst ) % 7 --the @@datefirst part is needed if you are outside of US where 0 is Monday 

    return case 
        when @dayOfWeek = 0 then --Sunday
            dateadd(d, @calendarDays, @startDate) + 1
        when @dayOfWeek = 6 then -- Saturday
            dateadd(d, @calendarDays, @startDate) + 2
        else
            dateadd(d, @calendarDays, @startDate)
    end
end


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The bellow table lists a few test cases:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0cdq3g17cjnd3ffkk16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0cdq3g17cjnd3ffkk16.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

</description>
      <category>sql</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
