Extension: Azure - quandis/qbo3-Documentation GitHub Wiki
Quandis has implemented a suite of Azure-based plugins:
Plugin | Description |
---|---|
qbo.Attachment.Azure | IFileObject implementation using Azure Blob Storage. |
qbo.Encryption.Azure | IEncryptionKey implementation using Azure Key Vault. |
qbo.Queue.Azure | IQueue implementation using Azure Service Bus. |
qbo.Security.Azure | Support federated authentication via Azure Active Directory. |
qbo.Service.Azure | IService implementation enables invoking Azure Functions. |
The qbo.Attachment.Azure plugin implements QBO's IFileObject
interface for Azure's Storage AppendBlob
s. Each qbo instance (DEV, UAT, PROD) should have a dedicated storage resource created. For example, the devqbo.acme.com
qbo instance used credentials to access a Storage resource named devqbo
.
Configuration details include:
- A
FileObject
entry:-
Name
:Azure
-
Uri
:https://samplebucket.core.windows.net
-
Type
:qbo.Attachment.Azure.BlobStorage, qbo.Attachment.Azure
-
- A credential entry:
-
Uri
:https://samplebucket.core.windows.net
-
Username
:devqbo
-
Password:
{AccessKey
from the configured storage account}
-
Microsoft's CloudBlobClient
requires a connection string in the following format:
DefaultEndpointsProtocol=https;AccountName={user name};AccountKey={access key};EndpointSuffix=core.windows.net
The qbo.Attachment.Azure.BlobStorage
class will populate this connection string by substituting the credential's user name and password associated with the FileObject
entry. One can have an unlimited number of Azure storage accounts configured from a single QBO instance, so QBO can read and write files with external partners using Azure storage (or S3, or Dropbox, etc.).
Relevant application settings include:
-
qbo.Attachment.Properties.Settings
-
DefaultFileObject
: Azure -
AppendFileObject
: Azure -
ScratchpadFileObject
: Azure
-
-
qbo.Attachment.Azure.Properties.Settings
- Endpoint:
DefaultEndpointsProtocol=https;AccountName={user name};AccountKey={access key};EndpointSuffix=core.windows.net
- Endpoint:
<ImportCollection>
<ConfigurationEntryCollection>
<ConfigurationEntryItem>
<ConfigurationEntry>Azure Blob Storage</ConfigurationEntry>
<Source>FileObject.config</Source>
<ConfigurationType>qbo.Attachment.Configuration.FileObjectCollection</ConfigurationType>
<ConfigurationKey>LocalFile</ConfigurationKey>
<ConfigurationXml>
<FileObject Name="Azure" Uri="https://samplebucket.core.windows.net" Type="qbo.Attachment.Azure.BlobStorage, qbo.Attachment.Azure" Compression="False" />
</ConfigurationXml>
</ConfigurationEntryItem>
<ConfigurationEntryItem>
<ConfigurationEntry>Azure Blob Credential</ConfigurationEntry>
<Source>Credential.config</Source>
<ConfigurationType>qbo.Application.Configuration.CredentialCollection</ConfigurationType>
<ConfigurationKey>Google SMTP</ConfigurationKey>
<ConfigurationXml>
<Credential Name="AzureBlob" UriPrefix="https://samplebucket.core.windows.net" AuthType="Basic" Username="{your user name}" Password="{your access key}" />
</ConfigurationXml>
</ConfigurationEntryItem>
</ConfigurationEntryCollection>
<SystemDefaultCollection>
<SystemDefaultItem>
<SystemDefault>qbo.Attachment.Properties.Settings.DefaultFileObject</SystemDefault>
<Value>Azure</Value>
</SystemDefaultItem>
<SystemDefaultItem>
<SystemDefault>qbo.Attachment.Properties.Settings.AppendFileObject</SystemDefault>
<Value>Azure</Value>
</SystemDefaultItem>
<SystemDefaultItem>
<SystemDefault>qbo.Attachment.Properties.Settings.ScratchpadFileObject</SystemDefault>
<Value>Azure</Value>
</SystemDefaultItem>
</SystemDefaultCollection>
</ImportCollection>
The qbo.Queue.Azure
plugin implements QBO's IQueue
interface for Azure's ServiceBus. Each QBO instance (DEV, UAT, PROD) should have a dedicated ServiceBus namespace created. For example, the devqbo.api.acmebank.com
QBO instance used credentials to access a ServiceBus Namespace called qbodev-servicebus
.
- Application Settings:
qbo.Queue.Azure.Properties.Settings
AzureSubscriptionID
AzureResourceGroup
AzureTenantID
- Credentials
-
ServiceBusManager
: used to create and manage queues -
ServiceBusUser
: used to send and receive messages
-
- Queues:
DefaultQueue
andSystemMaintenance
queues- The Uri of a queue shall be formatted as:
{namespace}/{Queue}
- E.g.
qbodev-servicebus/DefaultQueue
- E.g.
qbodev-servicebus/SystemMaintenance
- The Uri of a queue shall be formatted as:
The use of application settings to config-drive some variables for the qbo.Queue.Azure
plugin limits the plugin to accessing just one Azure tenant from a given qbo environment. Should other organizations wish to share Azure ServiceBus queues with qbo, they will need to be granted access to the ServiceBus
namespace created under the AzureTenantID
configured for the qbo environment.
Topics enable a pub/sub model over a queue. To use topics, the
ServiceBus
namespace must use the Standard pricing tier.
Configure a qbo environment as follows:
- Design > Configuration > Queuing
- DefaultQueue
- SystemMaintenance
- Design > Configuration > Config Entries
- Credential entries
AzureServiceBus/Manager
andAzureServiceBus/User
- Credential entries
- Security > Roles > Administrator, Defaults tab
- qbo.Queue.Azure.Properties.Settings.AzureSubscriptionID
- qbo.Queue.Azure.Properties.Settings.AzureResourceGroup
- qbo.Queue.Azure.Properties.Settings.AzureTenantID
The qbo QueueService
is designed to process QBO method signatures from a queue. An example method signature is:
Message/[email protected]&Subject=Hello World&BodyText=Foo Bar
To create such as message to ServiceBus
from third party code (C#):
var message = new BrokeredMessage($"Message/Send");
message.ContentType = "application/text";
message.Label = "My Sample Label";
message.MessageId = Guid.NewGuid().ToString();
message.Properties.Add("ToAddress", "[email protected]");
message.Properties.Add("Subject", "Hello World");
message.Properties.Add("BodyText", "Foo Bar");
message.Properties.Add("X-User", "[email protected]");
Microsoft provides examples of sending such a message to a ServiceBus
queue.
Azure offers three pub/sub services: ServiceBus Topics, EventGrid, and EventHub. Comparing the three, most qbo clients are likely to find Topics the most useful:
- Topics support larger messages, enabling messages to contain all the necessary data for subscribers to act (reducing overall network chatter)
- De-duplication is likely to have significant use cases (particularly in payment processing)
However, subscribers need to leverage either a native Microsoft ServiceBus client, or an AMQP client - this may be a challenge for some third party providers. It's easy to write a proxy using Azure Automation or a QBO monitoring method.
With that said, there's no reason Event Grid (or EventHub) cannot be used where appropriate - status notifications without detailed supporting data.
The qbo.Security.Azure
plugin assembly provides a new endpoint (/Security/Azure.ashx
) and logic to allow users to authenticate and log in to QBO by signing in to their specified Azure Active Directory tenant.
- Log in to Azure Portal.
- Open the Azure Active Directory tab.
- Select App registrations.
- Hit 'New application registration'
- Enter an application name.
- As the sign on URL, add the application's sign on URL to hit the new endpoint; e.g.
https://acme.quandis.net/Security/Azure.ashx/Authenticate
- Click create.
- The summary screen should be displayed. Make note of the Application ID (otherwise known as Client ID) to use in later steps.
- Navigate to Settings > Reply URLs, and ensure that the value used for the sign on URL is present.
- Include
Azure.Targets
in your build script, and ensure theqbo.Security.Azure
assembly is built and deployed. - Create new
SystemDefault
rows for:
-
qbo.Security.Azure.Properties.Settings.AzureTenantID
: the AD Tenant ID to use, and -
qbo.Security.Azure.Properties.Settings.AzureClientID
: the client ID of the application's registration (see above)
- Modify
web.config
to allow anonymous access toAzure.ashx
, similar to the entry forSecurity/Login.ashx
:
<location path="Security/Azure.ashx">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
The functionality is designed to be invoked using a new button on the login page. The button needs to point to Security/Azure.ashx/Authenticate
which is the entry point for users to authenticate with Azure Active Directory:
<a href="Security/Azure.ashx/Authenticate">
<img src="https://docs.microsoft.com/en-us/azure/active-directory/develop/media/howto-add-branding-in-azure-ad-apps/ms-symbollockup_signin_light.png" height="41" width="215" />
</a>
The qbo.Encryption.Azure
plugin enables QBO to use Azure KeyVault to manage encryption keys.
From the Azure Portal:
- Create a new resource
- Select Key Vault
- Fill out desired details and Create
- Navigate to the Key Vault that was created
- Select Keys
- Click Generate/Import
- Ensure Generate is selected on the drop down, RSA Key Type is selected, and other details are filled out
- Click Create
- Select your new key, click the current version and find the field Key Identifier.
This string is how we will be able to reference the key in code
To take advantage of managed identities for Azure resources, make default Azure credentials available to the virtual machine QBO is running one:
- Select Identity when viewing the resource
- Click System Assigned
- Switch Status to on.
Next, give permissions to our VM/Application
- Select Access policies on the resource, and choose Add New
- Select principal, type in the name of the VM resource, and select it
- Ensure the desired permissions are selected. For
qbo.Encryption.Azure
purposes we needDecrypt
andGet
under Key Permissions. - Do not change Authorized application (leave it as None selected). Click OK.
- The access policy should now be shown in the list.
- Click Save
Now we need to set up the website to use qbo.Encryption.Azure
with our new Key in the Key Vault.
EncryptionKeys.Config
Using EncryptionKeys.Base.Config, create a new EncryptionKeys.Config by adding a new child of Keys as
<EncryptionKey Name="Unique Key Name" KeyUri="Complete url to new key" Type=" 'Class, assembly' like: qbo.Encryption.Azure.KvEncryptionKey, qbo.Encryption.Azure">
Create a system default to override qbo.Application.Properties.Settings.Default.DefaultEncryptionKey
and set it to the unique key name of the new EncryptionKey
in EncryptionKeys.Config
.
When the previous steps have been taken on an environment, credentials should now be making use of your new EncryptionKey
. When the application uses its credentials, it will recognize we have an EncryptionKey
set up and make use of it.