Categories
Uncategorized

Copying a Database in Azure with Always Encrypted Data

When trying to copy a database with Always Encrypted data (say, to a different environment), you’ll generally want to recycle the Column Master Key used to match the vault stored in the same Azure resource group. This takes a little bit of work to do:

Pre-Reqs

You’ll need to have the following software installed:

  • SSMS
  • Azure CLI

You’ll also need to make sure the database you’re copying from has a key that already exists. Run the following query on your newly copied database:

select * from sys.column_master_keys

And then check to see if the key exists in the appropriate vault:

az keyvault key show --id KEY_PATH

If it exists, you’ll be able to copy the database over without issue.

Procedure

Create a new key in the Key Vault:

az keyvault key create --name Always-Encrypted-Auto1 --vault-name VAULT_NAME

Next, create a new Column Master Key, using the created key above.

With two CMKs, rotate the initial CMK (using credentials from the source key vault, and then the destination key vault).

Next, clean up the previous CMK:

After this is done, you can delete the old CMK.

Categories
Uncategorized

Setting up HTTPS on an AKS Cluster

Pre-Reqs

The following is required:

  • An ingress controller should already be installed.
  • The public IP of the Ingress controller should have a DNS name.
  • Helm needs to be running at 2.13.1.
  • The Kubernetes cluster should be publicly accessible (to allow cert creation)

To check if Helm is running with version 2.13.1 (there is a bug that doesn’t allow 2.14+ to work). To check, run the following:

helm version

Client: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}

If the output doesn’t match as below, you need to downgrade Helm. Install:

# only needed if Client above is not 2.13.1
choco uninstall kubernetes-helm
choco install kubernetes-helm --version 2.13.1

helm init --upgrade --force-upgrade

Procedure

Run the following commands:

# Install the CustomResourceDefinition resources separately
kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.8/deploy/manifests/00-crds.yaml

# Create the namespace for cert-manager
kubectl create namespace cert-manager

# Label the cert-manager namespace to disable resource validation
kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true

# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io

# Update your local Helm chart repository cache
helm repo update

# Install the cert-manager Helm chart
helm install --name cert-manager --namespace cert-manager --version v0.8.0 jetstack/cert-manager

Create the following YAML file `cluster-issuer.yml’:

apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
  namespace: ingress-nginx
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: UPDATE_THIS_EMAIL
    privateKeySecretRef:
      name: letsencrypt-staging
    http01: {}

Apply the changes to the cluster:

kubectl apply -f ../shared/cluster-issuer.yml

Create the certificate.yml file:

apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: tls-secret
  namespace: ingress-nginx
spec:
  secretName: tls-secret-staging
  dnsNames:
  - YOUR_DOMAIN
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - YOUR_DOMAIN
  issuerRef:
    name: letsencrypt-staging
    kind: ClusterIssuer

Apply those changes:

kubectl apply -f certificate.yml

Verification

Confirm creation of the certificate:

kubectl describe certificate tls-secret --namespace ingress-nginx

You should see the following:

...
Normal   OrderCreated        27s                cert-manager  Created Order resource "tls-secret-3300974441"
Normal   CertIssued          3s (x2 over 20m)   cert-manager  Certificate issued successfully
Normal   OrderComplete       3s                 cert-manager  Order "tls-secret-3300974441" completed successfully

Verify HTTPS can be accessed.

Categories
Uncategorized

Adding Font Awesome to an Angular CLI Project

To add Font Awesome to your Angular CLI project, do the following:

Install Font Awesome:

npm i @fortawesome/fontawesome-free

Then add the following to your styles.css:

@import '~@fortawesome/fontawesome-free/css/all.min.css';

Once that’s done, use the following to add to your project:

<i class="far fa-copy"></i>

Categories
Uncategorized

Applying IP Restrictions to a Large Set of Azure Resources

To do this, use PowerShell and Azure CLI to collect all of the NSGs and get all of the NSGs in the subscription:

az account set -s <SUB_ID>
$nsgs = az network nsg list | ConvertFrom-Json

Then go through every NSG and create the rule:

$nsgs | ForEach-Object -Process { az network nsg rule create --name NAME --nsg-name $_.name --priority PRIORITY --resource-group $_.resourceGroup --protocol Tcp --destination-port-ranges 80 443 --source-address-prefixes IP_ADDRESSES }

Next, get a list of the App Services:

$webapps = az webapp list | ConvertFrom-Json

And go through and add the list of IPs required (must use individual IPs):

$webapps | ForEach-Object -Process { $WebAppConfig = Get-AzResource -ResourceName $_.name -ResourceType Microsoft.Web/sites/config -ResourceGroupName $_.resourceGroup -ApiVersion 2018-11-01; $WebAppConfig.Properties.ipSecurityRestrictions = @([PSCustomObject] @{ ipAddress = '127.0.0.1/32' },@{ ipAddress = '127.0.0.1/32' });  Set-AzResource -ResourceId $WebAppConfig.ResourceId -Properties $WebAppConfig.Properties -ApiVersion 2018-11-01 }

Removing Access

To delete the same list of rules from the NSGs, use the same name:

$nsgs | ForEach-Object -Process { az network nsg rule delete -g resourceGroup --nsg-name $_.name -n NAME }

Reference:

https://docs.microsoft.com/en-us/cli/azure/network/nsg?view=azure-cli-latest#az-network-nsg-list

https://docs.microsoft.com/en-us/cli/azure/network/nsg/rule?view=azure-cli-latest#az-network-nsg-rule-create

https://docs.microsoft.com/en-us/cli/azure/network/nsg/rule?view=azure-cli-latest#az-network-nsg-rule-delete

Categories
Uncategorized

Creating a Buy One Get One Half Off Discount In NopCommerce

I recently worked with a client on trying to set up a Buy One Get One Half Off deal on NopCommerce – here’s what I did to get it working:

Requirements

Before starting, you should have the following:

Process

Go to the Discounts page and create a new Discount with the following information:

Next, go to the ‘Restrictions’ tab and add a restriction for the Product, using the ‘Add Product’ functionality Make sure you add the :2 to the end to force purchase of two:

Categories
Uncategorized

Deploying web.config with an Angular Project

When deploying an Angular project out to Azure, you’ll need to include a web.config file to allow for things such as the following:

  • Getting routing to work.
  • Serving static content.

First, create a web.config file in src/. Here’s an example of what it might look like:

<?xml version="1.0"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="Angular Routing" stopProcessing="true">
                <match url=".*" />
                <conditions logicalGrouping="MatchAll">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile"
                         negate="true" />
                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory"
                         negate="true" />
                </conditions>
                <action type="Rewrite" url="/" />
                </rule>
            </rules>
        </rewrite>
        <staticContent>
            <mimeMap fileExtension="woff" mimeType="application/font-woff" />
            <mimeMap fileExtension="json" mimeType="application/json" />
        </staticContent>
    </system.webServer>
</configuration>

After this is done, make a change to angular.json to bundle the web.config file in the build:

...
"assets": [
    /src/favicon.ico",
    /src/assets",
    /src/web.config"
],
...

Now let’s verify by running ng build --prod:

Categories
Uncategorized

Adding Bootstrap To An Angular CLI Project

Pre-Reqs

Before setting this up, you’ll need to have an Angular project to add Bootstrap to. If you’re starting fresh, you can create one easily with ng new <name>.

Procedure

First, install bootstrap from npm:

npm install bootstrap

Then add the following to the top of your styles.css file:

@import '~bootstrap/dist/css/bootstrap.min.css';

That’s it! Bootstrap is now enabled for your Angular CLI application.

Categories
Uncategorized

Setting up WordPress in Azure with AKS and Helm

To get started, you’ll need the following:

  • kubectl
  • helm
  • Azure subscription

Installing WordPress in AKS with Helm

Set up an Azure Kubernetes Service with the following:

  • Node size – desired VM size (cheapest available is B2s)
  • Node count – need to use at least a minimum of 1.

After AKS is set up, connect to it with the following:

az aks get-credentials --resource-group AKS_RG --name AKS_NAME

Install Helm:

helm init

Create a values.yml file:

wordpressUsername: sammy
wordpressEmail: sammy@example.com
wordpressFirstName: Sammy
wordpressLastName: the Shark
wordpressBlogName: Sammy's Blog!

Create a second file values.secret.yml:

wordpressPassword: password

Now install WordPress with the following commands:

helm install --name blog -f values.yml -f values.secrets.yml stable/wordpress

After installation, run the following command to get the external IP:

kubectl get svc --namespace default -w blog-wordpress

Once the IP is ready, you’ll likely need to wait for the pods to finish loading. You can check their status with:

kubectl get pods

Once ready, try accessing the IP address to get the WordPress installation.

Reference: https://www.digitalocean.com/community/tutorials/how-to-set-up-wordpress-with-mysql-on-kubernetes-using-helm

Categories
Uncategorized

Setting Up SonarQube in Azure with Azure AD Integration

Installing SonarQube

Go to the marketplace and install SonarQube from Bitnami – https://bitnami.com/stack/sonarqube/cloud/azure with the following:

  • resize to D1_v2
  • if desired, configure any NSG restrictions

After creation, set a DNS name label for the IP address.

Access using the domain name, and follow the directions in the link above to log in.

Setting up Azure AD Integration

Setting up HTTPS

To be able to use Azure AD, you have to use HTTPS.

Set up the Server base URL to be the configured HTTPS address in Administration → Configuration → General → Server base URL:

SSH into the server and set up a Let’s Encrypt script and enforce redirection to HTTPS here (make sure you aren’t behind a firewall to allow for Let’s Encrypt).

Restart Apache:

sudo /opt/bitnami/ctlscript.sh restart apache

Verify that trying to access the HTTP version of SonarQube automatically redirects you to the HTTPS version.

Creating App Registration in Azure

Run the following command in CLI to generate a service principal:

az ad sp create-for-rbac --name="{NAME}" --role="Contributor" --scope="/subscriptions/{SUBSCRIPTION_ID}" --years=100

You should receive some output data, which you will use when filling out info in SonarQube:

Set the Reply URL of the application to https://<URL>/oauth2/callback/aad:

Set the required permissions:

  • Sign in and read user profile
  • Read all users’ basic profiles

Installing Plug-in

Install the Azure Active Directory (AAD) Authentication Plug-in for SonarQube (restarting when requested):

Configure in Administration → General Settings → Azure Active Directory:

  1. Activate Azure AD
  2. Use the value in “appId”
  3. Use the value in “password”
  4. Use the value in “tenant”
  5. Allow users to sign-up.

Log out as admin, and verify the ability to log in as an Azure AD user.

Categories
Uncategorized

Create Multiple Terraform Resources with a Map

I recently worked through a case in Terraform where I wanted to be able to pass in a map for Terraform to allow creating secrets in an Azure Key Vault. We’ll use the count, keys(, and values( helpers to iterate through the map.

This code sample will show a way to dynamically determine the amount of resources needed. In this case, this will create secrets based on the map provided in the Terraform variable:

variable "vault_secrets" {
  secret_name_1 = "secret_value_1"
  secret_name_2 = "secret_value_2"
  secret_name_3 = "secret_value_3"
}

resource "azurerm_key_vault" "vault" {
  name                = "example-vault"
  location            = "${var.rg_location}"
  resource_group_name = "${var.rg_name}"
  tenant_id           = "00000000-0000-0000-0000-000000000000"

  sku {
    name = "standard"
  }
}

resource "azurerm_key_vault_secret" "secret" {
  count = "${length(keys(var.vault_secrets))}"

  name         = "${element(keys(var.vault_secrets), count.index)}"
  value        = "${element(values(var.vault_secrets), count.index)}"
  key_vault_id = "${azurerm_key_vault.vault.id}"
}