From 807b8d6b2aa59a6fe07d9c0e3bd486f840bd51ac Mon Sep 17 00:00:00 2001 From: clemensv Date: Wed, 21 Sep 2022 10:40:52 -0700 Subject: [PATCH] SQL Server example Signed-off-by: clemensv --- CONFIG.md | 6 +- examples/sqlserver/Deploy-Relay.ps1 | 23 +++ examples/sqlserver/README.md | 132 ++++++++++++++++++ examples/sqlserver/client_config.yml | 15 ++ .../sqlserver/relay-resource-template.json | 58 ++++++++ examples/sqlserver/server_config.yml | 16 +++ src/tools/azure/test-resource-template.json | 2 +- 7 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 examples/sqlserver/Deploy-Relay.ps1 create mode 100644 examples/sqlserver/README.md create mode 100644 examples/sqlserver/client_config.yml create mode 100644 examples/sqlserver/relay-resource-template.json create mode 100644 examples/sqlserver/server_config.yml diff --git a/CONFIG.md b/CONFIG.md index 365f290..560dbb3 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -252,10 +252,10 @@ The configuration file can exist in three locations: 1. Machine configuration, always loaded if present. Linux: /etc/azurebridge/azurebridge_config - Windows: %ALLUSERSPROFILE%\Microsoft\AzureBridge\azbridge_config + Windows: %PROGRAMDATA%\Microsoft\AzureBridge\azbridge_config.machine.yml 2. User configuration, overrides and complements machine config. - Linux: ~/.azurebridge/config - Windows: %USERPROFILE%\.azurebridge\config + Linux: ~/.azbridge/azbridge_config.yml + Windows: %APPDATA%\azbridge\azbridge_config.yml 3. Override user configuration location for current execution with the -f option. diff --git a/examples/sqlserver/Deploy-Relay.ps1 b/examples/sqlserver/Deploy-Relay.ps1 new file mode 100644 index 0000000..56f81d8 --- /dev/null +++ b/examples/sqlserver/Deploy-Relay.ps1 @@ -0,0 +1,23 @@ +<# +.DESCRIPTION +Deploys an Azure Relay namespace in a goiven location. The script assumes that Azure Powershell is installed and the user is logged into Powershell. + +.PARAMETER NamespaceName +Unqualified namespace name. Must be globally unique. + +.PARAMETER Location +Valid Azure region identifier, eg. westeurope or eastus + +.EXAMPLE +.\Deploy-Relay.ps1 myuniquename westeurope +#> + +param( + [parameter(Mandatory = $true)] + [string] $namespaceName, + [parameter(Mandatory = $true)] + [string] $location +) + +$ = New-AzResourceGroup -Name $NamespaceName -Location $Location +New-AzResourceGroupDeployment -ResourceGroupName $NamespaceName -TemplateFile "$PSScriptRoot\relay-resource-template.json" -namespaceName $namespaceName -location $location \ No newline at end of file diff --git a/examples/sqlserver/README.md b/examples/sqlserver/README.md new file mode 100644 index 0000000..bc3c657 --- /dev/null +++ b/examples/sqlserver/README.md @@ -0,0 +1,132 @@ +## Microsoft SQL Server example + +This directory contains a set of sample files illustrating how to bridge to a +SQL Server instance. + + +## Relay Setup + +First, create an Azure Relay namespace with a Hybrid Connection named "sql". + +The included [Azure +Powershell](https://learn.microsoft.com/en-us/powershell/azure/) script +`Deploy-Relay.ps1`can be called with the name of the namespace and the Azure +region, for instance, and deploys the included resource template: + +```Powershell +$result=./Deploy-Relay.ps1 mynamespacename westeurope +echo $result.Outputs.sendListenConnectionString.Value +``` + +An equivalent, explicit script using [Azure +CLI](https://learn.microsoft.com/en-us/cli/azure/) looks like this: + +```azurecli +export _NS=mynamespacename +az group create --name $_NS --location westeurope +az relay namespace create -g $_NS --name $_NS +az relay hyco create -g $_NS --namespace-name $_NS --name sql +az relay namespace authorization-rule create -g $_NS --namespace-name $_NS -n sendlisten --rights Send Listen +az relay namespace authorization-rule keys list -g cvtest888 --namespace-name cvtest888 -n sendlisten --out tsv --query "primaryConnectionString" +``` + +## Customizing the config files + +The template deployment returns a connection string from the +`sendListenConnectionString` value. The last line of the CLI script yields a +connection string as well. + +These connection strings are associated with a namespace-wide [shared access +signature +rule](https://learn.microsoft.com/en-us/azure/azure-relay/relay-authentication-and-authorization#shared-access-signature) +called "sendlisten" that confers both the "Listen" and "Send" permission at +once. + +The `client_config.yml` and `server_config.yml` files each have a line as +follows. Replace the placeholder with the connection string in those files. + +```yml +AzureRelayConnectionString : <> +``` + +The remaining content of `client_config.yml` sets up a local forwarder bound to +address 127.0.0.2 with TCP port 1433 mapped to hybrid connection "sql". The +logical port name is set to "tds", which allows for the TCP port number here to +differ from that on the server. + +```yml +LocalForward : + - BindAddress: 127.0.0.2 + BindPort: 1433 + PortName: tds + RelayName: sql + +LogLevel: INFO +``` + +Using the `add-hostname` PowerShell command (Windows) or the `addhost` bash +function (Linux) that are installed with `azbridge`, you can easily map that +address to a local host name alias. You must run that command as administrator. + +Bash: + +```bash +addhost 127.0.0.2 localsql +``` + +Powershell: + +```powershell +add-hostname 127.0.0.2 localsql +``` + +The remaining `server_config.yml` file sets up a remote forwarder that binds the hybrid connection "sql" with logical port "tds" to the SQL server endpoint on "localhost", port 1433. + +```yml +RemoteForward : + - RelayName: sql + Host: localhost + PortName: tds + HostPort: 1433 + +LogLevel: INFO +``` + +## Running the bridge + +To run the bridge, you can now run + +```azurecli +azbridge -f ./client_config.yml +``` + +on the client side where the SQL client will run. + +You run + +```azurecli +azbridge -f ./server_config.yml +``` + +on the server side where SQL server runs. + +To verify the bridge, you can now connect through it from the client side, for +instance with `sqlcmd`: + +```azurecli +sqlcmd -S tcp:127.0.0.2,1433 -P <> -U <> +``` + +With the host name alias use + +```azurecli +sqlcmd -S tcp:localsql,1433 -P <> -U <> +``` + +Mind that if you enable TLS (Encryption) for SQL Server (as you should), the +host name alias you configure must match the remote SQL server's host name in +order for the certificate validation on the client to function correctly. Concretely, if the SQL Server's host name on its local network is "sql.corp.example.com", that exact name must be used for the host name alias. + + +The Azure Relay tunnel is *always* TLS protected, independent of the SQL server +configuration. \ No newline at end of file diff --git a/examples/sqlserver/client_config.yml b/examples/sqlserver/client_config.yml new file mode 100644 index 0000000..b389354 --- /dev/null +++ b/examples/sqlserver/client_config.yml @@ -0,0 +1,15 @@ +# Azure Relay Bridge Configuration + +# Replace the value with the connection string returned when the template was deployed +AzureRelayConnectionString : <> + +# The local forwarder binds 127.0.0.2 port 1433 to +# hybrid connection "sql" using the logical port name "tds" + +LocalForward : + - BindAddress: 127.0.0.2 + BindPort: 1433 + PortName: tds + RelayName: sql + +LogLevel: INFO \ No newline at end of file diff --git a/examples/sqlserver/relay-resource-template.json b/examples/sqlserver/relay-resource-template.json new file mode 100644 index 0000000..42d7d8f --- /dev/null +++ b/examples/sqlserver/relay-resource-template.json @@ -0,0 +1,58 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "namespaceName": { + "type": "String" + }, + "location": { + "type": "String" + } + }, + "variables": { + "apiVersion": "2017-04-01" + }, + "resources": [{ + "type": "Microsoft.Relay/namespaces", + "name": "[parameters('namespaceName')]", + "apiVersion": "[variables('apiVersion')]", + "location": "[parameters('location')]", + "dependsOn": [] + }, + { + "type": "Microsoft.Relay/namespaces/AuthorizationRules", + "name": "[concat(parameters('namespaceName'), '/sendlisten')]", + "apiVersion": "[variables('apiVersion')]", + "properties": { + "rights": [ + "Send", + "Listen" + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Relay/namespaces', parameters('namespaceName'))]" + ] + }, + { + "type": "Microsoft.Relay/namespaces/hybridConnections", + "name": "[concat(parameters('namespaceName'), '/sql')]", + "apiVersion": "[variables('apiVersion')]", + "properties": { + "requiresClientAuthorization": true + }, + "dependsOn": [ + "[resourceId('Microsoft.Relay/namespaces', parameters('namespaceName'))]" + ] + } + ], + "outputs": { + "serviceBusNamespaceName": { + "type": "string", + "value": "[parameters('namespaceName')]" + }, + "sendListenConnectionString": { + "type": "string", + "value": "[listkeys(resourceId('Microsoft.Relay/namespaces/AuthorizationRules', parameters('namespaceName'), 'sendlisten'),variables('apiVersion')).primaryConnectionString]" + } + } +} \ No newline at end of file diff --git a/examples/sqlserver/server_config.yml b/examples/sqlserver/server_config.yml new file mode 100644 index 0000000..198f4d8 --- /dev/null +++ b/examples/sqlserver/server_config.yml @@ -0,0 +1,16 @@ +# Azure Relay Bridge Configuration + +# Replace the value with the connection string returned when the template was deployed +AzureRelayConnectionString : <> + +# The remote forwarder points to TCP port 1433 of the SQL Server on localhost. +# If the bridge runs on a separate machine, this can also point to another +# host on the local network. + +RemoteForward : + - RelayName: sql + Host: localhost + PortName: tds + HostPort: 1433 + +LogLevel: INFO \ No newline at end of file diff --git a/src/tools/azure/test-resource-template.json b/src/tools/azure/test-resource-template.json index 0d96683..2cbd77f 100644 --- a/src/tools/azure/test-resource-template.json +++ b/src/tools/azure/test-resource-template.json @@ -1,5 +1,5 @@ { - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "relay_namespace": {