Category Archives: Guides

Key Vault Template for Azure Bicep

Hi everyone,

I’m currently mucking around with Bicep as a replacement for plain ARM templates. I’ve just created a key vault and thought I’d share it in case anyone else finds it useful:

param namePrefix string
param location string = resourceGroup().location
param tenantId string

var name = '${namePrefix}${uniqueString(resourceGroup().id)}'

resource key_vault 'Microsoft.KeyVault/vaults@2019-09-01' = {
  name: name
  location: location
  properties: {
    sku: {
      family: 'A'
      name: 'standard'
    }    
    tenantId: tenantId
  }
}

resource my_test_secret 'Microsoft.KeyVault/vaults/secrets@2019-09-01' = {
  name: '${key_vault.name}/my-test-secret'
  properties: {
    attributes: {
      enabled: true
    }
  }
}

If you want to add any other properties checkout the arm template definition: https://docs.microsoft.com/en-us/azure/templates/microsoft.keyvault/2019-09-01/vaults?tabs=json

Setup MongoDB on an Azure VM

Hi everyone,

I’m currently using a small linux vm to host a MongoDB instance on Azure. These are the steps I followed:

## MongoDB

### Install
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/

1. Import the public key: `wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -`
2. Create a list file:  `echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list`
   - This is for Ubuntu 18.04, check version using `lsb_release -a` 
3. Reload the local package database: `sudo apt-get update`
4. Install MongoDb: `sudo apt-get install -y mongodb-org`
5. Pin the version to prevent automatic upgrades 
```
echo "mongodb-org hold" | sudo dpkg --set-selections
echo "mongodb-org-server hold" | sudo dpkg --set-selections
echo "mongodb-org-shell hold" | sudo dpkg --set-selections
echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
echo "mongodb-org-tools hold" | sudo dpkg --set-selections
```

### Allow remote access
https://www.digitalocean.com/community/tutorials/how-to-configure-remote-access-for-mongodb-on-ubuntu-20-04

1. sudo nano /etc/mongod.conf
2. Find the `network interfaces` section
3. Find the `bindIp` value
4. Append the public ip of your vm to this address list `bindIp: 0.0.0.0`
   - *Note that this is the VM ip not the ip of the machine you plan to connect from.*
5. Restart MongoDB `sudo systemctl restart mongod`

### Add authentication
1. Connect to the instance from an ssh connection: `mongo --port 27017'
2. Create the user:
https://stackoverflow.com/a/38921949/522859
```
db.createUser(
  {
    user: "YOUR_USERNAME",
    pwd: "YOUR_PASSWORD",
    roles: [ { role: "root", db: "admin" } ]
  }
)
```
3. Restart with access control: `mongod --auth --port 27017 --dbpath /data/db1`
4. Authenticate as the user adminstrator: `mongo --port 27017 -u "YOUR_USERNAME" -p "YOUR_PASSWORD"  --authenticationDatabase "admin"`
5. Locate the commented out security heading and uncomment it.
6. Add `authorized: enabled`
```
security:
  authorization: enabled
```
7. Restart with access control: `mongod --auth --port 27017 --dbpath /data/db1` 

Setup PostgreSQL on an Azure VM

Hi everyone,

I’m currently testing out a small linux vm with PostgreSQL on Azure. Just sharing the steps for future reference and hopefully it’ll be able to help you out as well.

# Setup PostgreSQL on Azure VM

## Run updates
sudo apt-get update
sudo apt-get install postgresql

## Setup postgresql.conf
1. sudo vim /etc/postgresql/10/main/postgresql.conf
2. Add or uncomment `listen_addresses = '*'`

## Update pg_hba.conf
1. sudo nano /etc/postgresql/10/main/pg_hba.conf
2. Add the following line `host    all             all             151.XXX.XXX.XXX/32        md5` *\*where the ip is your public ip*
3. Restart pgsql `invoke-rc.d postgresql restart`

## Setup a PostgreSQL user
https://serverfault.com/a/248162/148152  

1. sudo -u postgres psql postgres
2. postgres=# \password postgres
3. Enter a new password and then confirm it.

## Done
You should now be able to login remotely (I was using pgAdmin from Windows for this).

Good luck!

Quick Sample to Create a VM – Azure Bicep

Hey everyone,

I’m trying out Bicep for my current side project and have created a small vm to host a PostgreSQL instance. There weren’t a lot of samples to reference in order to get this going so I thought I’d upload it:

I’ve added a github repo if you find that a little easier to go through but all of the code is available below: https://github.com/Buzzology/bicep-vm.git

Update the resource group in the parameters file and then run the following command to deploy it:

az deployment group create --template-file ./main.bicep  --parameters ./parameters/parameters.prod.json -g "{YOUR_RESOURCE_GROUP}"
// main.bicep
targetScope = 'subscription' // tenant', 'managementGroup', 'subscription', 'resourceGroup'

param vmPgsqlUsername string
param vmPgsqlPassword string
param resourceGroupName string = 'not-set'
param namePrefix string = 'not set'


module vnet_generic './vnets/vnet-generic.bicep' = {
  name: 'vnet'
  scope: resourceGroup(resourceGroupName)
  params: {
    namePrefix: '${namePrefix}-vnet'
  }
}


module vm_pgsql './virtual-machines/postgresql/vm-postgresql.bicep' = {
  name: 'vm-pgsql'
  scope: resourceGroup(resourceGroupName)
  params: {
    namePrefix: '${namePrefix}-vm'
    subnetId: vnet_generic.outputs.subnetId
    username: vmPgsqlUsername
    password: vmPgsqlPassword
  }
}
 

output vmName string = vm_pgsql.name
// vnets\vnet-generic.bicep
param namePrefix string = 'unique'
param location string = resourceGroup().location

var name = '${namePrefix}-${uniqueString(resourceGroup().id)}'
var subnetName = 'main-subnet'

resource vnet_generic 'Microsoft.Network/virtualNetworks@2020-08-01' = {
  name: name
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/24'
      ]
    }
    subnets: [
      {
        name: subnetName
        properties: {
          addressPrefix: '10.0.0.0/24'
          delegations: []
          privateEndpointNetworkPolicies: 'Enabled'
          privateLinkServiceNetworkPolicies: 'Enabled'
        }
      }
    ]
    virtualNetworkPeerings: []
    enableDdosProtection: false
  }
}


output vnetId string = vnet_generic.id
output subnetId string = '${vnet_generic.id}/subnets/${subnetName}'
output subnetName string = subnetName
// virtual-machines\gneral\vm-small
param namePrefix string = 'unique'
param location string = resourceGroup().location
param subnetId string
param privateIPAddress string =  '10.0.0.4'

var vmName = '${namePrefix}${uniqueString(resourceGroup().id)}'

resource nic_pgsql 'Microsoft.Network/networkInterfaces@2020-08-01' = {
  name: vmName
  location: location
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig1'
        properties: {
          privateIPAddress: privateIPAddress
          privateIPAllocationMethod: 'Dynamic'
          subnet: {
            id: subnetId
          }
          primary: true
          privateIPAddressVersion: 'IPv4'
        }
      }
    ]
    dnsSettings: {
      dnsServers: []
    }
    enableAcceleratedNetworking: false
    enableIPForwarding: false
  }
}


output nicId string = nic_pgsql.id
// virtual-machines\general\vm-small.bicep
param namePrefix string = 'unique'
param location string = resourceGroup().location
param subnetId string
param ubuntuOsVersion string = '18.04-LTS'
param osDiskType string = 'Standard_LRS'
param vmSize string = 'Standard_B1s'
param username string
param password string

var vmName = '${namePrefix}${uniqueString(resourceGroup().id)}'

// Bring in the nic
module nic './vm-small-nic.bicep' = {
  name: '${vmName}-nic'
  params: {
    namePrefix: '${vmName}-hdd'
    subnetId: subnetId
  }
}

// Create the vm
resource vm_small 'Microsoft.Compute/virtualMachines@2019-07-01' = {
  name: vmName
  location: location
  zones: [
    '1'
  ]
  properties: {
    hardwareProfile: {
      vmSize: vmSize
    }
    storageProfile: {
      osDisk: {
        createOption: 'FromImage'
        managedDisk: {
          storageAccountType: osDiskType
        }
      }
      imageReference: {
        publisher: 'Canonical'
        offer: 'UbuntuServer'
        sku: ubuntuOsVersion
        version: 'latest'
      }
    }
    osProfile: {
      computerName: vmName
      adminUsername: username
      adminPassword: password
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: nic.outputs.nicId
        }
      ]
    }
  }
}

output id string = vm_small.id

// virtual-machines/postgresql/vm-postgresql.bicep
param namePrefix string
param subnetId string
param username string
param password string

var name = '${namePrefix}-pgsql'

module vm_pgsql '../general/vm-small/vm-small.bicep' = {
  name: name
  params: {
    namePrefix: name
    location: resourceGroup().location
    subnetId: subnetId
    ubuntuOsVersion: '18.04-LTS'
    osDiskType: 'Standard_LRS'
    vmSize: 'Standard_B1s'
    username: username
    password: password    
  }
}

output vmId string = vm_pgsql.outputs.id
// parameters/parameters.prod.json
{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "resourceGroupName": {
            "value": "prod"
        },
        "namePrefix": {
            "value": "prod"
        },
        "vmPgsqlUsername": {
            "value": "test_username"
        },
        "vmPgsqlPassword": {
            "value": "$1test_password"
        }
    }
}

Overwrite Selected Tree View Item Styles – Material UI ReactJS

Hi everyone,

Just a quick post on how to overwrite the styles of a selected tree item using material ui and ReactJS:

treeItem: {
paddingTop: theme.spacing(1),
‘&[aria-selected=”true”][aria-expanded=”true”] > div:nth-of-type(1)’: {
backgroundColor: ‘red’,
}
},

This will make the background color red for ONLY the selected item:
material-ui-tree-view

Cheers,
Chris

.Net Core Web Api Returning Binary File with No Headers Instead of Expected Response

Hey everyone,

A small issue I’ve run into while setting up a .net core web api microservice that also utilises a number of gRPC services. Symptoms were as follows:

Response Read via Fiddler
– HTTP/1.0 200 This buggy server did not return headers
– Value was binary and unable to be read

Server logs

03:59:23 DBG] Connection id “0HM01U963EUAR” accepted.
[03:59:23 DBG] Connection id “0HM01U963EUAR” started.
[03:59:23 DBG] Connection id “0HM01U963EUAR”: HTTP/2 connection error.
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2ConnectionErrorException: HTTP/2 connection error (PROTOCOL_ERROR): Invalid HTTP/2 connection preface.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2Connection.ParsePreface(ReadOnlySequence`1& buffer, SequencePosition& consumed, SequencePosition& examined)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2Connection.TryReadPrefaceAsync()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2Connection.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
[03:59:23 DBG] Connection id “0HM01U963EUAR” is closed. The last processed stream ID was 0.
[03:59:23 VRB] Connection id “0HM01U963EUAR” sending GOAWAY frame for stream ID 0 with length 8 and flags 0x0
[03:59:23 DBG] Connection id “0HM01U963EUAR” stopped.
[03:59:23 DBG] Connection id “0HM01U963EUAR” sending FIN because: “The Socket transport’s send loop completed gracefully.”

The issue turned out to be that in appSettings.json the default kestrel endpoint had been set to utilise http2. Removing this immediately resolved the issue. It may also be worth double checking your launch settings, startup.cs and program.cs to ensure that nothing’s been overridden.

I expect that any similar routing issues would result in similar symptoms so hopefully this post will be able to save a few people a bit time!

Cheers,
Chris

OpenXml Validation Spreadsheet Value Between Two Numbers – C#

Hi everyone,

Just a quick post on how to validate a numeric cell to ensure that the value is between two numbers when using OpenXml:

// Restrict min and max values
var dataValidations = new DocumentFormat.OpenXml.Spreadsheet.DataValidations { Count = 0 };
DocumentFormat.OpenXml.Spreadsheet.DataValidation dataValidation;
dataValidation = new DocumentFormat.OpenXml.Spreadsheet.DataValidation {
Type = DataValidationValues.Decimal,
AllowBlank = false,
SequenceOfReferences = new ListValue() { InnerText = $”{columnName}2:{columnName}1048576″ },
Operator = DataValidationOperatorValues.Between,
Formula1 = new Formula1 { Text = “10 “},
Formula2 = new Formula2 { Text = “20 “},
};
dataValidations.Append(dataValidation);
dataValidations.Count++;
worksheetPart.Worksheet.Append(dataValidations);

The snippet above will ensure that any values are between 10 and 20. I didn’t come across any examples for this while searching, so hopefully this will be able to help someone else out!

Thanks,
Chris

View Raw SQL in EF Core – Simple Option

Hi everyone,

I’ve been looking for a simple way of viewing the raw output of sql in my local environment without having to make code changes and came across the following config setup:

{
“Logging”: {
“LogLevel”: {
“Default”: “Debug”,
“System”: “Information”,
“Microsoft”: “Information”
}
}

This will show the sql statements in your output window without requiring any additional code:
sql-output

Thanks to this stackoverflow post for the answer: https://stackoverflow.com/a/54704006/522859

Simple React-Leaflet Location Picker Setup

Hi everyone,

Just thought I’d share a very simple react-leaflet setup in case it’s able to help anyone.

screencast-localhost_3889-2019.08.24-14_01_41.gif

Add the css and javascript for leaflet to public > index.html:

  
https://unpkg.com/leaflet@1.5.1/dist/leaflet.js">https://unpkg.com/leaflet@1.5.1/dist/leaflet.js

Install react-leaflet via npm or yarn, also add the dependencies:

npm install react-leaflet # npm
npm install leaflet react react-dom # npm

yarn add react-leaflet # Yarn
yarn add leaflet react react-dom # Yarn

Create the map component:

import React, { useState } from 'react'
import { Map, TileLayer, Marker, Popup } from 'react-leaflet'


const MapSimple = () => {

    const [location, setLocation] = useState({
        lat: 51.505,
        lng: -0.09,
        zoom: 13,
    });
    const position = [location.lat, location.lng];
    
    const setMarkerPosition = e => {
        setLocation({ ...e.latlng, zoom: 19 });
        console.log(`My location is: ${JSON.stringify(e.latlng, null, 3)}`)
    };

    return (
        
            <TileLayer
                attribution='© OpenStreetMap contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
            />
            
                
                   A sample popup.
                
            
        
    )
}

export default MapSimple;

NetTopologySuite Circular Reference with .net core 2.2

Hey everyone,

Testing out a spatial project with .net core and I ran into the following error:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : The best overloaded method match for ‘Xunit.Assert.Equal(string, string)’ has some invalid arguments

at CallSite.Target(Closure , CallSite , Type , Nullable`1 , Object )
at UpdateDelegates.UpdateAndExecuteVoid3[T0,T1,T2](CallSite site, T0 arg0, T1 arg1, T2 arg2)
at DiscussionsControllerIntegrationTests.CreateTestDiscussion(HttpClient client, ApplicationDbContext db, DiscussionCreateWebRequest payload) in DiscussionsControllerIntegrationTests.cs line: 56
at DiscussionsControllerIntegrationTests.b__1_0(ApplicationDbContext db) in DiscussionsControllerIntegrationTests.cs line: 27
at IntegrationTestBase.RunTest(Func`2 testToExecute) in IntegrationTestBase.cs line: 54
at DiscussionsControllerIntegrationTests.CreateDiscussionIsSuccessful() in DiscussionsControllerIntegrationTests.cs line: 25
at — End of stack trace from previous location where exception was thrown —

Thankfully the solution is pretty straight forward. Install GeoJSON:

Install-Package NetTopologySuite.IO.GeoJSON

Then merge the following with your existing addMvc call in startup.cs:

services.AddMvc(options =>
            {
                // Prevent the following exception: 'This method does not support GeometryCollection arguments'
                // See: https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/585
                options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Point)));
                options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Coordinate)));
                options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(LineString)));
                options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(MultiLineString)));
            })
                .AddJsonOptions(options =>
                {
                    foreach (var converter in NetTopologySuite.IO.GeoJsonSerializer.Create(new GeometryFactory(new PrecisionModel(), 4326)).Converters)
                    {
                        options.SerializerSettings.Converters.Add(converter);
                    }
                })
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);