(fix): integration tests add yaml and test resouces
This commit is contained in:
Родитель
65167de612
Коммит
9e88dbf210
|
@ -10,3 +10,5 @@ coverage
|
|||
pl
|
||||
# don't use rules on the config file
|
||||
.eslintrc.js
|
||||
# don't spell check the package.json
|
||||
package.json
|
|
@ -7,6 +7,7 @@ module.exports = {
|
|||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:security/recommended",
|
||||
"plugin:mocha/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
|
@ -15,7 +16,8 @@ module.exports = {
|
|||
"jsdoc"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8
|
||||
"ecmaVersion": 8,
|
||||
tsconfigRootDir: __dirname
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
|
@ -32,7 +34,7 @@ module.exports = {
|
|||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-inferrable-types": "off",
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"@typescript-eslint/member-ordering": ["error", {"default": ["abstract-method", "instance-method", "static-method"]}],
|
||||
"@typescript-eslint/member-ordering": ["error", { "default": ["abstract-method", "instance-method", "static-method"] }],
|
||||
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
|
||||
"@typescript-eslint/dot-notation": "error",
|
||||
"@typescript-eslint/member-delimiter-style": [
|
||||
|
@ -71,6 +73,7 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
"rules": {
|
||||
"security/detect-object-injection": "off",
|
||||
"mocha/no-setup-in-describe": "off",
|
||||
"no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
|
||||
"arrow-parens": [
|
||||
|
@ -88,7 +91,7 @@ module.exports = {
|
|||
"error",
|
||||
"smart"
|
||||
],
|
||||
"id-blacklist": [
|
||||
"id-denylist": [
|
||||
"error",
|
||||
"any",
|
||||
"Number",
|
||||
|
|
13
package.json
13
package.json
|
@ -15,25 +15,23 @@
|
|||
"azure-iot-common": "1.13.0",
|
||||
"azure-iot-http-base": "1.12.0",
|
||||
"debug": "^4.3.1",
|
||||
"es5-ext": "0.10.53",
|
||||
"lodash": "^4.17.21",
|
||||
"machina": "^4.0.2",
|
||||
"rhea": "^1.0.15",
|
||||
"tslib": "^1.9.3"
|
||||
"rhea": "^1.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/debug": "^4.1.5",
|
||||
"@types/node": "^16.10.2",
|
||||
"autorest": "^2.0.4413",
|
||||
"@typescript-eslint/eslint-plugin": "^5.41.0",
|
||||
"@typescript-eslint/eslint-plugin-tslint": "^5.41.0",
|
||||
"@typescript-eslint/parser": "^5.41.0",
|
||||
"eslint": "^8.26.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.41.0",
|
||||
"@typescript-eslint/parser": "^5.41.0",
|
||||
"eslint-plugin-jsdoc": "^39.3.25",
|
||||
"eslint-plugin-mocha": "^10.1.0",
|
||||
"eslint-plugin-no-null": "^1.0.2",
|
||||
"eslint-plugin-no-only-tests": "^3.1.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-security": "^1.5.0",
|
||||
"autorest": "^2.0.4413",
|
||||
"chai": "^4.3.3",
|
||||
"jshint": "^2.13.4",
|
||||
"mocha": "^9.2.1",
|
||||
|
@ -77,6 +75,7 @@
|
|||
"shared-access-signature": "node node_modules/mocha/bin/_mocha ./test/_shared_access_signature_test.js",
|
||||
"amqp-simulated": "node node_modules/mocha/bin/_mocha ./test/amqp_simulated.js",
|
||||
"twin": "node node_modules/mocha/bin/_mocha ./test/_twin_test.js",
|
||||
"registry-test-integration": "node node_modules/mocha/bin/_mocha ./test/_registry_test_integration.js",
|
||||
"unittest-min": "tsc && nyc --reporter lcov ./node_modules/mocha/bin/_mocha --reporter dot --parallel test/**/_*_test.js",
|
||||
"alltest-min": "tsc && nyc --reporter lcov ./node_modules/mocha/bin/_mocha --reporter dot --parallel test/_*_test*.js",
|
||||
"unittest": "tsc && nyc --reporter lcov --reporter text ./node_modules/mocha/bin/_mocha --parallel test/**/_*_test.js",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable security/detect-non-literal-fs-filename */ // Eslint is mistakenly detecting client opens as fs opens.
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable security/detect-non-literal-fs-filename */ // Eslint is mistakenly detecting client opens as fs opens.
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
|
|
|
@ -21,18 +21,25 @@ const badConnectionStrings = [
|
|||
makeConnectionString(cn.HostName, cn.SharedAccessKeyName, 'bad'),
|
||||
];
|
||||
|
||||
function one() {
|
||||
return '0000000000000000000000000000000000000000';
|
||||
}
|
||||
function two() {
|
||||
return '1111111111111111111111111111111111111111';
|
||||
}
|
||||
|
||||
let basicDevice = {
|
||||
deviceId: 'testDevice' + Math.random(),
|
||||
deviceId: 'testDevice' + uuid.v4(),
|
||||
status: 'disabled'
|
||||
};
|
||||
|
||||
const x509Device = {
|
||||
deviceId: 'testDevice' + Math.random(),
|
||||
deviceId: 'testDevice' + uuid.v4(),
|
||||
starts: 'disabled',
|
||||
authentication: {
|
||||
x509Thumbprint : {
|
||||
primaryThumbprint: uuid.v4().replace(/-/g, ''),
|
||||
secondaryThumbprint: uuid.v4().replace(/-/g, '')
|
||||
primaryThumbprint: one(),
|
||||
secondaryThumbprint: two()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
secrets/
|
|
@ -0,0 +1,39 @@
|
|||
# Script for creating Azure resources needed to run E2E tests for the Azure IoT Node.js SDK
|
||||
|
||||
The E2E tests for the Azure IoT Node.js SDK require some Azure resources to be set up and configured.
|
||||
Running [`deploy.sh`](deploy.sh) is a convenient way to get these required resources set up. **This
|
||||
script will create resources that cost money**, so make sure to delete the resources if they are no longer required. To delete the resources, simply delete the resource group that was created by the
|
||||
script.
|
||||
|
||||
## Prerequisites
|
||||
- Azure CLI installed, added to the PATH, and logged in to the subscription where the resources are to be created. To login, run `az login` and follow
|
||||
the prompts. To set the subscription, run
|
||||
`az account set --subscription <subscription name or id>`.
|
||||
- OpenSSL installed and added to the PATH
|
||||
|
||||
## How it works
|
||||
The script makes heavy use of [Bicep](https://github.com/Azure/bicep), a domain-specific language
|
||||
for authoring ARM templates. The main bicep file is [`test-resources.bicep`](test-resources.bicep),
|
||||
which depends on the modules defined in the other bicep files. The script does the following:
|
||||
|
||||
1. Use OpenSSL to create a (self-signed) root cert and private key. The cert is valid for 2 years.
|
||||
1. Deploy the resources defined in the Bicep file using Azure CLI
|
||||
1. Add the certs to the deployed IoT Hub and DPS instance
|
||||
|
||||
A resource group with the following resources get created by the script:
|
||||
|
||||
1. A storage account with a blob storage container
|
||||
1. An IoT Hub with a verified cert and configured to allow for file upload notifications
|
||||
1. A DPS instance with a verified cert and configured to allow for devices to be provisioned on the
|
||||
Hub
|
||||
1. A Key Vault with all the necessary secrets needed to run the Node.js E2E tests, including the
|
||||
root cert value and private key
|
||||
|
||||
## Running the script
|
||||
To quickly get started with the script, run `./deploy.sh -n <desired resource group name>` and
|
||||
read and accept the prompt when asked. For more information on the usage, run `./deploy.sh -h`.
|
||||
|
||||
## Fetching secrets to run E2E tests
|
||||
To fetch the secrets needed to run the E2E tests, simply run `source get-env.sh <keyvault name>`.
|
||||
The name of the Key Vault should have been printed by [`deploy.sh`](deploy.sh). Alternatively,
|
||||
you can use the Azure Portal or Azure CLI to find the Key Vault name.
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"tool": "Credential Scanner",
|
||||
"suppressions": [
|
||||
{
|
||||
"file": "\\test-resources.bicep",
|
||||
"_justification": "Bicep file containing fake shared access tokens"
|
||||
},
|
||||
{
|
||||
"file": "\\deploy.sh",
|
||||
"_justification": "Bash script containing fake shared access tokens"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
# Copyright (c) Microsoft. All rights reserved.
|
||||
# Licensed under the MIT license. See LICENSE file in the project root for
|
||||
# full license information.
|
||||
script_dir=$(cd "$(dirname "$0")" && pwd)
|
||||
which az > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
printf "Azure CLI must be installed and added to PATH\n"
|
||||
exit 1
|
||||
fi
|
||||
set -e
|
||||
|
||||
function usage {
|
||||
printf "usage: $0 [flags]\n\n"
|
||||
printf "flags:\n"
|
||||
printf " --help, -h Show this help message\n"
|
||||
printf " --rg-name, -n Name of the resource group to use. Will be created if needed. (required)\n"
|
||||
printf " Note: A resource group can only hold a single set of E2E resources.\n"
|
||||
printf " --location, -l Deploy to specific Azure region (optional, default is westus2)\n"
|
||||
}
|
||||
|
||||
|
||||
# process args
|
||||
location=westus2
|
||||
|
||||
while [ "$1" != "" ]; do
|
||||
case $1 in
|
||||
-l | --location)
|
||||
location=$2
|
||||
shift; shift;
|
||||
;;
|
||||
|
||||
-n | --rg-name)
|
||||
rgName=$2
|
||||
shift; shift;
|
||||
;;
|
||||
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
*)
|
||||
printf "Unexpected argument: $1\n"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$rgName" == "" ]; then
|
||||
printf "Expected argument rg-name is missing\n"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# print warning
|
||||
printf "WARNING\n"
|
||||
printf "This script will deploy Azure resources into\n"
|
||||
printf "Subscription: $(az account show --query "name" -o tsv)\n"
|
||||
printf "Resource Group: $rgName\n"
|
||||
printf "Region: $location\n"
|
||||
printf "(Use 'az account list' and 'az account set' to change the subscription.)\n"
|
||||
read -p 'Press [Enter] to continue or ctrl-c to break'
|
||||
|
||||
|
||||
# create certs
|
||||
printf "Creating certs...\n"
|
||||
mkdir -p ${script_dir}/secrets/{certs,env}
|
||||
openssl req \
|
||||
-new \
|
||||
-newkey rsa:4096 \
|
||||
-days 730 \
|
||||
-nodes \
|
||||
-x509 \
|
||||
-subj '/CN=Azure IoT Test Only' \
|
||||
-keyout ${script_dir}/secrets/certs/azure-iot-test-only.key \
|
||||
-out ${script_dir}/secrets/certs/azure-iot-test-only.cert.pem > /dev/null 2>&1
|
||||
root_cert=$(printf "%s" $(base64 -i ${script_dir}/secrets/certs/azure-iot-test-only.cert.pem))
|
||||
private_key=$(printf "%s" $(base64 -i ${script_dir}/secrets/certs/azure-iot-test-only.key))
|
||||
|
||||
|
||||
# start deployment
|
||||
deploymentName="IoT-E2E-$(printf $RANDOM)"
|
||||
|
||||
printf "Deploying Azure resources...\n"
|
||||
deployment_out=$(az deployment sub create --only-show-errors \
|
||||
-f ${script_dir}/test-resources.bicep \
|
||||
-l $location \
|
||||
-n $deploymentName \
|
||||
-p \
|
||||
rgName=$rgName \
|
||||
alias=$(az account show --query '{user:user.name}' -o tsv) \
|
||||
userObjectId=$(az ad signed-in-user show --query id -o tsv) \
|
||||
rootCertValue=$root_cert \
|
||||
rootCertPrivateKey=$private_key)
|
||||
|
||||
iot_hub_name=$(printf "$deployment_out" | jq -r .properties.outputs.iotHubName.value)
|
||||
key_vault_name=$(printf "$deployment_out" | jq -r .properties.outputs.keyVaultName.value)
|
||||
iothub_connection_string=$(printf "$deployment_out" | jq -r .properties.outputs.iotHubConnectionString.value)
|
||||
eventhub_connection_string=$(printf "$deployment_out" | jq -r .properties.outputs.eventHubConnectionString.value)
|
||||
storage_connection_string=$(printf "$deployment_out" | jq -r .properties.outputs.storageConnectionString.value)
|
||||
|
||||
|
||||
# add cert to IoT Hub
|
||||
printf "Adding cert to IoT Hub...\n"
|
||||
az iot hub certificate create --only-show-errors -v \
|
||||
--hub-name $iot_hub_name \
|
||||
-g $rgName \
|
||||
-n azure-iot-test-only \
|
||||
-p ${script_dir}/secrets/certs/azure-iot-test-only.cert.pem
|
||||
|
||||
|
||||
# create activation scripts
|
||||
printf "Creating activation scripts...\n"
|
||||
|
||||
# fake secrets
|
||||
iot_provisioning_device_endpoint="global.azure-devices-provisioning.net"
|
||||
iothub_conn_string_invalid_cert="HostName=invalidcertiothub1.westus.cloudapp.azure.com;SharedAccessKeyName=iothubowner;SharedAccessKey=Fk1H0asPeeAwlRkUMTybJasksTYTd13cgI7SsteB05U="
|
||||
iothub_device_conn_string_invalid_cert="HostName=invalidcertiothub1.westus.cloudapp.azure.com;DeviceId=DoNotDelete1;SharedAccessKey=zWmeTGWmjcgDG1dpuSCVjc5ZY4TqVnKso5+g1wt/K3E="
|
||||
|
||||
pushd ${script_dir}/secrets/env/ > /dev/null 2>&1
|
||||
# PS
|
||||
printf "Set-Item -Path Env:IOTHUB_CA_ROOT_CERT -Value '$root_cert'\r\n" >> activate.ps1
|
||||
printf "Set-Item -Path Env:IOTHUB_CA_ROOT_CERT_KEY -Value '$private_key'\r\n" >> activate.ps1
|
||||
printf "Set-Item -Path Env:IOTHUB_CONNECTION_STRING -Value '$iothub_connection_string'\r\n" >> activate.ps1
|
||||
printf "Set-Item -Path Env:EVENTHUB_CONNECTION_STRING -Value '$eventhub_connection_string'\r\n" >> activate.ps1
|
||||
printf "Set-Item -Path Env:STORAGE_CONNECTION_STRING -Value '$storage_connection_string'\r\n" >> activate.ps1
|
||||
printf "Set-Item -Path Env:IOTHUB_CONN_STRING_INVALID_CERT -Value '$iothub_conn_string_invalid_cert'\r\n" >> activate.ps1
|
||||
printf "Set-Item -Path Env:IOTHUB_DEVICE_CONN_STRING_INVALID_CERT -Value '$iothub_device_conn_string_invalid_cert'\r\n" >> activate.ps1
|
||||
|
||||
# CMD
|
||||
printf "set IOTHUB_CA_ROOT_CERT=$root_cert\r\n" >> activate.cmd
|
||||
printf "set IOTHUB_CA_ROOT_CERT_KEY=$private_key\r\n" >> activate.cmd
|
||||
printf "set IOTHUB_CONNECTION_STRING=$iothub_connection_string\r\n" >> activate.cmd
|
||||
printf "set EVENTHUB_CONNECTION_STRING=$eventhub_connection_string\r\n" >> activate.cmd
|
||||
printf "set STORAGE_CONNECTION_STRING=$storage_connection_string\r\n" >> activate.cmd
|
||||
printf "set IOTHUB_CONN_STRING_INVALID_CERT=$iothub_conn_string_invalid_cert\r\n" >> activate.cmd
|
||||
printf "set IOTHUB_DEVICE_CONN_STRING_INVALID_CERT=$iothub_device_conn_string_invalid_cert\r\n" >> activate.cmd
|
||||
|
||||
# BASH
|
||||
printf "#!/bin/bash\n" > activate
|
||||
printf "export IOTHUB_CA_ROOT_CERT='$root_cert'\n" >> activate
|
||||
printf "export IOTHUB_CA_ROOT_CERT_KEY='$private_key'\n" >> activate
|
||||
printf "export IOTHUB_CONNECTION_STRING='$iothub_connection_string'\n" >> activate
|
||||
printf "export EVENTHUB_CONNECTION_STRING='$eventhub_connection_string'\n" >> activate
|
||||
printf "export STORAGE_CONNECTION_STRING='$storage_connection_string'\n" >> activate
|
||||
printf "export IOTHUB_CONN_STRING_INVALID_CERT='$iothub_conn_string_invalid_cert'\n" >> activate
|
||||
printf "export IOTHUB_DEVICE_CONN_STRING_INVALID_CERT='$iothub_device_conn_string_invalid_cert'\n" >> activate
|
||||
|
||||
# JSON
|
||||
printf "{\n" > env.json
|
||||
printf " \"IOTHUB_CA_ROOT_CERT\": \"$root_cert\",\n" >> env.json
|
||||
printf " \"IOTHUB_CA_ROOT_CERT_KEY\": \"$private_key\",\n" >> env.json
|
||||
printf " \"IOTHUB_CONNECTION_STRING\": \"$iothub_connection_string\",\n" >> env.json
|
||||
printf " \"EVENTHUB_CONNECTION_STRING\": \"$eventhub_connection_string\",\n" >> env.json
|
||||
printf " \"STORAGE_CONNECTION_STRING\": \"$storage_connection_string\",\n" >> env.json
|
||||
printf " \"IOTHUB_CONN_STRING_INVALID_CERT\": \"$iothub_conn_string_invalid_cert\",\n" >> env.json
|
||||
printf " \"IOTHUB_DEVICE_CONN_STRING_INVALID_CERT\": \"$iothub_device_conn_string_invalid_cert\"\n" >> env.json
|
||||
printf "}\n" >> env.json
|
||||
|
||||
popd > /dev/null 2>&1
|
||||
|
||||
printf "Done!\n"
|
||||
printf "WARNING: The secrets directory contains secret values. Do not check-in this directory.\n"
|
||||
printf "Depending on your environment, activate the E2E test environment by running the following\n"
|
||||
printf "Bash: source secrets/env/activate\n"
|
||||
printf "PowerShell: secrets/env/activate.ps1\n"
|
||||
printf "CMD: secrets/env/activate.cmd\n"
|
||||
printf "Alternatively, you can retreive the environment variables from secrets/env/env.json\n"
|
||||
printf "or from the Key Vault named $key_vault_name.\n"
|
|
@ -0,0 +1,28 @@
|
|||
@minLength(3)
|
||||
@maxLength(64)
|
||||
param name string
|
||||
|
||||
@secure()
|
||||
@description('The connection string of the IoT Hub to link to this DPS instance')
|
||||
param iotHubConnectionString string
|
||||
|
||||
resource dps 'Microsoft.Devices/provisioningServices@2020-03-01' = {
|
||||
name: name
|
||||
location: resourceGroup().location
|
||||
sku: {
|
||||
name: 'S1'
|
||||
}
|
||||
properties: {
|
||||
iotHubs: [
|
||||
{
|
||||
connectionString: iotHubConnectionString
|
||||
location: resourceGroup().location
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
output idScope string = dps.properties.idScope
|
||||
var key = listKeys(resourceId('Microsoft.Devices/provisioningServices/keys', dps.name, 'provisioningserviceowner'), dps.apiVersion).primaryKey
|
||||
output connectionString string = 'HostName=${dps.properties.serviceOperationsHostName};SharedAccessKeyName=provisioningserviceowner;SharedAccessKey=${key}'
|
||||
output name string = name
|
|
@ -0,0 +1,10 @@
|
|||
# Copyright (c) Microsoft. All rights reserved.
|
||||
# Licensed under the MIT license. See LICENSE file in the project root for
|
||||
# full license information.
|
||||
|
||||
export IOTHUB_CA_ROOT_CERT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-CA-ROOT-CERT)
|
||||
export IOTHUB_CA_ROOT_CERT_KEY=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-CA-ROOT-CERT-KEY)
|
||||
export IOTHUB_CONNECTION_STRING=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-CONNECTION-STRING)
|
||||
export STORAGE_CONNECTION_STRING=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name STORAGE-CONNECTION-STRING)
|
||||
export IOTHUB_CONN_STRING_INVALID_CERT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-CONN-STRING-INVALID-CERT)
|
||||
export IOTHUB_DEVICE_CONN_STRING_INVALID_CERT=$(az keyvault secret show --query '{value:value}' --output tsv --vault-name $1 --name IOTHUB-DEVICE-CONN-STRING-INVALID-CERT)
|
|
@ -0,0 +1,56 @@
|
|||
@minLength(3)
|
||||
@maxLength(50)
|
||||
@description('The name of the IoT Hub to be created')
|
||||
param name string
|
||||
|
||||
@secure()
|
||||
@description('The connection string for the storage account')
|
||||
param storageConnectionString string
|
||||
|
||||
resource iotHub 'Microsoft.Devices/IotHubs@2021-07-01' = {
|
||||
name: name
|
||||
location: resourceGroup().location
|
||||
sku: {
|
||||
name: 'S1'
|
||||
capacity: 2
|
||||
}
|
||||
properties: {
|
||||
enableFileUploadNotifications: true
|
||||
storageEndpoints: {
|
||||
'$default': {
|
||||
sasTtlAsIso8601: 'PT1H'
|
||||
connectionString: storageConnectionString
|
||||
containerName: 'aziotbld'
|
||||
}
|
||||
}
|
||||
routing: {
|
||||
routes: [
|
||||
{
|
||||
name: 'twin-update-event'
|
||||
source: 'TwinChangeEvents'
|
||||
condition: 'true'
|
||||
endpointNames: [
|
||||
'events'
|
||||
]
|
||||
isEnabled: true
|
||||
}
|
||||
]
|
||||
fallbackRoute: {
|
||||
name: '$fallback'
|
||||
source: 'DeviceMessages'
|
||||
condition: 'true'
|
||||
endpointNames: [
|
||||
'events'
|
||||
]
|
||||
isEnabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var sharedAccessKeyName = '${listKeys(iotHub.id, '2020-04-01').value[0].keyName}'
|
||||
var sharedAccessKey = '${listKeys(iotHub.id, '2020-04-01').value[0].primaryKey}'
|
||||
|
||||
output connectionString string = 'HostName=${iotHub.name}.azure-devices.net;SharedAccessKeyName=${sharedAccessKeyName};SharedAccessKey=${sharedAccessKey}'
|
||||
output eventHubConnectionString string = 'Endpoint=${iotHub.properties.eventHubEndpoints.events.endpoint};SharedAccessKeyName=${sharedAccessKeyName};SharedAccessKey=${sharedAccessKey};EntityPath=${iotHub.properties.eventHubEndpoints.events.path}'
|
||||
output name string = name
|
|
@ -0,0 +1,52 @@
|
|||
@minLength(3)
|
||||
@maxLength(24)
|
||||
@description('The name of the Key Vault to be created')
|
||||
param keyVaultName string
|
||||
|
||||
@description('Signed in user objectId')
|
||||
param userObjectId string
|
||||
|
||||
// TODO: switch to object and use items() when released in Bicep v0.5
|
||||
// https://github.com/Azure/bicep/pull/4456
|
||||
param keyVaultSecrets array
|
||||
|
||||
resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' = {
|
||||
name: keyVaultName
|
||||
location: resourceGroup().location
|
||||
properties: {
|
||||
sku: {
|
||||
family: 'A'
|
||||
name: 'standard'
|
||||
}
|
||||
tenantId: subscription().tenantId
|
||||
accessPolicies: [
|
||||
{
|
||||
objectId: userObjectId
|
||||
tenantId: subscription().tenantId
|
||||
permissions: {
|
||||
secrets: [
|
||||
'all'
|
||||
]
|
||||
certificates: [
|
||||
'all'
|
||||
]
|
||||
keys: [
|
||||
'all'
|
||||
]
|
||||
storage: [
|
||||
'all'
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
resource secrets 'secrets' = [for secret in keyVaultSecrets: {
|
||||
name: secret.name
|
||||
properties: {
|
||||
value: secret.value
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
output name string = keyVaultName
|
|
@ -0,0 +1,21 @@
|
|||
@minLength(3)
|
||||
@maxLength(24)
|
||||
@description('The name of the storage account to be created')
|
||||
param storageAccountName string
|
||||
|
||||
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' = {
|
||||
name: storageAccountName
|
||||
location: resourceGroup().location
|
||||
sku: {
|
||||
name: 'Standard_GRS'
|
||||
}
|
||||
kind: 'Storage'
|
||||
resource blobService 'blobServices' = {
|
||||
name: 'default'
|
||||
resource container 'containers' = {
|
||||
name: 'aziotbld'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output connectionString string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=${environment().suffixes.storage}'
|
|
@ -0,0 +1,96 @@
|
|||
targetScope = 'subscription'
|
||||
|
||||
@description('Signed in user alias')
|
||||
param alias string
|
||||
|
||||
@description('Signed in user objectId')
|
||||
param userObjectId string
|
||||
|
||||
@maxLength(46)
|
||||
@description('Name of the resource group to create')
|
||||
param rgName string
|
||||
|
||||
@secure()
|
||||
@description('The value of the Hub and DPS root CA cert to store in the keyvault (base64 encoded)')
|
||||
param rootCertValue string
|
||||
|
||||
@secure()
|
||||
@description('The value of the Hub and DPS root CA cert private key to store in the keyvault (base64 encoded)')
|
||||
param rootCertPrivateKey string
|
||||
|
||||
resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
|
||||
name: rgName
|
||||
location: deployment().location
|
||||
tags: {
|
||||
createdBy: alias
|
||||
}
|
||||
}
|
||||
|
||||
var shortName = take(replace(replace(rgName,'_',''),'-',''),10)
|
||||
var uniqueId = take(uniqueString(rg.id),8)
|
||||
|
||||
module storageAccount 'storage-account.bicep' = {
|
||||
scope: rg
|
||||
name: 'storageAccount'
|
||||
params: {
|
||||
storageAccountName: toLower('${shortName}${uniqueId}')
|
||||
}
|
||||
}
|
||||
|
||||
module iotHub 'iot-hub.bicep' = {
|
||||
scope: rg
|
||||
name: 'iotHub'
|
||||
params: {
|
||||
name: 'hub-${shortName}-${uniqueId}'
|
||||
storageConnectionString: storageAccount.outputs.connectionString
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var keyVaultSecrets = [
|
||||
{
|
||||
name: 'IOTHUB-CA-ROOT-CERT'
|
||||
value: rootCertValue
|
||||
}
|
||||
{
|
||||
name: 'IOTHUB-CA-ROOT-CERT-KEY'
|
||||
value: rootCertPrivateKey
|
||||
}
|
||||
{
|
||||
name: 'IOTHUB-CONNECTION-STRING'
|
||||
value: iotHub.outputs.connectionString
|
||||
}
|
||||
{
|
||||
name: 'EVENTHUB-CONNECTION-STRING'
|
||||
value: iotHub.outputs.eventHubConnectionString
|
||||
}
|
||||
{
|
||||
name: 'STORAGE-CONNECTION-STRING'
|
||||
value: storageAccount.outputs.connectionString
|
||||
}
|
||||
{
|
||||
name: 'IOTHUB-CONN-STRING-INVALID-CERT' // Fake credential
|
||||
value: 'HostName=invalidcertiothub1.westus.cloudapp.azure.com;SharedAccessKeyName=iothubowner;SharedAccessKey=Fk1H0asPeeAwlRkUMTybJasksTYTd13cgI7SsteB05U='
|
||||
}
|
||||
{
|
||||
name: 'IOTHUB-DEVICE-CONN-STRING-INVALID-CERT' // Fake credential
|
||||
value: 'HostName=invalidcertiothub1.westus.cloudapp.azure.com;DeviceId=DoNotDelete1;SharedAccessKey=zWmeTGWmjcgDG1dpuSCVjc5ZY4TqVnKso5+g1wt/K3E='
|
||||
}
|
||||
]
|
||||
|
||||
module keyVault 'key-vault.bicep' = {
|
||||
scope: rg
|
||||
name: 'keyVault'
|
||||
params: {
|
||||
keyVaultName: 'kv-${shortName}-${uniqueId}'
|
||||
keyVaultSecrets: keyVaultSecrets
|
||||
userObjectId: userObjectId
|
||||
}
|
||||
}
|
||||
|
||||
output iotHubName string = iotHub.outputs.name
|
||||
output keyVaultName string = keyVault.outputs.name
|
||||
|
||||
output iotHubConnectionString string = iotHub.outputs.connectionString
|
||||
output eventHubConnectionString string = iotHub.outputs.eventHubConnectionString
|
||||
output storageConnectionString string = storageAccount.outputs.connectionString
|
|
@ -1,227 +0,0 @@
|
|||
# Compiled object files
|
||||
*.o
|
||||
*.opp
|
||||
|
||||
# Compiled static libraries
|
||||
*.a
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
/build/release/Maven
|
||||
!/build/release/
|
||||
[Cc]make/
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
|
||||
!packages/*/build/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.log
|
||||
*.scc
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# Visual Studio user folder
|
||||
.vs
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.VC.opendb
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
|
||||
# NuGet Packages Directory
|
||||
packages/
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.[Pp]ublish.xml
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
*.jar
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
App_Data/*.mdf
|
||||
App_Data/*.ldf
|
||||
|
||||
|
||||
#LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
_Pvt_Extensions/
|
||||
ModelManifest.xml
|
||||
|
||||
# CPython & Wheels
|
||||
*.pyc
|
||||
*.pyd
|
||||
*.whl
|
||||
*.egg-info
|
||||
|
||||
# =========================
|
||||
# Windows detritus
|
||||
# =========================
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Mac desktop service store files
|
||||
.DS_Store
|
||||
|
||||
# Visual studio build artifacts
|
||||
*.tlog
|
||||
*.lastbuildstate
|
||||
*.idb
|
||||
*.exp
|
||||
*.lib
|
||||
*.dll
|
||||
|
||||
# Visual Studio Temporary files
|
||||
*.VC.db
|
||||
|
||||
# hg directories should be ignored
|
||||
**/hg/
|
||||
|
||||
# Node.js
|
||||
**/.settings/
|
||||
**/node_modules/
|
||||
**/.idea/
|
||||
**/coverage/
|
||||
**/.nyc_output/
|
||||
**/package-lock.json
|
||||
|
||||
# VS Code stuff
|
||||
**/typings/**
|
||||
**/.vscode/**
|
||||
# C/C++ extension for VS Code
|
||||
.browse.VC.db*
|
||||
|
||||
# Certificates
|
||||
**/*.pem
|
||||
|
||||
# Typescript
|
||||
**/*.map
|
||||
|
||||
# Typescript compiler output files
|
||||
**/dist/
|
||||
|
||||
device/samples/typescript/dist
|
||||
|
||||
# Build artifacts
|
||||
build/build_parallel/temp
|
||||
|
||||
# lerna
|
||||
lerna-debug.log
|
||||
|
||||
# mocha
|
||||
**/test-results.*.xml
|
||||
|
||||
# longhaul settings
|
||||
**/_settings.json
|
||||
|
|
@ -17,42 +17,11 @@ jobs:
|
|||
versionSpec: '14.x'
|
||||
|
||||
- script: |
|
||||
npm install --global node-gyp
|
||||
npm install --global lerna
|
||||
npm install
|
||||
displayName: 'Install Dependencies'
|
||||
|
||||
- script: |
|
||||
lerna bootstrap --hoist
|
||||
lerna run build
|
||||
displayName: 'Bootstrap & Build'
|
||||
|
||||
- script: 'lerna run ci'
|
||||
npm run ci
|
||||
displayName: 'Unit & Integration Tests'
|
||||
env:
|
||||
IOTHUB_CONNECTION_STRING: $(IOTHUB-CONNECTION-STRING)
|
||||
|
||||
- script: 'lerna run e2e'
|
||||
displayName: 'E2E Tests'
|
||||
env:
|
||||
IOTHUB_CA_ROOT_CERT: $(IOTHUB-CA-ROOT-CERT)
|
||||
IOTHUB_CA_ROOT_CERT_KEY: $(IOTHUB-CA-ROOT-CERT-KEY)
|
||||
IOT_PROVISIONING_DEVICE_ENDPOINT: $(IOT-PROVISIONING-DEVICE-ENDPOINT)
|
||||
IOTHUB_CONNECTION_STRING: $(IOTHUB-CONNECTION-STRING)
|
||||
STORAGE_CONNECTION_STRING: $(STORAGE-CONNECTION-STRING)
|
||||
IOT_PROVISIONING_DEVICE_IDSCOPE: $(IOT-PROVISIONING-DEVICE-IDSCOPE)
|
||||
IOT_PROVISIONING_ROOT_CERT: $(IOT-PROVISIONING-ROOT-CERT)
|
||||
IOT_PROVISIONING_ROOT_CERT_KEY: $(IOT-PROVISIONING-ROOT-CERT-KEY)
|
||||
IOT_PROVISIONING_SERVICE_CONNECTION_STRING: $(IOT-PROVISIONING-SERVICE-CONNECTION-STRING)
|
||||
DPS_CONN_STRING_INVALID_CERT: $(DPS-CONN-STRING-INVALID-CERT)
|
||||
DPS_GLOBAL_DEVICE_ENDPOINT_INVALID_CERT: $(DPS-GLOBAL-DEVICE-ENDPOINT-INVALID-CERT)
|
||||
IOTHUB_CONN_STRING_INVALID_CERT: $(IOTHUB-CONN-STRING-INVALID-CERT)
|
||||
IOTHUB_DEVICE_CONN_STRING_INVALID_CERT: $(IOTHUB-DEVICE-CONN-STRING-INVALID-CERT)
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results | Mocha'
|
||||
inputs:
|
||||
testResultsFiles: 'e2etests/test-results.*.xml'
|
||||
mergeTestResults: true
|
||||
testRunTitle: 'E2E Tests - Linux'
|
||||
condition: succeededOrFailed()
|
||||
|
|
|
@ -17,46 +17,15 @@ jobs:
|
|||
|
||||
- powershell: |
|
||||
runas.exe /savecred /user:administrator
|
||||
npm install --global node-gyp@6.1.0
|
||||
npm install --global lerna
|
||||
npm install
|
||||
displayName: 'Install Dependencies'
|
||||
|
||||
- script: |
|
||||
call lerna bootstrap --hoist
|
||||
call lerna run build
|
||||
displayName: 'Bootstrap & Build'
|
||||
|
||||
- script: 'call lerna run ci'
|
||||
npm run ci'
|
||||
displayName: 'Unit & Integration Tests'
|
||||
env:
|
||||
IOTHUB_CONNECTION_STRING: $(IOTHUB-CONNECTION-STRING)
|
||||
|
||||
- script: 'lerna run e2e'
|
||||
displayName: 'E2E Tests'
|
||||
env:
|
||||
IOTHUB_CA_ROOT_CERT: $(IOTHUB-CA-ROOT-CERT)
|
||||
IOTHUB_CA_ROOT_CERT_KEY: $(IOTHUB-CA-ROOT-CERT-KEY)
|
||||
IOT_PROVISIONING_DEVICE_ENDPOINT: $(IOT-PROVISIONING-DEVICE-ENDPOINT)
|
||||
IOTHUB_CONNECTION_STRING: $(IOTHUB-CONNECTION-STRING)
|
||||
STORAGE_CONNECTION_STRING: $(STORAGE-CONNECTION-STRING)
|
||||
IOT_PROVISIONING_DEVICE_IDSCOPE: $(IOT-PROVISIONING-DEVICE-IDSCOPE)
|
||||
IOT_PROVISIONING_ROOT_CERT: $(IOT-PROVISIONING-ROOT-CERT)
|
||||
IOT_PROVISIONING_ROOT_CERT_KEY: $(IOT-PROVISIONING-ROOT-CERT-KEY)
|
||||
IOT_PROVISIONING_SERVICE_CONNECTION_STRING: $(IOT-PROVISIONING-SERVICE-CONNECTION-STRING)
|
||||
DPS_CONN_STRING_INVALID_CERT: $(DPS-CONN-STRING-INVALID-CERT)
|
||||
DPS_GLOBAL_DEVICE_ENDPOINT_INVALID_CERT: $(DPS-GLOBAL-DEVICE-ENDPOINT-INVALID-CERT)
|
||||
IOTHUB_CONN_STRING_INVALID_CERT: $(IOTHUB-CONN-STRING-INVALID-CERT)
|
||||
IOTHUB_DEVICE_CONN_STRING_INVALID_CERT: $(IOTHUB-DEVICE-CONN-STRING-INVALID-CERT)
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results | Mocha'
|
||||
inputs:
|
||||
testResultsFiles: 'e2etests/test-results.*.xml'
|
||||
mergeTestResults: true
|
||||
testRunTitle: 'E2E Tests - Windows'
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
condition: coalesce(variables.release, False)
|
||||
inputs:
|
||||
|
|
Загрузка…
Ссылка в новой задаче