This commit is contained in:
sushilraje 2019-04-03 17:17:21 -07:00 коммит произвёл GitHub
Родитель 37cf899f43
Коммит 4e474afc97
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
111 изменённых файлов: 1689 добавлений и 1988 удалений

1
asa-manager/.vscode/launch.json поставляемый
Просмотреть файл

@ -43,6 +43,7 @@
},
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceRoot}/WebService/bin/Debug/netcoreapp2.0/Microsoft.Azure.IoTSolutions.AsaManager.WebService.dll",
"args": [],
"cwd": "${workspaceRoot}/WebService/bin/Debug/netcoreapp2.0",

Просмотреть файл

@ -23,28 +23,38 @@ namespace Microsoft.Azure.IoTSolutions.AsaManager.Services.Runtime
private readonly IConfigurationRoot configuration;
private readonly ILogger log;
// Key Vault
private KeyVault keyVault;
// Constants
private const string CLIENT_ID = "KeyVault:aadAppId";
private const string CLIENT_SECRET = "KeyVault:aadAppSecret";
private const string KEY_VAULT_NAME = "KeyVault:name";
public ConfigData(ILogger logger)
{
this.log = logger;
// More info about configuration at
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddIniFile("appsettings.ini", optional: true, reloadOnChange: true);
this.configuration = configurationBuilder.Build();
// Set up Key Vault
this.SetUpKeyVault();
}
public string GetString(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
var value = this.GetSecrets(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
public bool GetBool(string key, bool defaultValue = false)
{
var value = this.GetString(key, defaultValue.ToString()).ToLowerInvariant();
var value = this.GetSecrets(key, defaultValue.ToString()).ToLowerInvariant();
var knownTrue = new HashSet<string> { "true", "t", "yes", "y", "1", "-1" };
var knownFalse = new HashSet<string> { "false", "f", "no", "n", "0" };
@ -59,7 +69,7 @@ namespace Microsoft.Azure.IoTSolutions.AsaManager.Services.Runtime
{
try
{
return Convert.ToInt32(this.GetString(key, defaultValue.ToString()));
return Convert.ToInt32(this.GetSecrets(key, defaultValue.ToString()));
}
catch (Exception e)
{
@ -67,6 +77,45 @@ namespace Microsoft.Azure.IoTSolutions.AsaManager.Services.Runtime
}
}
private void SetUpKeyVault()
{
var clientId = this.GetEnvironmentVariable(CLIENT_ID, string.Empty);
var clientSecret = this.GetEnvironmentVariable(CLIENT_SECRET, string.Empty);
var keyVaultName = this.GetEnvironmentVariable(KEY_VAULT_NAME, string.Empty);
// Initailize key vault
this.keyVault = new KeyVault(keyVaultName, clientId, clientSecret, this.log);
}
private string GetSecrets(string key, string defaultValue = "")
{
string value = string.Empty;
value = this.GetLocalVariable(key, defaultValue);
// If secrets are not found locally, search in Key-Vault
if (string.IsNullOrEmpty(value))
{
log.Warn($"Value for secret {key} not found in local env. " +
$" Trying to get the secret from KeyVault.", () => { });
value = this.keyVault.GetSecret(key);
}
return !string.IsNullOrEmpty(value) ? value : defaultValue;
}
private string GetLocalVariable(string key, string defaultValue = "")
{
return this.configuration.GetValue(key, defaultValue);
}
public string GetEnvironmentVariable(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
private void ReplaceEnvironmentVariables(ref string value, string defaultValue = "")
{
if (string.IsNullOrEmpty(value)) return;

Просмотреть файл

@ -0,0 +1,70 @@
using Microsoft.Azure.IoTSolutions.AsaManager.Services.Diagnostics;
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.Azure.IoTSolutions.AsaManager.Services.Runtime
{
public class KeyVault {
// Key Vault details and access
private readonly string name;
private readonly string clientId;
private readonly string clientSecret;
private ILogger log;
// Key Vault Client
private readonly KeyVaultClient keyVaultClient;
// Constants
private const string KEY_VAULT_URI = "https://{0}.vault.azure.net/secrets/{1}";
public KeyVault(
string name,
string clientId,
string clientSecret,
ILogger logger)
{
this.name = name;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.log = logger;
this.keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(this.GetToken));
}
public string GetSecret(string secretKey)
{
secretKey = secretKey.Split(':').Last();
var uri = string.Format(KEY_VAULT_URI, this.name, secretKey);
try
{
return this.keyVaultClient.GetSecretAsync(uri).Result.Value;
}
catch (Exception e)
{
this.log.Error($"Secret {secretKey} not found in Key Vault.", ()=>{ });
return null;
}
}
//the method that will be provided to the KeyVaultClient
private async Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
ClientCredential clientCred = new ClientCredential(this.clientId, this.clientSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
{
this.log.Debug($"Failed to obtain authentication token from key vault.", () => { });
throw new System.InvalidOperationException("Failed to obtain the JWT token");
}
return result.AccessToken;
}
}
}

Просмотреть файл

@ -14,5 +14,7 @@
<PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="1.10.0" />
<PackageReference Include="Microsoft.Azure.EventHubs.Processor" Version="2.0.1" />
<PackageReference Include="Microsoft.Azure.EventHubs" Version="2.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="4.5.0" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="2.0.6" />
</ItemGroup>
</Project>

Просмотреть файл

@ -13,18 +13,11 @@
"launchBrowser": true,
"launchUrl": "http://localhost:9024/v1/status",
"environmentVariables": {
"PCS_TELEMETRY_WEBSERVICE_URL": "http://localhost:9004/v1",
"PCS_CONFIG_WEBSERVICE_URL": "http://localhost:9005/v1",
"PCS_IOTHUBMANAGER_WEBSERVICE_URL": "http://localhost:9002/v1",
"PCS_TELEMETRY_DOCUMENTDB_CONNSTRING": "$(PCS_TELEMETRY_DOCUMENTDB_CONNSTRING)",
"PCS_TELEMETRY_STORAGE_TYPE": "$(PCS_TELEMETRY_STORAGE_TYPE)",
"PCS_ASA_DATA_AZUREBLOB_ACCOUNT": "$(PCS_ASA_DATA_AZUREBLOB_ACCOUNT)",
"PCS_ASA_DATA_AZUREBLOB_KEY": "$(PCS_ASA_DATA_AZUREBLOB_KEY)",
"PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX": "$(PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX)",
"PCS_EVENTHUB_CONNSTRING": "$(PCS_EVENTHUB_CONNSTRING)",
"PCS_EVENTHUB_NAME": "$(PCS_EVENTHUB_NAME)"
"PCS_KEYVAULT_NAME": "$(PCS_KEYVAULT_NAME)",
"PCS_AAD_APPID": "$(PCS_AAD_APPID)",
"PCS_AAD_APPSECRET": "$(PCS_AAD_APPSECRET)"
},
"applicationUrl": "http://localhost:9024/v1/status"
}
}
}
}

Просмотреть файл

@ -5,6 +5,7 @@ using System.Collections.Generic;
using Microsoft.Azure.IoTSolutions.AsaManager.Services.Diagnostics;
using Microsoft.Azure.IoTSolutions.AsaManager.Services.Runtime;
using Microsoft.Azure.IoTSolutions.AsaManager.WebService.Auth;
using System.Threading.Tasks;
// TODO: tests
// TODO: handle errors
@ -30,73 +31,72 @@ namespace Microsoft.Azure.IoTSolutions.AsaManager.WebService.Runtime
public class Config : IConfig
{
private const string APPLICATION_KEY = "AsaManagerService:";
private const string PORT_KEY = APPLICATION_KEY + "webservice_port";
private const string PORT_KEY = APPLICATION_KEY + "webservicePort";
private const string LOGGING_KEY = APPLICATION_KEY + "Logging:";
private const string LOGGING_LOGLEVEL_KEY = LOGGING_KEY + "LogLevel";
private const string LOGGING_INCLUDEPROCESSID_KEY = LOGGING_KEY + "IncludeProcessId";
private const string LOGGING_DATEFORMAT_KEY = LOGGING_KEY + "DateFormat";
private const string LOGGING_BLACKLIST_PREFIX_KEY = LOGGING_KEY + "BWListPrefix";
private const string LOGGING_BLACKLIST_SOURCES_KEY = LOGGING_KEY + "BlackListSources";
private const string LOGGING_WHITELIST_SOURCES_KEY = LOGGING_KEY + "WhiteListSources";
private const string LOGGING_EXTRADIAGNOSTICS_KEY = LOGGING_KEY + "ExtraDiagnostics";
private const string LOGGING_EXTRADIAGNOSTICSPATH_KEY = LOGGING_KEY + "ExtraDiagnosticsPath";
private const string LOGGING_LOGLEVEL_KEY = LOGGING_KEY + "logLevel";
private const string LOGGING_INCLUDEPROCESSID_KEY = LOGGING_KEY + "includeProcessId";
private const string LOGGING_DATEFORMAT_KEY = LOGGING_KEY + "dateFormat";
private const string LOGGING_BLACKLIST_PREFIX_KEY = LOGGING_KEY + "bwListPrefix";
private const string LOGGING_BLACKLIST_SOURCES_KEY = LOGGING_KEY + "blackListSources";
private const string LOGGING_WHITELIST_SOURCES_KEY = LOGGING_KEY + "whiteListSources";
private const string LOGGING_EXTRADIAGNOSTICS_KEY = LOGGING_KEY + "extraDiagnostics";
private const string LOGGING_EXTRADIAGNOSTICSPATH_KEY = LOGGING_KEY + "extraDiagnosticsPath";
private const string CLIENT_AUTH_KEY = APPLICATION_KEY + "ClientAuth:";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "cors_whitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "auth_type";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "auth_required";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "corsWhitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "authType";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "authRequired";
private const string JWT_KEY = APPLICATION_KEY + "ClientAuth:JWT:";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowed_algorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "issuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "audience";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clock_skew_seconds";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowedAlgorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "authIssuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "aadAppId";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clockSkewSeconds";
private const string EVENTHUB_KEY = APPLICATION_KEY + "EventHub:";
private const string EVENTHUB_CONNECTION_KEY = EVENTHUB_KEY + "connection_string";
private const string EVENTHUB_NAME = EVENTHUB_KEY + "name";
private const string EVENTHUB_CHECKPOINT_INTERVAL_MS = EVENTHUB_KEY + "checkpoint_interval_msecs";
private const string EVENTHUB_CONNECTION_KEY = EVENTHUB_KEY + "messagesEventHubConnectionString";
private const string EVENTHUB_NAME = EVENTHUB_KEY + "messagesEventHubName";
private const string EVENTHUB_CHECKPOINT_INTERVAL_MS = EVENTHUB_KEY + "checkpointIntervalMsecs";
private const string BLOB_STORAGE_KEY = APPLICATION_KEY + "BlobStorage:";
private const string STORAGE_REFERENCE_DATA_CONTAINER_KEY = BLOB_STORAGE_KEY + "reference_data_container";
private const string STORAGE_EVENTHUB_CONTAINER_KEY = BLOB_STORAGE_KEY + "eventhub_container";
private const string STORAGE_ACCOUNT_NAME_KEY = BLOB_STORAGE_KEY + "account_name";
private const string STORAGE_ACCOUNT_KEY_KEY = BLOB_STORAGE_KEY + "account_key";
private const string STORAGE_ACCOUNT_ENDPOINT_KEY = BLOB_STORAGE_KEY + "account_endpoint";
private const string STORAGE_DEVICE_GROUPS_FILE_NAME = BLOB_STORAGE_KEY + "reference_data_device_groups_file_name";
private const string STORAGE_RULES_FILE_NAME = BLOB_STORAGE_KEY + "reference_data_rules_file_name";
private const string STORAGE_DATE_FORMAT = BLOB_STORAGE_KEY + "reference_data_date_format";
private const string STORAGE_TIME_FORMAT = BLOB_STORAGE_KEY + "reference_data_time_format";
private const string STORAGE_REFERENCE_DATA_CONTAINER_KEY = BLOB_STORAGE_KEY + "referenceDataContainer";
private const string STORAGE_EVENTHUB_CONTAINER_KEY = BLOB_STORAGE_KEY + "eventhubContainer";
private const string STORAGE_ACCOUNT_NAME_KEY = BLOB_STORAGE_KEY + "storageAccountName";
private const string STORAGE_ACCOUNT_KEY_KEY = BLOB_STORAGE_KEY + "storageAccountKey";
private const string STORAGE_ACCOUNT_ENDPOINT_KEY = BLOB_STORAGE_KEY + "storageEndpointSuffix";
private const string STORAGE_DEVICE_GROUPS_FILE_NAME = BLOB_STORAGE_KEY + "referenceDataDeviceGroupsFileName";
private const string STORAGE_RULES_FILE_NAME = BLOB_STORAGE_KEY + "referenceDataRulesFileName";
private const string STORAGE_DATE_FORMAT = BLOB_STORAGE_KEY + "referenceDataDateFormat";
private const string STORAGE_TIME_FORMAT = BLOB_STORAGE_KEY + "referenceDataTimeFormat";
private const string STORAGE_ACCOUNT_ENDPOINT_DEFAULT = "core.windows.net";
private const string MESSAGES_KEY = APPLICATION_KEY + "MessagesStorage:";
private const string MESSAGES_STORAGE_TYPE_KEY = MESSAGES_KEY + "storageType";
private const string MESSAGES_STORAGE_TYPE_KEY = MESSAGES_KEY + "telemetryStorageType";
private const string ALARMS_KEY = APPLICATION_KEY + "AlarmsStorage:";
private const string ALARMS_STORAGE_TYPE_KEY = ALARMS_KEY + "storageType";
private const string ALARMS_STORAGE_TYPE_KEY = ALARMS_KEY + "alarmsStorageType";
private const string DEVICE_TELEMETRY_KEY = "DeviceTelemetryService:";
private const string DEVICE_TELEMETRY_WEBSERVICE_URL_KEY = DEVICE_TELEMETRY_KEY + "webservice_url";
private const string DEVICE_TELEMETRY_WEBSERVICE_TIMEOUT_KEY = DEVICE_TELEMETRY_KEY + "webservice_timeout_msecs";
private const string EXTERNAL_DEPENDENCIES_KEY = "ExternalDependencies:";
private const string DEVICE_TELEMETRY_WEBSERVICE_URL_KEY = EXTERNAL_DEPENDENCIES_KEY + "telemetryWebServiceUrl";
private const string DEVICE_TELEMETRY_WEBSERVICE_TIMEOUT_KEY = EXTERNAL_DEPENDENCIES_KEY + "telemetryWebServiceTimeoutMsecs";
private const string CONFIG_KEY = "PCSConfigurationService:";
private const string CONFIG_WEBSERVICE_URL_KEY = CONFIG_KEY + "webservice_url";
private const string CONFIG_WEBSERVICE_TIMEOUT_KEY = CONFIG_KEY + "webservice_timeout_msecs";
private const string CONFIG_WEBSERVICE_URL_KEY = EXTERNAL_DEPENDENCIES_KEY + "configWebServiceUrl";
private const string CONFIG_WEBSERVICE_TIMEOUT_KEY = EXTERNAL_DEPENDENCIES_KEY + "configWebServiceTimeoutMsecs";
private const string IOTHUB_MANAGER_KEY = "IoTHubManagerService:";
private const string IOTHUB_MANAGER_WEBSERVICE_URL_KEY = IOTHUB_MANAGER_KEY + "webservice_url";
private const string IOTHUB_MANAGER_WEBSERVICE_TIMEOUT_KEY = IOTHUB_MANAGER_KEY + "webservice_timeout_msecs";
private const string IOTHUB_MANAGER_RETRY_COUNT = IOTHUB_MANAGER_KEY + "retry_count";
private const string IOTHUB_MANAGER_INITIAL_RETRY_INTERVAL_MS = IOTHUB_MANAGER_KEY + "initial_retry_interval_msecs";
private const string IOTHUB_MANAGER_RETRY_INCREASE_FACTOR = IOTHUB_MANAGER_KEY + "retry_increase_factor";
private const string IOTHUB_MANAGER_WEBSERVICE_URL_KEY = EXTERNAL_DEPENDENCIES_KEY + "iothubmanagerWebServiceUrl";
private const string IOTHUB_MANAGER_WEBSERVICE_TIMEOUT_KEY = EXTERNAL_DEPENDENCIES_KEY + "iothubmanagerTimeoutMsecs";
private const string IOTHUB_MANAGER_RETRY_COUNT = EXTERNAL_DEPENDENCIES_KEY + "retryCount";
private const string IOTHUB_MANAGER_INITIAL_RETRY_INTERVAL_MS = EXTERNAL_DEPENDENCIES_KEY + "initialRetryIntervalMsecs";
private const string IOTHUB_MANAGER_RETRY_INCREASE_FACTOR = EXTERNAL_DEPENDENCIES_KEY + "retryIncreaseFactor";
// Values common to all the tables (messages and alarms)
private const string COSMOSDBSQL_CONNSTRING_KEY = "cosmosdbsql_connstring";
private const string COSMOSDBSQL_DATABASE_KEY = "cosmosdbsql_database";
private const string COSMOSDBSQL_CONSISTENCY_KEY = "cosmosdbsql_consistency_level";
private const string COSMOSDBSQL_COLLECTION_KEY = "cosmosdbsql_collection";
private const string COSMOSDBSQL_RUS_KEY = "cosmosdbsql_RUs";
private const string COSMOSDBSQL_CONNSTRING_KEY = "documentDBConnectionString";
private const string COSMOSDBSQL_DATABASE_KEY = "documentDBDatabase";
private const string COSMOSDBSQL_CONSISTENCY_KEY = "documentDBConsistencyLevel";
private const string COSMOSDBSQL_COLLECTION_KEY = "documentDBCollection";
private const string COSMOSDBSQL_RUS_KEY = "documentDBRUs";
// Simple keys used internally in this class, these don't appear in the config file
private const string MESSAGES = "messages";

Просмотреть файл

@ -1,109 +1,109 @@
[AsaManagerService]
webservice_port = 9024
webservicePort = 9024
; Storage where ASA will write telemetry messages
; The application is responsible for preparing this storage before the ASA Job starts
[AsaManagerService:MessagesStorage]
storageType = "${PCS_TELEMETRY_STORAGE_TYPE}"
cosmosdbsql_connstring = "${PCS_TELEMETRY_DOCUMENTDB_CONNSTRING}"
cosmosdbsql_database = "pcs-iothub-stream"
cosmosdbsql_collection = "messages"
telemetryStorageType = ""
documentDBConnectionString = ""
documentDBDatabase = "pcs-iothub-stream"
documentDBCollection = "messages"
; For telemetry scenarios, eventual consistency is ok
cosmosdbsql_consistency_level = "Eventual"
documentDBConsistencyLevel = "Eventual"
; 2500 => unlimited space - see https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data
cosmosdbsql_RUs = 2500
documentDBRUs = 2500
; Storage where ASA will write alarms
; The application is responsible for preparing this storage before the ASA Job starts
[AsaManagerService:AlarmsStorage]
storageType = "CosmosDbSql"
cosmosdbsql_connstring = "${PCS_TELEMETRY_DOCUMENTDB_CONNSTRING}"
cosmosdbsql_database = "pcs-iothub-stream"
cosmosdbsql_collection = "alarms"
alarmsStorageType = "CosmosDbSql"
documentDBConnectionString = ""
documentDBdatabase = "pcs-iothub-stream"
documentDBcollection = "alarms"
; For telemetry scenarios, eventual consistency is ok
cosmosdbsql_consistency_level = "Eventual"
documentDBconsistencyLevel = "Eventual"
; 400 => fixed storage 10GB - see https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data
cosmosdbsql_RUs = 400
documentDBRUs = 400
[AsaManagerService:EventHub]
; Connection string for event hub
connection_string = ${PCS_EVENTHUB_CONNSTRING}
messagesEventHubConnectionString =
; Name of event hub
name = ${PCS_EVENTHUB_NAME}
; event hub checkpoint interval in msecs
checkpoint_interval_msecs = 60000
messagesEventHubName =
; event hub checkpoint interval in Msecs
checkpointIntervalMsecs = 60000
[AsaManagerService:BlobStorage]
; Blob Storage Container name for ASA reference data
reference_data_container="referenceinput"
referenceDataContainer="referenceinput"
; Blob Storage Container name for Event Hub Checkpoints
eventhub_container="eventhub-checkpoints"
eventhubContainer="eventhub-checkpoints"
; Blob Storage Account Name
account_name=${PCS_ASA_DATA_AZUREBLOB_ACCOUNT}
storageAccountName=""
; Blob Storage Account Key
account_key=${PCS_ASA_DATA_AZUREBLOB_KEY}
storageAccountKey=""
; Blob Storage Endpoint Suffix
account_endpoint=${?PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX}
storageEndpointSuffix=""
; Following parameters create file path for device groups mapping
; in blob storage.
; File path will be:
; {YYYY-MM-DD}/{HH-mm}/{device_groups_file_name}
; For ASA file name must be in this format, see:
; https://docs.microsoft.com/en-us/azure/stream-analytics/stream-analytics-use-reference-data
reference_data_date_format="yyyy-MM-dd"
reference_data_time_format="HH-mm"
reference_data_device_groups_file_name="devicegroups.csv"
reference_data_rules_file_name="rules.json"
referenceDataDateFormat="yyyy-MM-dd"
referenceDataTimeFormat="HH-mm"
referenceDataDeviceGroupsFileName="devicegroups.csv"
referenceDataRulesFileName="rules.json"
[AsaManagerService:Logging]
; Application log levels: Debug, Info, Warn, Error
; Default: Warn
LogLevel = "${?PCS_LOG_LEVEL}"
logLevel = "${?PCS_LOG_LEVEL}"
; Whether to log the ProcessId, true by default
IncludeProcessId = true
includeProcessId = true
; How to format the datetime in the logs
; example: DateFormat = "yyyy-MM-dd HH:mm:ss.fff"
DateFormat = "yyyy-MM-dd HH:mm:ss.fff"
dateFormat = "yyyy-MM-dd HH:mm:ss.fff"
; Prefix to add to the items listed in BlackListSources and WhiteListSources
; example: BWListPrefix = "Microsoft.Azure.IoTSolutions.AsaManager."
BWListPrefix = "Microsoft.Azure.IoTSolutions.AsaManager."
bwListPrefix = "Microsoft.Azure.IoTSolutions.AsaManager."
; Comma separated list of classes and methods to ignore, i.e. discard logs from
; example: BlackListSources = "AsaConfigAgent.Program,HttpClient.*"
BlackListSources = ""
blackListSources = ""
; Comma separated list of classes and methods to include, i.e. discard everything else
; example: WhiteListSources = "HttpClient.*"
WhiteListSources = ""
whiteListSources = ""
; Whether to generate extra log files to diagnose the application. This is disk I/O intensive
; and most likely affects the overall performance. Enable this option only for development
; to get detailed information about the state of each actor and each device.
; Default: false
ExtraDiagnostics = false
extraDiagnostics = false
; Folder to store the extra diagnostics. Logging is disabled if the folder cannot
; be created or is not writable.
ExtraDiagnosticsPath = "/tmp/asa/"
extraDiagnosticsPath = "/tmp/asa/"
[AsaManagerService:ClientAuth]
; Current auth type, only "JWT" is currently supported.
auth_type="JWT"
authType="JWT"
; This can be changed to false, for example during development,
; to allow invalid/missing authorizations.
; Default: true
auth_required="${?PCS_AUTH_REQUIRED}"
authRequired=""
; Can be used when running services on multiple hostnames and/or ports
; e.g. "{ 'origins': ['*'], 'methods': ['*'], 'headers': ['*'] }" to allow everything.
; Comment it or leave it empty to disable CORS.
; Default: empty
cors_whitelist = "${?PCS_CORS_WHITELIST}"
corsWhitelist = ""
[AsaManagerService:ClientAuth:JWT]
; Trusted algorithms
; Default: RS256, RS384, RS512
allowed_algorithms="RS256"
allowedAlgorithms="RS256"
; Identifies the security token service (STS) that constructs and returns the token.
; In the tokens that Azure AD returns, the issuer is sts.windows.net. The GUID in
; the Issuer claim value is the tenant ID of the Azure AD directory. The tenant ID
@ -112,45 +112,47 @@ allowed_algorithms="RS256"
; When using Azure Active Directory, the format of the Issuer is:
; https://sts.windows.net/<tenant Id>/
; example: issuer="https://sts.windows.net/fa01ade2-2365-4dd1-a084-a6ef027090fc/"
issuer="${?PCS_AUTH_ISSUER}"
authIssuer=""
; Used to verify that tokens are issued to be given to this service
; Also referenced as "Application Id" and "Resource Id"
; example: audience="2814e709-6a0e-4861-9594-d3b6e2b81331"
audience="${?PCS_AUTH_AUDIENCE}"
aadTenantId=""
; When validating the token expiration, allows some clock skew
; Default: 2 minutes
clock_skew_seconds = 300
clockSkewSeconds = 300
[ExternalDependencies]
; The Device Telemetry service is used to retrieve the list
; of monitoring rules, which are used to generate ASA Jobs configuration
[DeviceTelemetryService]
; e.g. http://127.0.0.1:9004/v1/rules
webservice_url = ${PCS_TELEMETRY_WEBSERVICE_URL}
telemetryWebServiceUrl = ""
; timeout value in milliseconds
webservice_timeout_msecs = 10000
telemetryWebServiceTimeoutMsecs = 10000
; The Configuration service is used to retrieve the list
; of device groups, which are referenced in the monitoring rules
[PCSConfigurationService]
; e.g. http://127.0.0.1:9005/v1
webservice_url = ${PCS_CONFIG_WEBSERVICE_URL}
configWebServiceUrl =""
; timeout value in milliseconds
webservice_timeout_msecs = 10000
configWebServiceTimeoutMsecs = 10000
; The IoT Hub Manager service is used to run device queries,
; e.g. to retrieve the list of device IDs in a device group
[IoTHubManagerService]
; e.g. http://127.0.0.1:9002/v1
webservice_url = ${PCS_IOTHUBMANAGER_WEBSERVICE_URL}
iothubmanagerWebServiceUrl = ""
; timeout value in milliseconds
webservice_timeout_msecs = 10000
iothubmanagerTimeoutMsecs = 10000
; number of retries to attempt before failing
retry_count = 5
retryCount = 5
; initial interval to wait before retrying. Subsequent retries will
; increase interval by retry_increase_factor
initial_retry_interval_msecs = 750
retry_increase_factor = 2
initialRetryIntervalMsecs = 750
retryIncreaseFactor = 2
[KeyVault]
aadAppId = ${PCS_AAD_APPID}
aadAppSecret = ${PCS_AAD_APPSECRET}
name = ${PCS_KEYVAULT_NAME}
; For more information about ASP.NET logging see
; https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging

Просмотреть файл

@ -16,21 +16,9 @@ run_container() {
echo "Starting ASA manager ..."
docker run -it -p 9024:9024 \
-e PCS_TELEMETRY_WEBSERVICE_URL \
-e PCS_CONFIG_WEBSERVICE_URL \
-e PCS_IOTHUBMANAGER_WEBSERVICE_URL \
-e PCS_ASA_DATA_AZUREBLOB_ACCOUNT \
-e PCS_ASA_DATA_AZUREBLOB_KEY \
-e PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX \
-e PCS_EVENTHUB_CONNSTRING \
-e PCS_EVENTHUB_NAME \
-e PCS_AUTH_REQUIRED \
-e PCS_CORS_WHITELIST \
-e PCS_AUTH_ISSUER \
-e PCS_AUTH_AUDIENCE \
-e PCS_TWIN_READ_WRITE_ENABLED \
-e PCS_TELEMETRY_DOCUMENTDB_CONNSTRING \
-e PCS_TELEMETRY_STORAGE_TYPE \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
"$DOCKER_IMAGE:testing"
}

Просмотреть файл

@ -21,21 +21,9 @@ IF %ERRORLEVEL% NEQ 0 GOTO FAIL
:: Start the application
echo Starting ASA manager ...
docker run -it -p 9024:9024 ^
-e PCS_TELEMETRY_WEBSERVICE_URL ^
-e PCS_CONFIG_WEBSERVICE_URL ^
-e PCS_IOTHUBMANAGER_WEBSERVICE_URL ^
-e PCS_ASA_DATA_AZUREBLOB_ACCOUNT ^
-e PCS_ASA_DATA_AZUREBLOB_KEY ^
-e PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX ^
-e PCS_EVENTHUB_CONNSTRING ^
-e PCS_EVENTHUB_NAME ^
-e PCS_AUTH_REQUIRED ^
-e PCS_CORS_WHITELIST ^
-e PCS_AUTH_ISSUER ^
-e PCS_AUTH_AUDIENCE ^
-e PCS_TWIN_READ_WRITE_ENABLED ^
-e PCS_TELEMETRY_DOCUMENTDB_CONNSTRING ^
-e PCS_TELEMETRY_STORAGE_TYPE ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
%DOCKER_IMAGE%:testing
:: - - - - - - - - - - - - - -

Просмотреть файл

@ -1,64 +1,17 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Before checking all the env vars, detect whether secrets, usually encrypted, are available or not.
# Secrets are not available when building a pull request, so the script will not check for those.
detect_secrets() {
SECRETS_AVAILABLE="true"
if [[ "$TRAVIS_PULL_REQUEST" != "" && "$TRAVIS_PULL_REQUEST" != "false" ]]; then
SECRETS_AVAILABLE="false"
echo "Warning: secrets and encrypted variables are not available when testing pull requests."
fi
}
detect_secrets
if [[ -z "PCS_TELEMETRY_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_TELEMETRY_WEBSERVICE_URL environment variable is not defined."
if [[ -z "$PCS_KEYVAULT_NAME" ]]; then
echo "Error: the PCS_KEYVAULT_NAME environment variable is not defined."
exit 1
fi
if [[ -z "PCS_CONFIG_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_CONFIG_WEBSERVICE_URL environment variable is not defined."
if [[ -z "$PCS_AAD_APPID" ]]; then
echo "Error: the PCS_AAD_APPID environment variable is not defined."
exit 1
fi
if [[ -z "PCS_IOTHUBMANAGER_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_IOTHUBMANAGER_WEBSERVICE_URL environment variable is not defined."
exit 1
fi
if [[ -z "PCS_ASA_DATA_AZUREBLOB_ACCOUNT" ]]; then
echo "Error: the PCS_ASA_DATA_AZUREBLOB_ACCOUNT environment variable is not defined."
exit 1
fi
if [[ -z "PCS_ASA_DATA_AZUREBLOB_KEY" && "$SECRETS_AVAILABLE" = "true" ]]; then
echo "Error: the PCS_ASA_DATA_AZUREBLOB_KEY environment variable is not defined."
exit 1
fi
if [[ -z "PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX" ]]; then
echo "Error: the PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX environment variable is not defined."
exit 1
fi
if [[ -z "PCS_EVENTHUB_CONNSTRING" && "$SECRETS_AVAILABLE" = "true" ]]; then
echo "Error: the PCS_EVENTHUB_CONNSTRING environment variable is not defined."
exit 1
fi
if [[ -z "PCS_TELEMETRY_DOCUMENTDB_CONNSTRING" && "$SECRETS_AVAILABLE" = "true" ]]; then
echo "Error: the PCS_TELEMETRY_DOCUMENTDB_CONNSTRING environment variable is not defined."
exit 1
fi
if [[ -z "PCS_EVENTHUB_NAME" ]]; then
echo "Error: the PCS_EVENTHUB_NAME environment variable is not defined."
exit 1
fi
if [[ -z "PCS_TELEMETRY_STORAGE_TYPE" ]]; then
echo "Error: the PCS_TELEMETRY_STORAGE_TYPE environment variable is not defined."
if [[ -z "$PCS_AAD_APPSECRET" ]]; then
echo "Error: the PCS_AAD_APPSECRET environment variable is not defined."
exit 1
fi

Просмотреть файл

@ -2,53 +2,18 @@
@ECHO off & setlocal enableextensions enabledelayedexpansion
IF "%PCS_TELEMETRY_WEBSERVICE_URL%" == "" (
echo Error: the PCS_TELEMETRY_WEBSERVICE_URL environment variable is not defined.
IF "%PCS_KEYVAULT_NAME%" == "" (
echo Error: the PCS_KEYVAULT_NAME environment variable is not defined.
exit /B 1
)
IF "%PCS_CONFIG_WEBSERVICE_URL%" == "" (
echo Error: the PCS_CONFIG_WEBSERVICE_URL environment variable is not defined.
IF "%PCS_AAD_APPID%" == "" (
echo Error: the PCS_AAD_APPID environment variable is not defined.
exit /B 1
)
IF "%PCS_IOTHUBMANAGER_WEBSERVICE_URL%" == "" (
echo Error: the PCS_IOTHUBMANAGER_WEBSERVICE_URL environment variable is not defined.
exit /B 1
)
IF "%PCS_ASA_DATA_AZUREBLOB_ACCOUNT%" == "" (
echo Error: the PCS_ASA_DATA_AZUREBLOB_ACCOUNT environment variable is not defined.
exit /B 1
)
IF "%PCS_ASA_DATA_AZUREBLOB_KEY%" == "" (
echo Error: the PCS_ASA_DATA_AZUREBLOB_KEY environment variable is not defined.
exit /B 1
)
IF "%PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX%" == "" (
echo Error: the PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX environment variable is not defined.
exit /B 1
)
IF "%PCS_EVENTHUB_CONNSTRING%" == "" (
echo Error: the PCS_EVENTHUB_CONNSTRING environment variable is not defined.
exit /B 1
)
IF "%PCS_TELEMETRY_DOCUMENTDB_CONNSTRING%" == "" (
echo Error: the PCS_TELEMETRY_DOCUMENTDB_CONNSTRING environment variable is not defined.
exit /B 1
)
IF "%PCS_EVENTHUB_NAME%" == "" (
echo Error: the PCS_EVENTHUB_NAME environment variable is not defined.
exit /B 1
)
IF "%PCS_TELEMETRY_STORAGE_TYPE%" == "" (
echo Error: the PCS_TELEMETRY_STORAGE_TYPE environment variable is not defined.
IF "%PCS_AAD_APPSECRET%" == "" (
echo Error: the PCS_AAD_APPSECRET environment variable is not defined.
exit /B 1
)

Просмотреть файл

@ -1,33 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Prepare the environment variables used by the application.
#
# Endpoint used to retrieve the list of monitoring rules
export PCS_TELEMETRY_WEBSERVICE_URL="http://127.0.0.1:9004/v1"
# Endpoint used to retrieve the list of device groups
export PCS_CONFIG_WEBSERVICE_URL="http://127.0.0.1:9005/v1"
# Endpoint used to retrieve the list of devices in each group
export PCS_IOTHUBMANAGER_WEBSERVICE_URL="http://127.0.0.1:9002/v1"
# Connection details of the Azure Blob where event hub checkpoints and reference data are stored
export PCS_ASA_DATA_AZUREBLOB_ACCOUNT="..."
export PCS_ASA_DATA_AZUREBLOB_KEY="..."
export PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX="..."
# Event Hub where device notifications are stored
# IotHub needs to be set up to send device twin and lifecycle messages to this event hub, see below links
# https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-device-twins
# https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-identity-registry
export PCS_EVENTHUB_CONNSTRING="Endpoint=sb://....servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=..."
# Name of event hub where device notifications are stored
export PCS_EVENTHUB_NAME="..."
# Azure CosmosDb SQL connection string, storage used for telemetry and alarms
export PCS_TELEMETRY_DOCUMENTDB_CONNSTRING="AccountEndpoint=https://....documents.azure.com:443/;AccountKey=...;"
# The storage type for telemetry messages. Default is "tsi". Allowed values: ["cosmosdb", "tsi"]
export PCS_TELEMETRY_STORAGE_TYPE="tsi"

Просмотреть файл

@ -1,32 +0,0 @@
:: Copyright (c) Microsoft. All rights reserved.
:: Prepare the environment variables used by the application.
::
:: Endpoint used to retrieve the list of monitoring rules
SETX PCS_TELEMETRY_WEBSERVICE_URL "http://127.0.0.1:9004/v1"
:: Endpoint used to retrieve the list of device groups
SETX PCS_CONFIG_WEBSERVICE_URL "http://127.0.0.1:9005/v1"
:: Endpoint used to retrieve the list of devices in each group
SETX PCS_IOTHUBMANAGER_WEBSERVICE_URL "http://127.0.0.1:9002/v1"
:: Connection details of the Azure Blob where event hub checkpoints and reference data are stored
SETX PCS_ASA_DATA_AZUREBLOB_ACCOUNT "..."
SETX PCS_ASA_DATA_AZUREBLOB_KEY "..."
SETX PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX "..."
:: Event Hub connections string for where device notifications are stored
:: IotHub needs to be set up to send device twin and lifecycle messages to this event hub, see below links
:: https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-device-twins
:: https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-identity-registry
SETX PCS_EVENTHUB_CONNSTRING "Endpoint=sb://....servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=..."
:: Name of event hub where device notifications are stored
SETX PCS_EVENTHUB_NAME "..."
:: Azure CosmosDb SQL connection string, storage used for telemetry and alarms
SETX PCS_TELEMETRY_DOCUMENTDB_CONNSTRING "AccountEndpoint=https://....documents.azure.com:443/;AccountKey=...;"
:: The storage type for telemetry messages. Default is "tsi". Allowed values: ["cosmosdb", "tsi"]
SETX PCS_TELEMETRY_STORAGE_TYPE="tsi"

Просмотреть файл

@ -54,21 +54,9 @@ run_in_sandbox() {
docker run -it \
-p 9024:9024 \
-e PCS_TELEMETRY_WEBSERVICE_URL \
-e PCS_CONFIG_WEBSERVICE_URL \
-e PCS_IOTHUBMANAGER_WEBSERVICE_URL \
-e PCS_ASA_DATA_AZUREBLOB_ACCOUNT \
-e PCS_ASA_DATA_AZUREBLOB_KEY \
-e PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX \
-e PCS_EVENTHUB_CONNSTRING \
-e PCS_EVENTHUB_NAME \
-e PCS_AUTH_REQUIRED \
-e PCS_CORS_WHITELIST \
-e PCS_AUTH_ISSUER \
-e PCS_AUTH_AUDIENCE \
-e PCS_TWIN_READ_WRITE_ENABLED \
-e PCS_TELEMETRY_DOCUMENTDB_CONNSTRING \
-e PCS_TELEMETRY_STORAGE_TYPE \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
-v "$PCS_CACHE/sandbox/.config:/root/.config" \
-v "$PCS_CACHE/sandbox/.dotnet:/root/.dotnet" \
-v "$PCS_CACHE/sandbox/.nuget:/root/.nuget" \

Просмотреть файл

@ -81,21 +81,9 @@ GOTO :Run
:: Start the sandbox and run the application
docker run -it ^
-p 9024:9024 ^
-e PCS_TELEMETRY_WEBSERVICE_URL ^
-e PCS_CONFIG_WEBSERVICE_URL ^
-e PCS_IOTHUBMANAGER_WEBSERVICE_URL ^
-e PCS_ASA_DATA_AZUREBLOB_ACCOUNT ^
-e PCS_ASA_DATA_AZUREBLOB_KEY ^
-e PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX ^
-e PCS_EVENTHUB_CONNSTRING ^
-e PCS_EVENTHUB_NAME ^
-e PCS_AUTH_REQUIRED ^
-e PCS_CORS_WHITELIST ^
-e PCS_AUTH_ISSUER ^
-e PCS_AUTH_AUDIENCE ^
-e PCS_TWIN_READ_WRITE_ENABLED ^
-e PCS_TELEMETRY_DOCUMENTDB_CONNSTRING ^
-e PCS_TELEMETRY_STORAGE_TYPE ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
-v %PCS_CACHE%\sandbox\.config:/root/.config ^
-v %PCS_CACHE%\sandbox\.dotnet:/root/.dotnet ^
-v %PCS_CACHE%\sandbox\.nuget:/root/.nuget ^

Просмотреть файл

@ -1,29 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Note: Windows Bash doesn't support shebang extra params
set -e
# Example usage (see "travis help" for more information):
# travis help
# travis login --pro
# travis whoami --pro
# travis accounts --pro
# travis history
# travis monitor --pro
# travis settings
# travis show
# travis status
# travis token --pro
# travis whatsup --pro
APP_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )/"
cd $APP_HOME
mkdir -p .travis
docker run -it \
-v $APP_HOME/.travis:/root/.travis \
-v $APP_HOME:/opt/code \
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh $*
set +e

Просмотреть файл

@ -1,30 +0,0 @@
:: Copyright (c) Microsoft. All rights reserved.
@ECHO off & setlocal enableextensions enabledelayedexpansion
:: Example usage (see "travis help" for more information:
:: travis help
:: travis login --pro
:: travis whoami --pro
:: travis accounts --pro
:: travis history
:: travis monitor --pro
:: travis settings
:: travis show
:: travis status
:: travis token --pro
:: travis whatsup --pro
:: strlen("\scripts\") => 9
SET APP_HOME=%~dp0
SET APP_HOME=%APP_HOME:~0,-9%
cd %APP_HOME%
mkdir .travis 2>NUL
docker run -it ^
-v %APP_HOME%\.travis:/root/.travis ^
-v %APP_HOME%:/opt/code ^
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh %*
endlocal

Просмотреть файл

@ -23,28 +23,38 @@ namespace Microsoft.Azure.IoTSolutions.Auth.Services.Runtime
private readonly IConfigurationRoot configuration;
private readonly ILogger log;
// Key Vault
private KeyVault keyVault;
// Constants
private const string CLIENT_ID = "KeyVault:aadAppId";
private const string CLIENT_SECRET = "KeyVault:aadAppSecret";
private const string KEY_VAULT_NAME = "KeyVault:name";
public ConfigData(ILogger logger)
{
this.log = logger;
// More info about configuration at
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddIniFile("appsettings.ini", optional: true, reloadOnChange: true);
this.configuration = configurationBuilder.Build();
// Set up Key Vault
this.SetUpKeyVault();
}
public string GetString(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
var value = this.GetSecrets(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
public bool GetBool(string key, bool defaultValue = false)
{
var value = this.GetString(key, defaultValue.ToString()).ToLowerInvariant();
var value = this.GetSecrets(key, defaultValue.ToString()).ToLowerInvariant();
var knownTrue = new HashSet<string> { "true", "t", "yes", "y", "1", "-1" };
var knownFalse = new HashSet<string> { "false", "f", "no", "n", "0" };
@ -59,7 +69,7 @@ namespace Microsoft.Azure.IoTSolutions.Auth.Services.Runtime
{
try
{
return Convert.ToInt32(this.GetString(key, defaultValue.ToString()));
return Convert.ToInt32(this.GetSecrets(key, defaultValue.ToString()));
}
catch (Exception e)
{
@ -67,6 +77,45 @@ namespace Microsoft.Azure.IoTSolutions.Auth.Services.Runtime
}
}
private void SetUpKeyVault()
{
var clientId = this.GetEnvironmentVariable(CLIENT_ID, string.Empty);
var clientSecret = this.GetEnvironmentVariable(CLIENT_SECRET, string.Empty);
var keyVaultName = this.GetEnvironmentVariable(KEY_VAULT_NAME, string.Empty);
// Initailize key vault
this.keyVault = new KeyVault(keyVaultName, clientId, clientSecret, this.log);
}
private string GetSecrets(string key, string defaultValue = "")
{
string value = string.Empty;
value = this.GetLocalVariables(key, defaultValue);
// If secrets are not found locally, search in Key-Vault
if (string.IsNullOrEmpty(value))
{
log.Warn($"Value for secret {key} not found in local env. " +
$" Trying to get the secret from KeyVault.", () => { });
value = this.keyVault.GetSecret(key);
}
return !string.IsNullOrEmpty(value) ? value : defaultValue;
}
private string GetLocalVariables(string key, string defaultValue = "")
{
return this.configuration.GetValue(key, defaultValue);
}
public string GetEnvironmentVariable(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
private void ReplaceEnvironmentVariables(ref string value, string defaultValue = "")
{
if (string.IsNullOrEmpty(value)) return;

Просмотреть файл

@ -0,0 +1,71 @@
using Microsoft.Azure.IoTSolutions.Auth.Services.Diagnostics;
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.Azure.IoTSolutions.Auth.Services.Runtime
{
public class KeyVault
{
// Key Vault details and access
private readonly string name;
private readonly string clientId;
private readonly string clientSecret;
private ILogger log;
// Key Vault Client
private readonly KeyVaultClient keyVaultClient;
// Constants
private const string KEY_VAULT_URI = "https://{0}.vault.azure.net/secrets/{1}";
public KeyVault(
string name,
string clientId,
string clientSecret,
ILogger logger)
{
this.name = name;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.log = logger;
this.keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(this.GetToken));
}
public string GetSecret(string secretKey)
{
secretKey = secretKey.Split(':').Last();
var uri = string.Format(KEY_VAULT_URI, this.name, secretKey);
try
{
return this.keyVaultClient.GetSecretAsync(uri).Result.Value;
}
catch (Exception e)
{
this.log.Error($"Secret {secretKey} not found in Key Vault.", () => { });
return null;
}
}
//the method that will be provided to the KeyVaultClient
private async Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
ClientCredential clientCred = new ClientCredential(this.clientId, this.clientSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
{
this.log.Debug($"Failed to obtain authentication token from key vault.", () => { });
throw new System.InvalidOperationException("Failed to obtain the JWT token");
}
return result.AccessToken;
}
}
}

Просмотреть файл

@ -12,6 +12,7 @@
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="2.1.4" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.1.4" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="2.0.6" />
</ItemGroup>
<ItemGroup>
<None Update="data\policies\roles.json">

Просмотреть файл

@ -5,9 +5,9 @@
"launchBrowser": true,
"launchUrl": "http://localhost:9001/v1/status",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"PCS_AUTH_AUDIENCE": "${PCS_AUTH_AUDIENCE}",
"PCS_AUTH_ISSUER": "${PCS_AUTH_ISSUER}"
"PCS_KEYVAULT_NAME": "$(PCS_KEYVAULT_NAME)",
"PCS_AAD_APPID": "$(PCS_AAD_APPID)",
"PCS_AAD_APPSECRET": "$(PCS_AAD_APPSECRET)"
},
"applicationUrl": "http://localhost:9001/v1/status"
}

Просмотреть файл

@ -23,29 +23,29 @@ namespace Microsoft.Azure.IoTSolutions.Auth.WebService.Runtime
public class Config : IConfig
{
private const string APPLICATION_KEY = "AuthService:";
private const string PORT_KEY = APPLICATION_KEY + "webservice_port";
private const string JWT_USER_ID_FROM_KEY = APPLICATION_KEY + "extract_userid_from";
private const string JWT_NAME_FROM_KEY = APPLICATION_KEY + "extract_name_from";
private const string JWT_EMAIL_FROM_KEY = APPLICATION_KEY + "extract_email_from";
private const string JWT_ROLES_FROM_KEY = APPLICATION_KEY + "extract_roles_from";
private const string POLICIES_FOLDER_KEY = APPLICATION_KEY + "policies_folder";
private const string AAD_ENDPOINT_URL = APPLICATION_KEY + "aad_endpoint_url";
private const string AAD_TENANT_ID = APPLICATION_KEY + "aad_tenant_id";
private const string AAD_APPLICATION_ID = APPLICATION_KEY + "aad_application_id";
private const string AAD_APPLICATION_SECRET = APPLICATION_KEY + "aad_application_secret";
private const string ARM_ENDPOINT_URL = APPLICATION_KEY + "arm_endpoint_url";
private const string PORT_KEY = APPLICATION_KEY + "webservicePort";
private const string JWT_USER_ID_FROM_KEY = APPLICATION_KEY + "extractUserIdFrom";
private const string JWT_NAME_FROM_KEY = APPLICATION_KEY + "extractNameFrom";
private const string JWT_EMAIL_FROM_KEY = APPLICATION_KEY + "extractEmailFrom";
private const string JWT_ROLES_FROM_KEY = APPLICATION_KEY + "extractRolesFrom";
private const string POLICIES_FOLDER_KEY = APPLICATION_KEY + "policiesFolder";
private const string AAD_ENDPOINT_URL = APPLICATION_KEY + "aadEndpointUrl";
private const string AAD_TENANT_ID = APPLICATION_KEY + "aadTenantId";
private const string AAD_APPLICATION_ID = APPLICATION_KEY + "aadAppId";
private const string AAD_APPLICATION_SECRET = APPLICATION_KEY + "aadAppSecret";
private const string ARM_ENDPOINT_URL = APPLICATION_KEY + "armEndpointUrl";
private const string CLIENT_AUTH_KEY = APPLICATION_KEY + "ClientAuth:";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "cors_whitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "auth_type";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "auth_required";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "corsWhitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "authType";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "authRequired";
private const string JWT_KEY = APPLICATION_KEY + "ClientAuth:JWT:";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowed_algorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "issuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "audience";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowedAlgorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "authIssuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "aadAppId";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clock_skew_seconds";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clockSkewSeconds";
public const string DEFAULT_ARM_ENDPOINT_URL = "https://management.azure.com/";
public const string DEFAULT_AAD_ENDPOINT_URL = "https://login.microsoftonline.com/";

Просмотреть файл

@ -1,44 +1,44 @@
[AuthService]
webservice_port = 9001
webservicePort = 9001
; The claims to use to get the current user information
extract_userid_from="oid"
extract_name_from="given_name,family_name"
extract_email_from="email"
extract_roles_from="roles"
extractUserIdFrom="oid"
extractNameFrom="given_name,family_name"
extractEmailFrom="email"
extractRolesFrom="roles"
# Note: when running the service with Docker, the content of the `data`
# folder can be overridden, e.g. to inject custom policies.
policies_folder = ./data/policies/
policiesFolder = ./data/policies/
; The AAD endpoint url to acquire ARM token for AAD application
aad_endpoint_url="${?PCS_AAD_ENDPOINT_URL}"
aadEndpointUrl=""
; The AAD Tenant Id
aad_tenant_id="${?PCS_AAD_TENANT}"
aadTenantId=""
; The unique Id of AAD application that has already been authorized
; to access ARM resources
aad_application_id="${?PCS_AUTH_AUDIENCE}"
aadAppId=""
; The secret of AAD application
aad_application_secret="${?PCS_AAD_APPSECRET}"
aadAppSecret=""
;; Azure Resource Manager endpoint url to get token
arm_endpoint_url="${?PCS_ARM_ENDPOINT_URL}"
armEndpointUrl=""
[AuthService:ClientAuth]
;; Current auth type, only "JWT" is currently supported.
auth_type="JWT"
authType="JWT"
;; This can be changed to false, for example during development,
;; to allow invalid/missing authorizations.
;; Default: true
auth_required="${?PCS_AUTH_REQUIRED}"
authRequired=""
;; Can be used when running services on multiple hostnames and/or ports
;; e.g. "{ 'origins': ['*'], 'methods': ['*'], 'headers': ['*'] }" to allow everything.
;; Comment it or leave it empty to disable CORS.
;; Default: empty
cors_whitelist = "${?PCS_CORS_WHITELIST}"
corsWhitelist = ""
[AuthService:ClientAuth:JWT]
; Trusted algorithms
; Default: RS256, RS384, RS512
allowed_algorithms="RS256"
allowedAlgorithms="RS256"
; Identifies the security token service (STS) that constructs and returns the token.
; In the tokens that Azure AD returns, the issuer is sts.windows.net. The GUID in
; the Issuer claim value is the tenant ID of the Azure AD directory. The tenant ID
@ -47,16 +47,20 @@ allowed_algorithms="RS256"
; When using Azure Active Directory, the format of the Issuer is:
; https://sts.windows.net/<tenant Id>/
; example: issuer="https://sts.windows.net/fa01ade2-2365-4dd1-a084-a6ef027090fc/"
issuer="${?PCS_AUTH_ISSUER}"
authIssuer=""
; Used to verify that tokens are issued to be given to this service
; Also referenced as "Application Id" and "Resource Id"
; example: audience="2814e709-6a0e-4861-9594-d3b6e2b81331"
audience="${?PCS_AUTH_AUDIENCE}"
aadAppId=""
;; secret of the application audience
; When validating the token expiration, allows some clock skew
; Default: 2 minutes
clock_skew_seconds = 300
clockSkewSeconds = 300
[KeyVault]
aadAppId = ${PCS_AAD_APPID}
aadAppSecret = ${PCS_AAD_APPSECRET}
name = ${PCS_KEYVAULT_NAME}
; For more information about ASP.NET logging see
; https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging
@ -64,7 +68,7 @@ clock_skew_seconds = 300
; internal logs generated by ASP.NET
; ASP.NET log levels: Trace, Debug, Information, Warning, Error, Critical
[Logging]
IncludeScopes = true
includeScopes = true
LogLevel:Default = "Warning"
LogLevel:System = "Warning"
LogLevel:Microsoft = "Warning"

Просмотреть файл

@ -0,0 +1,100 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
AUTH_SERVER_URL=""
RESOURCE_TYPE=""
AUTH_TOKEN=""
# Acquires auth token for authroizating against key vault.
_acquire_token() {
__set_keyvault_auth_server
local _value=$(curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "client_id=$PCS_AAD_APPID&resource=https%3A%2F%2Fvault.azure.net&client_secret=$PCS_AAD_APPSECRET&grant_type=client_credentials" $AUTH_SERVER_URL/oauth2/token)
AUTH_TOKEN=$(__parse_json $_value "access_token")
}
# Fetch key vault secret.
_get_keyvault_secret() {
# Get a new token each time you access key vault.
_acquire_token
_keyvault_secret_bundle=$(curl -H "Authorization: Bearer $AUTH_TOKEN" -L https://$PCS_KEYVAULT_NAME.vault.azure.net/secrets/$1/?api-version=7.0)
_keyvault_secret_bundle="'$_keyvault_secret_bundle'"
# return the secret value.
echo $(__parse_json $_keyvault_secret_bundle "value")
}
# Gets keyvault auth server by examining response headers of unauthenticated request to key vault.
# The 401 redirect contains WWW-Authenticate header which has KV auth server and resource type.
__set_keyvault_auth_server() {
# Bare (unauthenticated) request to get secret.
key_vault_wo_auth_call=$(curl -i https://$PCS_KEYVAULT_NAME.vault.azure.net/secrets/authEnabled/?api-version=7.0 | grep 'www.*')
wo_auth_call_resp_header=${key_vault_wo_auth_call#*:}
# Extract auth server (url) & resource from WWW-Authenticate header.
IFS=',' read -ra PARAMS <<< "$wo_auth_call_resp_header"
for (( i = 0; i < 2; ++i )); do
if [ $i == 0 ]; then
__extract_auth_server ${PARAMS[0]}
else
__extract_resource_type ${PARAMS[1]}
fi
done
}
############# Helper functions #############
#Removes Bearer authorization prefix to extract auth server url from 401 redirect of keyvault.
__extract_auth_server() {
AUTH_SERVER_URL=$(__remove_double_quotes $2)
}
#Removes "resource" prefix to extract resource type from 401 redirect of keyvault.
__extract_resource_type() {
RESOURCE_TYPE=$(__remove_double_quotes $1)
}
__remove_double_quotes() {
local input=$1
# Remove trailing and prefixed double quotes.
local _value=${input#*'"'}
_value=${_value%'"'}
#return the value
echo $_value
}
__parse_json() {
_value=`echo $1 | sed 's/\\\\\//\//g' | sed 's/[{}]//g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | sed 's/\"\:\"/\|/g' | sed 's/[\,]/ /g' | sed 's/\"//g' | grep -w $2`;
echo ${_value##*|};
}
############# Main function #############
set_env_vars() {
# parse through all variables (Every odd variable is env var name & even variables are secret key names in Key vault).
while test ${#} -gt 0
do
_key=$1
_value=$(_get_keyvault_secret $2)
# export in current shell
export $_key=$_value
shift
shift
done
}
main() {
if [[ "$PCS_KEYVAULT_NAME" != "" ]] && [[ "$PCS_AAD_APPID" != "" ]] && [[ "$PCS_AAD_APPSECRET" != "" ]]; then
set_env_vars $@
fi
}
main $@

Просмотреть файл

@ -15,12 +15,9 @@ run_container() {
# Depending on which settings and which dependencies are needed, edit the list of variables
echo "Starting Auth ..."
docker run -it -p 9001:9001 \
-e PCS_AUTH_ISSUER \
-e PCS_AUTH_AUDIENCE \
-e PCS_AAD_ENDPOINT_URL \
-e PCS_AAD_TENANT \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
-e PCS_ARM_ENDPOINT_URL \
"$DOCKER_IMAGE:testing"
}

Просмотреть файл

@ -19,12 +19,9 @@ IF %ERRORLEVEL% NEQ 0 GOTO FAIL
:: Start the application
echo Starting Auth ...
docker run -it -p 9001:9001 ^
-e PCS_AUTH_ISSUER ^
-e PCS_AUTH_AUDIENCE ^
-e PCS_AAD_ENDPOINT_URL ^
-e PCS_AAD_TENANT ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
-e PCS_ARM_ENDPOINT_URL ^
%DOCKER_IMAGE%:testing
:: - - - - - - - - - - - - - -

Просмотреть файл

@ -1,54 +1,17 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Before checking all the env vars, detect whether secrets, usually encrypted, are available or not.
# Secrets are not available when building a pull request, so the script will not check for those.
detect_secrets() {
SECRETS_AVAILABLE="true"
if [[ "$TRAVIS_PULL_REQUEST" != "" && "$TRAVIS_PULL_REQUEST" != "false" ]]; then
SECRETS_AVAILABLE="false"
echo "Warning: secrets and encrypted variables are not available when testing pull requests."
fi
}
detect_secrets
# if [[ -z "$SOMETHING_SECRET" && "$SECRETS_AVAILABLE" = "true" ]]; then
# echo "Error: the SOMETHING_SECRET environment variable is not defined."
# exit -1
# fi
# if [[ -z "$SOMETHING_NOT_SECRET" ]]; then
# echo "Error: the SOMETHING_NOT_SECRET environment variable is not defined."
# exit -1
# fi
if [[ -z "$PCS_AUTH_ISSUER" ]]; then
echo "Error: the PCS_AUTH_ISSUER environment variable is not defined."
exit -1
if [[ -z "$PCS_KEYVAULT_NAME" ]]; then
echo "Error: the PCS_KEYVAULT_NAME environment variable is not defined."
exit 1
fi
if [[ -z "$PCS_AUTH_AUDIENCE" ]]; then
echo "Error: the PCS_AUTH_AUDIENCE environment variable is not defined."
exit -1
if [[ -z "$PCS_AAD_APPID" ]]; then
echo "Error: the PCS_AAD_APPID environment variable is not defined."
exit 1
fi
if [[ -z "PCS_AAD_ENDPOINT_URL" ]]; then
echo "Error: the PCS_AAD_ENDPOINT_URL environment variable is not defined."
exit -1
fi
if [[ -z "PCS_AAD_TENANT" ]]; then
echo "Error: the PCS_AAD_TENANT environment variable is not defined."
exit -1
fi
if [[ -z "PCS_AAD_APPSECRET" ]]; then
if [[ -z "$PCS_AAD_APPSECRET" ]]; then
echo "Error: the PCS_AAD_APPSECRET environment variable is not defined."
exit -1
exit 1
fi
if [[ -z "PCS_ARM_ENDPOINT_URL" ]]; then
echo "Error: the PCS_ARM_ENDPOINT_URL environment variable is not defined."
exit -1
fi

Просмотреть файл

@ -1,22 +1,14 @@
:: Copyright (c) Microsoft. All rights reserved.
@ECHO off & setlocal enableextensions enabledelayedexpansion
IF "%PCS_AUTH_ISSUER%" == "" (
echo Error: the PCS_AUTH_ISSUER environment variable is not defined.
IF "%PCS_KEYVAULT_NAME%" == "" (
echo Error: the PCS_KEYVAULT_NAME environment variable is not defined.
exit /B 1
)
IF "%PCS_AUTH_AUDIENCE%" == "" (
echo Error: the PCS_AUTH_AUDIENCE environment variable is not defined.
exit /B 1
)
IF "%PCS_AAD_ENDPOINT_URL%" == "" (
echo Error: the PCS_AAD_ENDPOINT_URL environment variable is not defined.
exit /B 1
)
IF "%PCS_AAD_TENANT%" == "" (
echo Error: the PCS_AAD_TENANT environment variable is not defined.
IF "%PCS_AAD_APPID%" == "" (
echo Error: the PCS_AAD_APPID environment variable is not defined.
exit /B 1
)
@ -25,9 +17,4 @@ IF "%PCS_AAD_APPSECRET%" == "" (
exit /B 1
)
IF "%PCS_ARM_ENDPOINT_URL%" == "" (
echo Error: the PCS_ARM_ENDPOINT_URL environment variable is not defined.
exit /B 1
)
endlocal

Просмотреть файл

@ -1,28 +0,0 @@
#!/usr/bin/env bash
# Usage: source ./scripts/env-vars-setup
#
# IMPORTANT NOTES:
# * use "source" in front of the script path, so that variables are exported in your shell
# * the variables are set only in the current shell, run this script every time, or automate
# the setup using your `~/.bash_profile`.
# Prepare the environment variables used by the application.
# The OpenId tokens issuer URL, e.g. https://sts.windows.net/12000000-3400-5600-0000-780000000000/
export PCS_AUTH_ISSUER="{enter the token issuer URL here}"
# The intended audience of the tokens, e.g. your Client Id
export PCS_AUTH_AUDIENCE="{enter the tokens audience here}"
# Azure Active Directory endpoint url, e.g. https://login.microsoftonline.com/
export PCS_AAD_ENDPOINT_URL="{enter the AAD endpoint URL here}"
# The tenant id of Azure Active Directory
export PCS_AAD_TENANT="{enter the tenant id of AAD here}"
# The secret of intended application audience
export PCS_AAD_APPSECRET="{enter the secret of AAD application here}"
# Azure Resource Manager endpoint url, e.g. https://management.azure.com/
export PCS_ARM_ENDPOINT_URL="{enter the endpoint URL of Azure Resource Manager here}"

Просмотреть файл

@ -1,19 +0,0 @@
:: Prepare the environment variables used by the application.
:: The OpenId tokens issuer URL, e.g. https://sts.windows.net/12000000-3400-5600-0000-780000000000/
SETX PCS_AUTH_ISSUER "{enter the token issuer URL here}"
:: The intended audience of the tokens, e.g. your Client Id
SETX PCS_AUTH_AUDIENCE "{enter the tokens audience here}"
# Azure Active Directory endpoint url, e.g. https://login.microsoftonline.com/
SETX PCS_AAD_ENDPOINT_URL "{enter the AAD endpoint URL here}"
# The tenant id of Azure Active Directory
SETX PCS_AAD_TENANT "{enter the tenant id of AAD here}"
# The secret of intended application audience
SETX PCS_AAD_APPSECRET "{enter the secret of AAD application here}"
# Azure Resource Manager endpoint url, e.g. https://management.azure.com/
SETX PCS_ARM_ENDPOINT_URL "{enter the endpoint URL of Azure Resource Manager here}"

Просмотреть файл

@ -58,12 +58,9 @@ run_in_sandbox() {
# edit the list of variables.
docker run -it \
-p 9001:9001 \
-e PCS_AUTH_ISSUER \
-e PCS_AUTH_AUDIENCE \
-e PCS_AAD_ENDPOINT_URL \
-e PCS_AAD_TENANT \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
-e PCS_ARM_ENDPOINT_URL \
-v "$PCS_CACHE/sandbox/.config:/root/.config" \
-v "$PCS_CACHE/sandbox/.dotnet:/root/.dotnet" \
-v "$PCS_CACHE/sandbox/.nuget:/root/.nuget" \

Просмотреть файл

@ -61,12 +61,9 @@ IF "%1"=="--in-sandbox" GOTO :RunInSandbox
:: Start the sandbox and run the service
docker run -it ^
-p 9001:9001 ^
-e PCS_AUTH_ISSUER ^
-e PCS_AUTH_AUDIENCE ^
-e PCS_AAD_ENDPOINT_URL ^
-e PCS_AAD_TENANT ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
-e PCS_ARM_ENDPOINT_URL ^
-v %PCS_CACHE%\sandbox\.config:/root/.config ^
-v %PCS_CACHE%\sandbox\.dotnet:/root/.dotnet ^
-v %PCS_CACHE%\sandbox\.nuget:/root/.nuget ^

Просмотреть файл

@ -1,27 +0,0 @@
#!/usr/bin/env bash
# Example usage (see "travis help" for more information):
# travis help
# travis login --pro
# travis whoami --pro
# travis accounts --pro
# travis history
# travis monitor --pro
# travis settings
# travis show
# travis status
# travis token --pro
# travis whatsup --pro
set -e
APP_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )/"
cd $APP_HOME
mkdir -p .travis
docker run -it \
-v $APP_HOME/.travis:/root/.travis \
-v $APP_HOME:/opt/code \
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh $*
set +e

Просмотреть файл

@ -1,28 +0,0 @@
@ECHO off & setlocal enableextensions enabledelayedexpansion
:: Example usage (see "travis help" for more information:
:: travis help
:: travis login --pro
:: travis whoami --pro
:: travis accounts --pro
:: travis history
:: travis monitor --pro
:: travis settings
:: travis show
:: travis status
:: travis token --pro
:: travis whatsup --pro
:: strlen("\scripts\") => 9
SET APP_HOME=%~dp0
SET APP_HOME=%APP_HOME:~0,-9%
cd %APP_HOME%
mkdir .travis 2>NUL
docker run -it ^
-v %APP_HOME%\.travis:/root/.travis ^
-v %APP_HOME%:/opt/code ^
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh %*
endlocal

Просмотреть файл

@ -23,28 +23,38 @@ namespace Microsoft.Azure.IoTSolutions.UIConfig.Services.Runtime
private readonly IConfigurationRoot configuration;
private readonly ILogger log;
// Key Vault
private KeyVault keyVault;
// Constants
private const string CLIENT_ID = "KeyVault:aadAppId";
private const string CLIENT_SECRET = "KeyVault:aadAppSecret";
private const string KEY_VAULT_NAME = "KeyVault:name";
public ConfigData(ILogger logger)
{
this.log = logger;
// More info about configuration at
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddIniFile("appsettings.ini", optional: true, reloadOnChange: true);
this.configuration = configurationBuilder.Build();
// Set up Key Vault
this.SetUpKeyVault();
}
public string GetString(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
var value = this.GetSecrets(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
public bool GetBool(string key, bool defaultValue = false)
{
var value = this.GetString(key, defaultValue.ToString()).ToLowerInvariant();
var value = this.GetSecrets(key, defaultValue.ToString()).ToLowerInvariant();
var knownTrue = new HashSet<string> { "true", "t", "yes", "y", "1", "-1" };
var knownFalse = new HashSet<string> { "false", "f", "no", "n", "0" };
@ -59,7 +69,7 @@ namespace Microsoft.Azure.IoTSolutions.UIConfig.Services.Runtime
{
try
{
return Convert.ToInt32(this.GetString(key, defaultValue.ToString()));
return Convert.ToInt32(this.GetSecrets(key, defaultValue.ToString()));
}
catch (Exception e)
{
@ -67,6 +77,49 @@ namespace Microsoft.Azure.IoTSolutions.UIConfig.Services.Runtime
}
}
private void SetUpKeyVault()
{
var clientId = this.GetEnvironmentVariable(CLIENT_ID, string.Empty);
var clientSecret = this.GetEnvironmentVariable(CLIENT_SECRET, string.Empty);
var keyVaultName = this.GetEnvironmentVariable(KEY_VAULT_NAME, string.Empty);
// Initailize key vault
this.keyVault = new KeyVault(keyVaultName, clientId, clientSecret, this.log);
}
private string GetSecrets(string key, string defaultValue = "")
{
string value = string.Empty;
value = this.GetLocalVariables(key, defaultValue);
// If secrets are not found locally, search in Key-Vault
if (string.IsNullOrEmpty(value))
{
log.Warn($"Value for secret {key} not found in local env. " +
$" Trying to get the secret from KeyVault.", () => { });
value = this.keyVault.GetSecret(key);
}
return !string.IsNullOrEmpty(value) ? value : defaultValue;
}
private string GetSecretsFromKeyVault(string key) {
return this.keyVault.GetSecret(key);
}
private string GetLocalVariables(string key, string defaultValue = "")
{
return this.configuration.GetValue(key, defaultValue);
}
public string GetEnvironmentVariable(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
private void ReplaceEnvironmentVariables(ref string value, string defaultValue = "")
{
if (string.IsNullOrEmpty(value)) return;

Просмотреть файл

@ -0,0 +1,71 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.IoTSolutions.UIConfig.Services.Diagnostics;
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
namespace Microsoft.Azure.IoTSolutions.UIConfig.Services.Runtime
{
public class KeyVault
{
// Key Vault details and access
private readonly string name;
private readonly string clientId;
private readonly string clientSecret;
private ILogger log;
// Key Vault Client
private readonly KeyVaultClient keyVaultClient;
// Constants
private const string KEY_VAULT_URI = "https://{0}.vault.azure.net/secrets/{1}";
public KeyVault(
string name,
string clientId,
string clientSecret,
ILogger logger)
{
this.name = name;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.log = logger;
this.keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(this.GetToken));
}
public string GetSecret(string secretKey)
{
secretKey = secretKey.Split(':').Last();
var uri = string.Format(KEY_VAULT_URI, this.name, secretKey);
try
{
return this.keyVaultClient.GetSecretAsync(uri).Result.Value;
}
catch (Exception e)
{
this.log.Error($"Secret {secretKey} not found in Key Vault.", () => { });
return null;
}
}
//the method that will be provided to the KeyVaultClient
private async Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
ClientCredential clientCred = new ClientCredential(this.clientId, this.clientSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
{
this.log.Debug($"Failed to obtain authentication token from key vault.", () => { });
throw new System.InvalidOperationException("Failed to obtain the JWT token");
}
return result.AccessToken;
}
}
}

Просмотреть файл

@ -22,6 +22,8 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="2.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="4.5.0" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="2.0.6" />
</ItemGroup>
<ItemGroup>
<None Update="Data\device-simulation-template.json">

Просмотреть файл

@ -1,26 +1,23 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:9005/",
"sslPort": 0
}
},
"profiles": {
"WebService": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "http://localhost:9005/v1/status",
"environmentVariables": {
"PCS_STORAGEADAPTER_WEBSERVICE_URL": "http://localhost:9022/v1",
"PCS_TELEMETRY_WEBSERVICE_URL": "http://localhost:9004/v1",
"PCS_DEVICESIMULATION_WEBSERVICE_URL": "http://localhost:9003/v1",
"PCS_AZUREMAPS_KEY": "static",
"PCS_AUTH_WEBSERVICE_URL": "http://localhost:9001/v1",
"PCS_AUTH_REQUIRED": "false"
},
"applicationUrl": "http://localhost:9005/v1/status"
}
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:9005/",
"sslPort": 0
}
},
"profiles": {
"WebService": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "http://localhost:9005/v1/status",
"environmentVariables": {
"PCS_KEYVAULT_NAME": "$(PCS_KEYVAULT_NAME)",
"PCS_AAD_APPID": "$(PCS_AAD_APPID)",
"PCS_AAD_APPSECRET": "$(PCS_AAD_APPSECRET)"
},
"applicationUrl": "http://localhost:9005/v1/status"
}
}
}

Просмотреть файл

@ -22,39 +22,39 @@ namespace Microsoft.Azure.IoTSolutions.UIConfig.WebService.Runtime
public class Config : IConfig
{
private const string APPLICATION_KEY = "ConfigService:";
private const string PORT_KEY = APPLICATION_KEY + "webservice_port";
private const string PORT_KEY = APPLICATION_KEY + "webservicePort";
private const string SOLUTION_TYPE_KEY = APPLICATION_KEY + "solutionType";
private const string SEED_TEMPLATE_KEY = APPLICATION_KEY + "seedTemplate";
private const string AZURE_MAPS_KEY = APPLICATION_KEY + "azuremaps_key";
private const string AZURE_MAPS_KEY = APPLICATION_KEY + "azureMapsKey";
private const string STORAGE_ADAPTER_KEY = "StorageAdapterService:";
private const string STORAGE_ADAPTER_URL_KEY = STORAGE_ADAPTER_KEY + "webservice_url";
private const string EXTERNAL_DEPENDENCIES_KEY = "ExternalDependencies:";
private const string STORAGE_ADAPTER_URL_KEY = EXTERNAL_DEPENDENCIES_KEY + "storageAdapterWebServiceUrl";
private const string DEVICE_SIMULATION_URL_KEY = EXTERNAL_DEPENDENCIES_KEY + "deviceSimulationWebServiceUrl";
private const string TELEMETRY_URL_KEY = EXTERNAL_DEPENDENCIES_KEY + "telemetryWebServiceUrl";
private const string DEVICE_SIMULATION_KEY = "DeviceSimulationService:";
private const string DEVICE_SIMULATION_URL_KEY = DEVICE_SIMULATION_KEY + "webservice_url";
private const string TELEMETRY_KEY = "TelemetryService:";
private const string TELEMETRY_URL_KEY = TELEMETRY_KEY + "webservice_url";
private const string CLIENT_AUTH_KEY = APPLICATION_KEY + "ClientAuth:";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "cors_whitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "auth_type";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "auth_required";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "corsWhitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "authType";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "authRequired";
private const string JWT_KEY = APPLICATION_KEY + "ClientAuth:JWT:";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowed_algorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "issuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "audience";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clock_skew_seconds";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowedAlgorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "authIssuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "aadAppId";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clockSkewSeconds";
private const string USER_MANAGEMENT_KEY = "UserManagementService:";
private const string USER_MANAGEMENT_URL_KEY = USER_MANAGEMENT_KEY + "webservice_url";
private const string USER_MANAGEMENT_URL_KEY = USER_MANAGEMENT_KEY + "authWebServiceUrl";
private const string ACTIONS_KEY = APPLICATION_KEY + "Actions:";
private const string OFFICE365_LOGIC_APP_URL_KEY = ACTIONS_KEY + "office365_logic_app_url";
private const string RESOURCE_GROUP_KEY = ACTIONS_KEY + "resource_group";
private const string SUBSCRIPTION_ID_KEY = ACTIONS_KEY + "subscription_id";
private const string MANAGEMENT_API_VERSION_KEY = ACTIONS_KEY + "management_api_version";
private const string ARM_ENDPOINT_URL_KEY = ACTIONS_KEY + "arm_endpoint_url";
private const string OFFICE365_LOGIC_APP_URL_KEY = ACTIONS_KEY + "office365ConnectionUrl";
private const string RESOURCE_GROUP_KEY = ACTIONS_KEY + "solutionName";
private const string SUBSCRIPTION_ID_KEY = ACTIONS_KEY + "subscriptionId";
private const string MANAGEMENT_API_VERSION_KEY = ACTIONS_KEY + "managementApiVersion";
private const string ARM_ENDPOINT_URL_KEY = ACTIONS_KEY + "armEndpointUrl";
public int Port { get; }
public IServicesConfig ServicesConfig { get; }

Просмотреть файл

@ -1,56 +1,46 @@
[ConfigService]
webservice_port = 9005
solutionType = "${?PCS_SOLUTION_TYPE}"
seedTemplate = "${?PCS_SEED_TEMPLATE}"
azuremaps_key = "${PCS_AZUREMAPS_KEY}"
[StorageAdapterService]
webservice_url = "${PCS_STORAGEADAPTER_WEBSERVICE_URL}"
[DeviceSimulationService]
webservice_url = "${PCS_DEVICESIMULATION_WEBSERVICE_URL}"
[TelemetryService]
webservice_url = "${PCS_TELEMETRY_WEBSERVICE_URL}"
[UserManagementService]
webservice_url = "${PCS_AUTH_WEBSERVICE_URL}"
webservicePort = 9005
solutionType = ""
seedTemplate = ""
azureMapsKey = ""
[ExternalDependencies]
;; Urls to external services
storageAdapterWebServiceUrl = ""
deviceSimulationWebServiceUrl = ""
telemetryWebServiceUrl = ""
authWebServiceUrl = ""
[ConfigService:Actions]
;; Url for the Office365 Logic App Connector in the Azure portal
office365_logic_app_url = "${PCS_OFFICE365_CONNECTION_URL}"
office365ConnectionUrl = ""
;; Resource group name, arm endpoint, and Subscription ID for the
;; Office365 Logic App Connector API call.
resource_group = "${PCS_SOLUTION_NAME}"
subscription_id = "${PCS_SUBSCRIPTION_ID}"
arm_endpoint_url = "${PCS_ARM_ENDPOINT_URL}"
solutionName = ""
subscriptionId = ""
armEndpointUrl = ""
;; api version for the azure management apis
management_api_version = "2016-06-01"
managementApiVersion = "2016-06-01"
[ConfigService:ClientAuth]
;; Current auth type, only "JWT" is currently supported.
auth_type="JWT"
authType="JWT"
;; This can be changed to false, for example during development,
;; to allow invalid/missing authorizations.
;; Default: true
auth_required="${?PCS_AUTH_REQUIRED}"
authRequired=""
;; Can be used when running services on multiple hostnames and/or ports
;; e.g. "{ 'origins': ['*'], 'methods': ['*'], 'headers': ['*'] }" to allow everything.
;; Comment it or leave it empty to disable CORS.
;; Default: empty
cors_whitelist = "${?PCS_CORS_WHITELIST}"
corsWhitelist = ""
[ConfigService:ClientAuth:JWT]
; Trusted algorithms
; Default: RS256, RS384, RS512
allowed_algorithms="RS256"
allowedAlgorithms="RS256"
; Identifies the security token service (STS) that constructs and returns the token.
; In the tokens that Azure AD returns, the issuer is sts.windows.net. The GUID in
; the Issuer claim value is the tenant ID of the Azure AD directory. The tenant ID
@ -59,15 +49,19 @@ allowed_algorithms="RS256"
; When using Azure Active Directory, the format of the Issuer is:
; https://sts.windows.net/<tenant Id>/
; example: issuer="https://sts.windows.net/fa01ade2-2365-4dd1-a084-a6ef027090fc/"
issuer="${?PCS_AUTH_ISSUER}"
authIssuer=""
; Used to verify that tokens are issued to be given to this service
; Also referenced as "Application Id" and "Resource Id"
; example: audience="2814e709-6a0e-4861-9594-d3b6e2b81331"
audience="${?PCS_AUTH_AUDIENCE}"
aadTenantId=""
; When validating the token expiration, allows some clock skew
; Default: 2 minutes
clock_skew_seconds = 300
clockSkewSeconds = 300
[KeyVault]
aadAppId = ${PCS_AAD_APPID}
aadAppSecret = ${PCS_AAD_APPSECRET}
name = ${PCS_KEYVAULT_NAME}
; For more information about ASP.NET logging see
; https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging
@ -75,7 +69,8 @@ clock_skew_seconds = 300
; internal logs generated by ASP.NET
; ASP.NET log levels: Trace, Debug, Information, Warning, Error, Critical
[Logging]
IncludeScopes = true
includeScopes = true
LogLevel:Default = "Warning"
LogLevel:System = "Warning"
LogLevel:Microsoft = "Warning"

Просмотреть файл

@ -13,22 +13,9 @@ run_container() {
echo "Starting Config service ..."
docker run -it -p 9005:9005 \
-e PCS_AUTH_WEBSERVICE_URL \
-e PCS_STORAGEADAPTER_WEBSERVICE_URL \
-e PCS_DEVICESIMULATION_WEBSERVICE_URL \
-e PCS_TELEMETRY_WEBSERVICE_URL \
-e PCS_SOLUTION_TYPE \
-e PCS_AZUREMAPS_KEY \
-e PCS_AUTH_ISSUER \
-e PCS_AUTH_AUDIENCE \
-e PCS_AUTH_REQUIRED \
-e PCS_CORS_WHITELIST \
-e PCS_APPLICATION_SECRET \
-e PCS_OFFICE365_CONNECTION_URL \
-e PCS_SOLUTION_NAME \
-e PCS_SUBSCRIPTION_ID \
-e PCS_ARM_ENDPOINT_URL \
-e PCS_SEED_TEMPLATE \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
"$DOCKER_IMAGE:testing"
}

Просмотреть файл

@ -19,22 +19,9 @@ IF %ERRORLEVEL% NEQ 0 GOTO FAIL
:: Start the application
echo Starting Config web service ...
docker run -it -p 9005:9005 ^
-e PCS_AUTH_WEBSERVICE_URL ^
-e PCS_STORAGEADAPTER_WEBSERVICE_URL ^
-e PCS_DEVICESIMULATION_WEBSERVICE_URL ^
-e PCS_TELEMETRY_WEBSERVICE_URL ^
-e PCS_SOLUTION_TYPE ^
-e PCS_AZUREMAPS_KEY ^
-e PCS_AUTH_ISSUER ^
-e PCS_AUTH_AUDIENCE ^
-e PCS_AUTH_REQUIRED ^
-e PCS_CORS_WHITELIST ^
-e PCS_APPLICATION_SECRET ^
-e PCS_OFFICE365_CONNECTION_URL ^
-e PCS_SOLUTION_NAME ^
-e PCS_SUBSCRIPTION_ID ^
-e PCS_ARM_ENDPOINT_URL ^
-e PCS_SEED_TEMPLATE ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
%DOCKER_IMAGE%:testing
:: - - - - - - - - - - - - - -

Просмотреть файл

@ -1,55 +1,17 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Before checking all the env vars, detect whether secrets, usually encrypted, are available or not.
# Secrets are not available when building a pull request, so the script will not check for those.
detect_secrets() {
SECRETS_AVAILABLE="true"
if [[ "$TRAVIS_PULL_REQUEST" != "" && "$TRAVIS_PULL_REQUEST" != "false" ]]; then
SECRETS_AVAILABLE="false"
echo "Warning: secrets and encrypted variables are not available when testing pull requests."
fi
}
detect_secrets
if [[ -z "$PCS_STORAGEADAPTER_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_STORAGEADAPTER_WEBSERVICE_URL environment variable is not defined."
exit -1
if [[ -z "$PCS_KEYVAULT_NAME" ]]; then
echo "Error: the PCS_KEYVAULT_NAME environment variable is not defined."
exit 1
fi
if [[ -z "$PCS_DEVICESIMULATION_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_DEVICESIMULATION_WEBSERVICE_URL environment variable is not defined."
exit -1
if [[ -z "$PCS_AAD_APPID" ]]; then
echo "Error: the PCS_AAD_APPID environment variable is not defined."
exit 1
fi
if [[ -z "$PCS_TELEMETRY_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_TELEMETRY_WEBSERVICE_URL environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_AZUREMAPS_KEY" && "$SECRETS_AVAILABLE" = "true" ]]; then
echo "Error: the PCS_AZUREMAPS_KEY environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_AUTH_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_AUTH_WEBSERVICE_URL environment variable is not defined."
exit -1
fi
# Optional environment variables
if [[ -z "$PCS_OFFICE365_CONNECTION_URL" ]]; then
echo "Warning: the PCS_OFFICE365_CONNECTION_URL environment variable is not defined."
fi
if [[ -z "$PCS_SOLUTION_NAME" ]]; then
echo "Warning: the PCS_SOLUTION_NAME environment variable is not defined."
fi
if [[ -z "$PCS_SUBSCRIPTION_ID" ]]; then
echo "Warning: the PCS_SUBSCRIPTION_ID environment variable is not defined."
fi
if [[ -z "$PCS_ARM_ENDPOINT_URL" ]]; then
echo "Warning: the PCS_ARM_ENDPOINT_URL environment variable is not defined."
if [[ -z "$PCS_AAD_APPSECRET" ]]; then
echo "Error: the PCS_AAD_APPSECRET environment variable is not defined."
exit 1
fi

Просмотреть файл

@ -1,45 +1,20 @@
:: Copyright (c) Microsoft. All rights reserved.
@ECHO off & setlocal enableextensions enabledelayedexpansion
IF "%PCS_STORAGEADAPTER_WEBSERVICE_URL%" == "" (
echo Error: the PCS_STORAGEADAPTER_WEBSERVICE_URL environment variable is not defined.
IF "%PCS_KEYVAULT_NAME%" == "" (
echo Error: the PCS_KEYVAULT_NAME environment variable is not defined.
exit /B 1
)
IF "%PCS_DEVICESIMULATION_WEBSERVICE_URL%" == "" (
echo Error: the PCS_DEVICESIMULATION_WEBSERVICE_URL environment variable is not defined.
IF "%PCS_AAD_APPID%" == "" (
echo Error: the PCS_AAD_APPID environment variable is not defined.
exit /B 1
)
IF "%PCS_TELEMETRY_WEBSERVICE_URL%" == "" (
echo Error: the PCS_TELEMETRY_WEBSERVICE_URL environment variable is not defined.
IF "%PCS_AAD_APPSECRET%" == "" (
echo Error: the PCS_AAD_APPSECRET environment variable is not defined.
exit /B 1
)
IF "%PCS_AZUREMAPS_KEY%" == "" (
echo Error: the PCS_AZUREMAPS_KEY environment variable is not defined.
exit /B 1
)
IF "%PCS_AUTH_WEBSERVICE_URL%" == "" (
echo Error: the PCS_AUTH_WEBSERVICE_URL environment variable is not defined.
exit /B 1
)
:: Optional environment variables
IF "%PCS_OFFICE365_CONNECTION_URL%" == "" (
echo Warning: the PCS_OFFICE365_CONNECTION_URL environment variable is not defined.
)
IF "%PCS_SOLUTION_NAME%" == "" (
echo Warning: the $PCS_SOLUTION_NAME environment variable is not defined.
)
IF "%PCS_SUBSCRIPTION_ID%" == "" (
echo Warning: the PCS_SUBSCRIPTION_ID environment variable is not defined.
)
IF "%PCS_ARM_ENDPOINT_URL%" == "" (
echo Warning: the PCS_ARM_ENDPOINT_URL environment variable is not defined.
)
endlocal

Просмотреть файл

@ -1,25 +0,0 @@
#!/usr/bin/env bash
# Usage: source ./scripts/env-vars-setup
#
# IMPORTANT NOTES:
# * use "source" in front of the script path, so that variables are exported in your shell
# * the variables are set only in the current shell, run this script every time, or automate
# the setup using your `~/.bash_profile`.
# Prepare the environment variables used by the application
# The URL where Storage Adapter web service is listening
export PCS_STORAGEADAPTER_WEBSERVICE_URL="http://127.0.0.1:9022/v1"
# The URL where Telemetry web service is listening
export PCS_TELEMETRY_WEBSERVICE_URL="http://127.0.0.1:9004/v1"
# The URL where Device Simulation web service is listening
export PCS_DEVICESIMULATION_WEBSERVICE_URL="http://127.0.0.1:9003/v1"
# The Azure Maps Api key
export PCS_AZUREMAPS_KEY="static"
# The URL where Authentication web service is listening
export PCS_AUTH_WEBSERVICE_URL="http://127.0.0.1:9001/v1"

Просмотреть файл

@ -1,16 +0,0 @@
:: Prepare the environment variables used by the application
:: Endpoint to reach the storage adapter
SETX PCS_STORAGEADAPTER_WEBSERVICE_URL "http://localhost:9022/v1"
:: Endpoint to reach the telemetry
SETX PCS_TELEMETRY_WEBSERVICE_URL "http://localhost:9004/v1"
:: Endpoint to reach the device simlation
SETX PCS_DEVICESIMULATION_WEBSERVICE_URL "http://localhost:9003/v1"
:: Azure Maps API Key
SETX PCS_AZUREMAPS_KEY "static"
:: Endpoint to reach the authentication service
SETX PCS_AUTH_WEBSERVICE_URL "http://localhost:9001/v1"

Просмотреть файл

@ -47,14 +47,9 @@ run_in_sandbox() {
# edit the list of variables.
docker run -it \
-p 9005:9005 \
-e PCS_STORAGEADAPTER_WEBSERVICE_URL \
-e PCS_DEVICESIMULATION_WEBSERVICE_URL \
-e PCS_TELEMETRY_WEBSERVICE_URL \
-e PCS_AUTH_WEBSERVICE_URL \
-e PCS_OFFICE365_CONNECTION_URL \
-e PCS_SOLUTION_NAME \
-e PCS_SUBSCRIPTION_ID \
-e PCS_ARM_ENDPOINT_URL \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
-v "$PCS_CACHE/sandbox/.config:/root/.config" \
-v "$PCS_CACHE/sandbox/.dotnet:/root/.dotnet" \
-v "$PCS_CACHE/sandbox/.nuget:/root/.nuget" \

Просмотреть файл

@ -58,16 +58,11 @@ IF "%1"=="--in-sandbox" GOTO :RunInSandbox
IF %ERRORLEVEL% NEQ 0 GOTO FAIL
:: Start the sandbox and run the application
docker run -it ^
docker run --detach ^
-p 9005:9005 ^
-e PCS_STORAGEADAPTER_WEBSERVICE_URL ^
-e PCS_DEVICESIMULATION_WEBSERVICE_URL ^
-e PCS_TELEMETRY_WEBSERVICE_URL ^
-e PCS_AUTH_WEBSERVICE_URL ^
-e PCS_OFFICE365_CONNECTION_URL ^
-e PCS_SOLUTION_NAME ^
-e PCS_SUBSCRIPTION_ID ^
-e PCS_ARM_ENDPOINT_URL ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
-v %PCS_CACHE%\sandbox\.config:/root/.config ^
-v %PCS_CACHE%\sandbox\.dotnet:/root/.dotnet ^
-v %PCS_CACHE%\sandbox\.nuget:/root/.nuget ^

Просмотреть файл

@ -1,26 +0,0 @@
#!/usr/bin/env bash -e
# Example usage (see "travis help" for more information):
# travis help
# travis login --pro
# travis whoami --pro
# travis accounts --pro
# travis history
# travis monitor --pro
# travis settings
# travis show
# travis status
# travis token --pro
# travis whatsup --pro
APP_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )/"
cd $APP_HOME
mkdir -p .travis
docker run -it \
-v $APP_HOME/.travis:/root/.travis \
-v $APP_HOME:/opt/code \
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh $*
set +e

Просмотреть файл

@ -1,28 +0,0 @@
@ECHO off & setlocal enableextensions enabledelayedexpansion
:: Example usage (see "travis help" for more information:
:: travis help
:: travis login --pro
:: travis whoami --pro
:: travis accounts --pro
:: travis history
:: travis monitor --pro
:: travis settings
:: travis show
:: travis status
:: travis token --pro
:: travis whatsup --pro
:: strlen("\scripts\") => 9
SET APP_HOME=%~dp0
SET APP_HOME=%APP_HOME:~0,-9%
cd %APP_HOME%
mkdir .travis 2>NUL
docker run -it ^
-v %APP_HOME%\.travis:/root/.travis ^
-v %APP_HOME%:/opt/code ^
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh %*
endlocal

Просмотреть файл

@ -3,4 +3,9 @@
cd /app/
echo "Setting environment variables."
# Running in current shell
. set_env.sh PCS_IOTHUB_CONNSTRING iotHubConnectionString PCS_STORAGEADAPTER_WEBSERVICE_URL storageAdapterWebServiceUrl
echo "Starting service."
cd webservice && dotnet Microsoft.Azure.IoTSolutions.DeviceSimulation.WebService.dll

Просмотреть файл

@ -0,0 +1,100 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
AUTH_SERVER_URL=""
RESOURCE_TYPE=""
AUTH_TOKEN=""
# Acquires auth token for authroizating against key vault.
_acquire_token() {
__set_keyvault_auth_server
local _temp=$(curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "client_id=$PCS_AAD_APPID&resource=https%3A%2F%2Fvault.azure.net&client_secret=$PCS_AAD_APPSECRET&grant_type=client_credentials" $AUTH_SERVER_URL/oauth2/token)
AUTH_TOKEN=$(__parse_json $_temp "access_token")
}
# Fetch key vault secret.
_get_keyvault_secret() {
# Get a new token each time you access key vault.
_acquire_token
_keyvault_secret_bundle=$(curl -H "Authorization: Bearer $AUTH_TOKEN" -L https://$PCS_KEYVAULT_NAME.vault.azure.net/secrets/$1/?api-version=7.0)
_keyvault_secret_bundle="'$_keyvault_secret_bundle'"
# return the secret value.
echo $(__parse_json $_keyvault_secret_bundle "value")
}
# Gets keyvault auth server by examining response headers of unauthenticated request to key vault.
# The 401 redirect contains WWW-Authenticate header which has KV auth server and resource type.
__set_keyvault_auth_server() {
# Bare (unauthenticated) request to get secret.
key_vault_wo_auth_call=$(curl -i -L "https://$PCS_KEYVAULT_NAME.vault.azure.net/secrets/authEnabled/?api-version=7.0" | grep -Fi WWW-Authenticate)
wo_auth_call_resp_header=${key_vault_wo_auth_call#*:}
# Extract auth server (url) & resource from WWW-Authenticate header.
IFS=',' read -ra PARAMS <<< "$wo_auth_call_resp_header"
for (( i = 0; i < 2; ++i )); do
if [ $i == 0 ]; then
__extract_auth_server ${PARAMS[0]}
else
__extract_resource_type ${PARAMS[1]}
fi
done
}
############# Helper functions #############
#Removes Bearer authorization prefix to extract auth server url from 401 redirect of keyvault.
__extract_auth_server() {
AUTH_SERVER_URL=$(__extract_value_from_double_quotes $2)
}
#Removes "resource" prefix to extract resource type from 401 redirect of keyvault.
__extract_resource_type() {
RESOURCE_TYPE=$(__extract_value_from_double_quotes $1)
}
__extract_value_from_double_quotes() {
local string=$1
# Remove trailing and prefixed double quotes.
local _temp=${string#*'"'}
_temp=${_temp%'"'}
#return the value
echo $_temp
}
__parse_json() {
_temp=`echo $1 | sed 's/\\\\\//\//g' | sed 's/[{}]//g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}' | sed 's/\"\:\"/\|/g' | sed 's/[\,]/ /g' | sed 's/\"//g' | grep -w $2`;
echo ${_temp##*|};
}
############# Main function #############
set_env_vars() {
# parse through all variables (Every odd variable is env var name & even variables are secret key names in Key vault).
while test ${#} -gt 0
do
_key=$1
_value=$(_get_keyvault_secret $2)
# export in current shell
export $_key=$_value
shift
shift
done
}
main() {
if [[ "$PCS_KEYVAULT_NAME" != "" ]] && [[ "$PCS_AAD_APPID" != "" ]] && [[ "$PCS_AAD_APPSECRET" != "" ]]; then
set_env_vars $@
fi
}
main $@

Просмотреть файл

@ -16,10 +16,10 @@ run_container() {
echo "Starting Device Simulation ..."
docker run --detach -p 9003:9003 \
-e PCS_IOTHUB_CONNSTRING \
-e PCS_STORAGEADAPTER_WEBSERVICE_URL="http://host.docker.internal:9022/v1" \
-e PCS_SUBSCRIPTION_ID \
"$DOCKER_IMAGE:DS-1.0.3"
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
"$DOCKER_IMAGE:DS-1.0.5"
}
run_container

Просмотреть файл

@ -20,11 +20,11 @@ IF %ERRORLEVEL% NEQ 0 GOTO FAIL
:: Start the application
echo Starting Device Simulation ...
docker run -it -p 9003:9003 ^
-e PCS_IOTHUB_CONNSTRING ^
-e PCS_STORAGEADAPTER_WEBSERVICE_URL="http://host.docker.internal:9022/v1" ^
-e PCS_SUBSCRIPTION_ID ^
%DOCKER_IMAGE%:testing
docker run --detach -p 9003:9003 ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
%DOCKER_IMAGE%:DS-1.0.5
:: - - - - - - - - - - - - - -
goto :END

Просмотреть файл

@ -1,24 +1,17 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Before checking all the env vars, detect whether secrets, usually encrypted, are available or not.
# Secrets are not available when building a pull request, so the script will not check for those.
detect_secrets() {
SECRETS_AVAILABLE="true"
if [[ "$TRAVIS_PULL_REQUEST" != "" && "$TRAVIS_PULL_REQUEST" != "false" ]]; then
SECRETS_AVAILABLE="false"
echo "Warning: secrets and encrypted variables are not available when testing pull requests."
fi
}
detect_secrets
if [[ -z "$PCS_IOTHUB_CONNSTRING" && "$SECRETS_AVAILABLE" = "true" ]]; then
echo "Error: the PCS_IOTHUB_CONNSTRING environment variable is not defined."
if [[ -z "$PCS_KEYVAULT_NAME" ]]; then
echo "Error: the PCS_KEYVAULT_NAME environment variable is not defined."
exit 1
fi
if [[ -z "$PCS_STORAGEADAPTER_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_STORAGEADAPTER_WEBSERVICE_URL environment variable is not defined."
if [[ -z "$PCS_AAD_APPID" ]]; then
echo "Error: the PCS_AAD_APPID environment variable is not defined."
exit 1
fi
if [[ -z "$PCS_AAD_APPSECRET" ]]; then
echo "Error: the PCS_AAD_APPSECRET environment variable is not defined."
exit 1
fi

Просмотреть файл

@ -2,13 +2,18 @@
@ECHO off & setlocal enableextensions enabledelayedexpansion
IF "%PCS_IOTHUB_CONNSTRING%" == "" (
echo Error: the PCS_IOTHUB_CONNSTRING environment variable is not defined.
IF "%PCS_KEYVAULT_NAME%" == "" (
echo Error: the PCS_KEYVAULT_NAME environment variable is not defined.
exit /B 1
)
IF "%PCS_STORAGEADAPTER_WEBSERVICE_URL%" == "" (
echo Error: the PCS_STORAGEADAPTER_WEBSERVICE_URL environment variable is not defined.
IF "%PCS_AAD_APPID%" == "" (
echo Error: the PCS_AAD_APPID environment variable is not defined.
exit /B 1
)
IF "%PCS_AAD_APPSECRET%" == "" (
echo Error: the PCS_AAD_APPSECRET environment variable is not defined.
exit /B 1
)

Просмотреть файл

@ -1,16 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Prepare the environment variables used by the application.
#
# For more information about finding IoT Hub settings, more information here:
#
# * https://docs.microsoft.com/azure/iot-hub/iot-hub-create-through-portal#endpoints
# * https://docs.microsoft.com/azure/iot-hub/iot-hub-csharp-csharp-getstarted
#
# Azure IoT Hub Connection string
export PCS_IOTHUB_CONNSTRING="your Azure IoT Hub connection string"
# Endpoint to reach the storage adapter
export PCS_STORAGEADAPTER_WEBSERVICE_URL="http://127.0.0.1:9022/v1"

Просмотреть файл

@ -1,15 +0,0 @@
:: Copyright (c) Microsoft. All rights reserved.
:: Prepare the environment variables used by the application.
::
:: For more information about finding IoT Hub settings, more information here:
::
:: * https://docs.microsoft.com/azure/iot-hub/iot-hub-create-through-portal#endpoints
:: * https://docs.microsoft.com/azure/iot-hub/iot-hub-csharp-csharp-getstarted
::
:: Azure IoT Hub Connection string
SETX PCS_IOTHUB_CONNSTRING "your Azure IoT Hub connection string"
:: Endpoint to reach the storage adapter
SETX PCS_STORAGEADAPTER_WEBSERVICE_URL "http://127.0.0.1:9022/v1"

Просмотреть файл

@ -23,28 +23,38 @@ namespace Microsoft.Azure.IoTSolutions.DeviceTelemetry.Services.Runtime
private readonly IConfigurationRoot configuration;
private readonly ILogger log;
// Key Vault
private KeyVault keyVault;
// Constants
private const string CLIENT_ID = "KeyVault:aadAppId";
private const string CLIENT_SECRET = "KeyVault:aadAppSecret";
private const string KEY_VAULT_NAME = "KeyVault:name";
public ConfigData(ILogger logger)
{
this.log = logger;
// More info about configuration at
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddIniFile("appsettings.ini", optional: true, reloadOnChange: true);
this.configuration = configurationBuilder.Build();
// Set up Key Vault
this.SetUpKeyVault();
}
public string GetString(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
var value = this.GetSecrets(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
public bool GetBool(string key, bool defaultValue = false)
{
var value = this.GetString(key, defaultValue.ToString()).ToLowerInvariant();
var value = this.GetSecrets(key, defaultValue.ToString()).ToLowerInvariant();
var knownTrue = new HashSet<string> { "true", "t", "yes", "y", "1", "-1" };
var knownFalse = new HashSet<string> { "false", "f", "no", "n", "0" };
@ -59,7 +69,7 @@ namespace Microsoft.Azure.IoTSolutions.DeviceTelemetry.Services.Runtime
{
try
{
return Convert.ToInt32(this.GetString(key, defaultValue.ToString()));
return Convert.ToInt32(this.GetSecrets(key, defaultValue.ToString()));
}
catch (Exception e)
{
@ -67,6 +77,49 @@ namespace Microsoft.Azure.IoTSolutions.DeviceTelemetry.Services.Runtime
}
}
private void SetUpKeyVault()
{
var clientId = this.GetEnvironmentVariable(CLIENT_ID, string.Empty);
var clientSecret = this.GetEnvironmentVariable(CLIENT_SECRET, string.Empty);
var keyVaultName = this.GetEnvironmentVariable(KEY_VAULT_NAME, string.Empty);
// Initailize key vault
this.keyVault = new KeyVault(keyVaultName, clientId, clientSecret, this.log);
}
private string GetSecrets(string key, string defaultValue = "")
{
string value = string.Empty;
value = this.GetLocalVariable(key, defaultValue);
// If secrets are not found locally, search in Key-Vault
if (string.IsNullOrEmpty(value))
{
log.Warn($"Value for secret {key} not found in local env. " +
$" Trying to get the secret from KeyVault.", () => { });
value = this.keyVault.GetSecret(key);
}
return !string.IsNullOrEmpty(value) ? value : defaultValue;
}
private string GetSecretsFromKeyVault(string key) {
return this.keyVault.GetSecret(key);
}
private string GetLocalVariable(string key, string defaultValue = "")
{
return this.configuration.GetValue(key, defaultValue);
}
public string GetEnvironmentVariable(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
private void ReplaceEnvironmentVariables(ref string value, string defaultValue = "")
{
if (string.IsNullOrEmpty(value)) return;

Просмотреть файл

@ -0,0 +1,71 @@
using Microsoft.Azure.IoTSolutions.DeviceTelemetry.Services.Diagnostics;
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.Azure.IoTSolutions.DeviceTelemetry.Services.Runtime
{
public class KeyVault
{
// Key Vault details and access
private readonly string name;
private readonly string clientId;
private readonly string clientSecret;
private ILogger log;
// Key Vault Client
private readonly KeyVaultClient keyVaultClient;
// Constants
private const string KEY_VAULT_URI = "https://{0}.vault.azure.net/secrets/{1}";
public KeyVault(
string name,
string clientId,
string clientSecret,
ILogger logger)
{
this.name = name;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.log = logger;
this.keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(this.GetToken));
}
public string GetSecret(string secretKey)
{
secretKey = secretKey.Split(':').Last();
var uri = string.Format(KEY_VAULT_URI, this.name, secretKey);
try
{
return this.keyVaultClient.GetSecretAsync(uri).Result.Value;
}
catch (Exception)
{
this.log.Error($"Secret {secretKey} not found in Key Vault.", () => { });
return null;
}
}
//the method that will be provided to the KeyVaultClient
private async Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
ClientCredential clientCred = new ClientCredential(this.clientId, this.clientSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
{
this.log.Debug($"Failed to obtain authentication token from key vault.", () => { });
throw new System.InvalidOperationException("Failed to obtain the JWT token");
}
return result.AccessToken;
}
}
}

Просмотреть файл

@ -11,6 +11,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="2.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="3.19.8" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.3" />
</ItemGroup>
<ItemGroup>
<None Update="Data\Rules\default.json">

Просмотреть файл

@ -13,21 +13,9 @@
"launchBrowser": true,
"launchUrl": "http://localhost:9004/v1/status",
"environmentVariables": {
"PCS_TELEMETRY_DOCUMENTDB_CONNSTRING": "$(PCS_TELEMETRY_DOCUMENTDB_CONNSTRING)",
"PCS_TELEMETRY_STORAGE_TYPE": "$(PCS_TELEMETRY_STORAGE_TYPE)",
"PCS_STORAGEADAPTER_WEBSERVICE_URL": "http://localhost:9022/v1",
"PCS_AUTH_WEBSERVICE_URL": "http://localhost:9001/v1",
"PCS_TSI_FQDN": "$(PCS_TSI_FQDN)",
"PCS_KEYVAULT_NAME": "$(PCS_KEYVAULT_NAME)",
"PCS_AAD_APPID": "$(PCS_AAD_APPID)",
"PCS_AAD_APPSECRET": "$(PCS_AAD_APPSECRET)",
"PCS_AAD_TENANT": "$(PCS_AAD_TENANT)",
"PCS_DIAGNOSTICS_WEBSERVICE_URL": "http://localhost:9006/v1",
"PCS_AUTH_REQUIRED": "false",
"PCS_AZUREBLOB_CONNSTRING": "$(PCS_AZUREBLOB_CONNSTRING)",
"PCS_ACTION_EVENTHUB_CONNSTRING": "$(PCS_ACTION_EVENTHUB_CONNSTRING)",
"PCS_ACTION_EVENTHUB_NAME": "$(PCS_ACTION_EVENTHUB_NAME)",
"PCS_LOGICAPP_ENDPOINT_URL": "$(PCS_LOGICAPP_ENDPOINT_URL)",
"PCS_SOLUTION_WEBSITE_URL": "$(PCS_SOLUTION_WEBSITE_URL)"
"PCS_AAD_APPSECRET": "$(PCS_AAD_APPSECRET)"
},
"applicationUrl": "http://localhost:9004/v1/status"
}

Просмотреть файл

@ -23,65 +23,61 @@ namespace Microsoft.Azure.IoTSolutions.DeviceTelemetry.WebService.Runtime
public class Config : IConfig
{
private const string APPLICATION_KEY = "TelemetryService:";
private const string PORT_KEY = APPLICATION_KEY + "webservice_port";
private const string PORT_KEY = APPLICATION_KEY + "webservicePort";
private const string COSMOSDB_KEY = "TelemetryService:CosmosDb:";
private const string COSMOSDB_CONNSTRING_KEY = COSMOSDB_KEY + "connstring";
private const string COSMOSDB_CONNSTRING_KEY = COSMOSDB_KEY + "documentDBConnectionString";
private const string COSMOSDB_RUS_KEY = COSMOSDB_KEY + "RUs";
private const string TIME_SERIES_KEY = APPLICATION_KEY + "TimeSeries:";
private const string TIME_SERIES_FQDN = TIME_SERIES_KEY + "fqdn";
private const string TIME_SERIES_FQDN = TIME_SERIES_KEY + "tsiDataAccessFQDN";
private const string TIME_SERIES_AUTHORITY = TIME_SERIES_KEY + "authority";
private const string TIME_SERIES_AUDIENCE = TIME_SERIES_KEY + "audience";
private const string TIME_SERIES_EXPLORER_URL = TIME_SERIES_KEY + "explorer_url";
private const string TIME_SERIES_API_VERSION = TIME_SERIES_KEY + "api_version";
private const string TIME_SERIES_EXPLORER_URL = TIME_SERIES_KEY + "explorerUrl";
private const string TIME_SERIES_API_VERSION = TIME_SERIES_KEY + "apiVersion";
private const string TIME_SERIES_TIMEOUT = TIME_SERIES_KEY + "timeout";
private const string AAD_KEY = APPLICATION_KEY + "AzureActiveDirectory:";
private const string AAD_TENANT = AAD_KEY + "tenant";
private const string AAD_APP_ID = AAD_KEY + "app_id";
private const string AAD_APP_SECRET = AAD_KEY + "app_secret";
private const string AAD_TENANT = AAD_KEY + "aadTenantId";
private const string AAD_APP_ID = AAD_KEY + "aadAppId";
private const string AAD_APP_SECRET = AAD_KEY + "aadAppSecret";
private const string MESSAGES_DB_KEY = "TelemetryService:Messages:";
private const string MESSAGES_DB_DATABASE_KEY = MESSAGES_DB_KEY + "database";
private const string MESSAGES_DB_COLLECTION_KEY = MESSAGES_DB_KEY + "collection";
private const string MESSAGES_STORAGE_TYPE = MESSAGES_DB_KEY + "storage_type";
private const string MESSAGES_STORAGE_TYPE = MESSAGES_DB_KEY + "telemetryStorageType";
private const string ALARMS_DB_KEY = "TelemetryService:Alarms:";
private const string ALARMS_DB_DATABASE_KEY = ALARMS_DB_KEY + "database";
private const string ALARMS_DB_COLLECTION_KEY = ALARMS_DB_KEY + "collection";
private const string ALARMS_DB_MAX_DELETE_RETRIES = ALARMS_DB_KEY + "max_delete_retries";
private const string ALARMS_DB_MAX_DELETE_RETRIES = ALARMS_DB_KEY + "maxDeleteRetries";
private const string STORAGE_ADAPTER_KEY = "StorageAdapterService:";
private const string STORAGE_ADAPTER_API_URL_KEY = STORAGE_ADAPTER_KEY + "webservice_url";
private const string STORAGE_ADAPTER_API_TIMEOUT_KEY = STORAGE_ADAPTER_KEY + "webservice_timeout";
private const string USER_MANAGEMENT_KEY = "UserManagementService:";
private const string USER_MANAGEMENT_URL_KEY = USER_MANAGEMENT_KEY + "webservice_url";
private const string DIAGNOSTICS_KEY = "DiagnosticsService:";
private const string DIAGNOSTICS_URL_KEY = DIAGNOSTICS_KEY + "webservice_url";
private const string DIAGNOSTICS_MAX_LOG_RETRIES = DIAGNOSTICS_KEY + "max_log_retries";
private const string EXT_DEPENDENCIES_KEY = "ExternalDependencies:";
private const string STORAGE_ADAPTER_API_URL_KEY = EXT_DEPENDENCIES_KEY + "storageAdapterWebServiceUrl";
private const string STORAGE_ADAPTER_API_TIMEOUT_KEY = EXT_DEPENDENCIES_KEY + "storageAdapterWebserviceTimeout";
private const string USER_MANAGEMENT_URL_KEY = EXT_DEPENDENCIES_KEY + "authWebServiceUrl";
private const string DIAGNOSTICS_URL_KEY = EXT_DEPENDENCIES_KEY + "diagnosticsWebServiceUrl";
private const string DIAGNOSTICS_MAX_LOG_RETRIES = EXT_DEPENDENCIES_KEY + "diagnosticsMaxLogRetries";
private const string CLIENT_AUTH_KEY = APPLICATION_KEY + "ClientAuth:";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "cors_whitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "auth_type";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "auth_required";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "corsWhitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "authType";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "authRequired";
private const string JWT_KEY = APPLICATION_KEY + "ClientAuth:JWT:";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowed_algorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "issuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "audience";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clock_skew_seconds";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowedAlgorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "authIssuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "aadAppId";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clockSkewSeconds";
private const string ACTIONS_KEY = "Actions:";
private const string ACTIONS_EVENTHUB_NAME = ACTIONS_KEY + "event_hub_name";
private const string ACTIONS_EVENTHUB_CONNSTRING = ACTIONS_KEY + "event_hub_connection_string";
private const string ACTIONS_LOGICAPP_ENDPOINTURL = ACTIONS_KEY + "logic_app_endpoint_url";
private const string ACTIONS_AZUREBLOB_CONNSTRING = ACTIONS_KEY + "blob_storage_connection_string";
private const string ACTIONS_AZUREBLOB_CONTAINER = ACTIONS_KEY + "blob_storage_container";
private const string SOLUTION_URL = ACTIONS_KEY + "solution_url";
private const string TEMPLATE_FOLDER = ACTIONS_KEY + "template_folder";
private const string ACTIONS_EVENTHUB_NAME = ACTIONS_KEY + "actionsEventHubName";
private const string ACTIONS_EVENTHUB_CONNSTRING = ACTIONS_KEY + "actionsEventHubConnectionString";
private const string ACTIONS_LOGICAPP_ENDPOINTURL = ACTIONS_KEY + "logicAppEndpointUrl";
private const string ACTIONS_AZUREBLOB_CONNSTRING = ACTIONS_KEY + "storageConnectionString";
private const string ACTIONS_AZUREBLOB_CONTAINER = ACTIONS_KEY + "storageContainer";
private const string SOLUTION_URL = ACTIONS_KEY + "solutionWebsiteUrl";
private const string TEMPLATE_FOLDER = ACTIONS_KEY + "templateFolder";
public int Port { get; }
public IServicesConfig ServicesConfig { get; }

Просмотреть файл

@ -1,88 +1,81 @@
[TelemetryService]
webservice_port = 9004
webservicePort = 9004
; Note: in linux containers, the `data` folder is a symlink to /app/data
; which can be mounted to inject custom rules
rules_templates_folder = ./data/Rules/
rulesTemplatesFolder = ./data/Rules/
[TelemetryService:CosmosDb]
connstring = "${PCS_TELEMETRY_DOCUMENTDB_CONNSTRING}"
documentDBConnectionString = ""
; TODO: move to [messages] and [alarms] which could have different size requirements
; https://github.com/Azure/remote-monitoring-services-dotnet/issues/114
RUs = 400
[TelemetryService:TimeSeries]
fqdn = "${?PCS_TSI_FQDN}"
tsiDataAccessFQDN = ""
authority = "https://login.windows.net/"
audience = "https://api.timeseries.azure.com/"
explorer_url = "https://insights.timeseries.azure.com/"
api_version = "2016-12-12"
explorerUrl = "https://insights.timeseries.azure.com/"
apiVersion = "2016-12-12"
; Timeout value should be in ISO 8601 duration format,
; for example "PT20S" and should be in the range 1-30s.
timeout = "PT20S"
[TelemetryService:AzureActiveDirectory]
tenant = "${?PCS_AAD_TENANT}"
app_id = "${?PCS_AAD_APPID}"
app_secret = "${?PCS_AAD_APPSECRET}"
aadTenantId = ""
aadAppId = ""
aadAppSecret = ""
[TelemetryService:Messages]
database = "pcs-iothub-stream"
collection = "messages"
; Supported values (not case sensitive): "cosmosdb", "tsi"
storage_type = "${PCS_TELEMETRY_STORAGE_TYPE}"
telemetryStorageType = ""
[TelemetryService:Alarms]
database = "pcs-iothub-stream"
collection = "alarms"
max_delete_retries = 3
maxDeleteRetries = 3
; Supported values (not case sensitive): "cosmosdb"
storage_type = "cosmosdb"
[StorageAdapterService]
webservice_url = "${PCS_STORAGEADAPTER_WEBSERVICE_URL}"
webservice_timeout = 10000
[UserManagementService]
webservice_url = "${PCS_AUTH_WEBSERVICE_URL}"
[DiagnosticsService]
webservice_url = "${?PCS_DIAGNOSTICS_WEBSERVICE_URL}"
max_log_retries = 3
[ExternalDependencies]
storageAdapterWebServiceUrl = ""
storageAdapterWebserviceTimeout = 10000
authWebServiceUrl = ""
diagnosticsWebServiceUrl = ""
diagnosticsMaxLogRetries = 3
[Actions]
event_hub_name = "${PCS_ACTION_EVENTHUB_NAME}"
event_hub_connection_string = "${PCS_ACTION_EVENTHUB_CONNSTRING}"
logic_app_endpoint_url = "${PCS_LOGICAPP_ENDPOINT_URL}"
blob_storage_connection_string = "${PCS_AZUREBLOB_CONNSTRING}"
blob_storage_container = "actions-eventhub-container"
solution_url = "${PCS_SOLUTION_WEBSITE_URL}"
template_folder = ./data/
actionsEventHubName = ""
actionsEventHubConnectionString = ""
logicAppEndpointUrl = ""
storageConnectionString = ""
storageContainer = "actions-eventhub-container"
solutionWebsiteUrl = ""
templateFolder = ./data/
[TelemetryService:ClientAuth]
;; Current auth type, only "JWT" is currently supported.
auth_type="JWT"
authType="JWT"
;; This can be changed to false, for example during development,
;; to allow invalid/missing authorizations.
;; Default: true
auth_required="${?PCS_AUTH_REQUIRED}"
authRequired=""
;; Can be used when running services on multiple hostnames and/or ports
;; e.g. "{ 'origins': ['*'], 'methods': ['*'], 'headers': ['*'] }" to allow everything.
;; Comment it or leave it empty to disable CORS.
;; Default: empty
cors_whitelist = "${?PCS_CORS_WHITELIST}"
corsWhitelist = ""
[TelemetryService:ClientAuth:JWT]
; Trusted algorithms
; Default: RS256, RS384, RS512
allowed_algorithms="RS256"
allowedAlgorithms="RS256"
; Identifies the security token service (STS) that constructs and returns the token.
; In the tokens that Azure AD returns, the issuer is sts.windows.net. The GUID in
; the Issuer claim value is the tenant ID of the Azure AD directory. The tenant ID
@ -91,15 +84,19 @@ allowed_algorithms="RS256"
; When using Azure Active Directory, the format of the Issuer is:
; https://sts.windows.net/<tenant Id>/
; example: issuer="https://sts.windows.net/fa01ade2-2365-4dd1-a084-a6ef027090fc/"
issuer="${?PCS_AUTH_ISSUER}"
authIssuer=""
; Used to verify that tokens are issued to be given to this service
; Also referenced as "Application Id" and "Resource Id"
; example: audience="2814e709-6a0e-4861-9594-d3b6e2b81331"
audience="${?PCS_AUTH_AUDIENCE}"
aadAppId=""
; When validating the token expiration, allows some clock skew
; Default: 2 minutes
clock_skew_seconds = 300
clockSkewSeconds = 300
[KeyVault]
aadAppId = ${PCS_AAD_APPID}
aadAppSecret = ${PCS_AAD_APPSECRET}
name = ${PCS_KEYVAULT_NAME}
; For more information about ASP.NET logging see
; https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging

Просмотреть файл

@ -16,25 +16,9 @@ run_container() {
echo "Starting Telemetry service..."
docker run -it -p 9004:9004 \
-e PCS_AUTH_WEBSERVICE_URL \
-e PCS_STORAGEADAPTER_WEBSERVICE_URL \
-e PCS_DIAGNOSTICS_WEBSERVICE_URL \
-e PCS_TELEMETRY_DOCUMENTDB_CONNSTRING \
-e PCS_AUTH_ISSUER \
-e PCS_AUTH_AUDIENCE \
-e PCS_AUTH_REQUIRED \
-e PCS_CORS_WHITELIST \
-e PCS_APPLICATION_SECRET \
-e PCS_AAD_TENANT \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
-e PCS_TELEMETRY_STORAGE_TYPE \
-e PCS_TSI_FQDN \
-e PCS_AZUREBLOB_CONNSTRING \
-e PCS_ACTION_EVENTHUB_CONNSTRING \
-e PCS_ACTION_EVENTHUB_NAME \
-e PCS_LOGICAPP_ENDPOINT_URL \
-e PCS_SOLUTION_WEBSITE_URL \
"$DOCKER_IMAGE:testing"
}

Просмотреть файл

@ -21,25 +21,9 @@ IF %ERRORLEVEL% NEQ 0 GOTO FAIL
:: Start the application
echo Starting Telemetry service...
docker run -it -p 9004:9004 ^
-e PCS_AUTH_WEBSERVICE_URL ^
-e PCS_STORAGEADAPTER_WEBSERVICE_URL ^
-e PCS_DIAGNOSTICS_WEBSERVICE_URL ^
-e PCS_TELEMETRY_DOCUMENTDB_CONNSTRING ^
-e PCS_AUTH_ISSUER ^
-e PCS_AUTH_AUDIENCE ^
-e PCS_AUTH_REQUIRED ^
-e PCS_CORS_WHITELIST ^
-e PCS_APPLICATION_SECRET ^
-e PCS_AAD_TENANT ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
-e PCS_TELEMETRY_STORAGE_TYPE ^
-e PCS_TSI_FQDN ^
-e PCS_AZUREBLOB_CONNSTRING ^
-e PCS_ACTION_EVENTHUB_CONNSTRING ^
-e PCS_ACTION_EVENTHUB_NAME ^
-e PCS_LOGICAPP_ENDPOINT_URL ^
-e PCS_SOLUTION_WEBSITE_URL ^
%DOCKER_IMAGE%:testing
:: - - - - - - - - - - - - - -

Просмотреть файл

@ -1,97 +1,17 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Some settings are used to connect to an external dependency, e.g. Azure IoT Hub and IoT Hub Manager API
# Depending on which settings and which dependencies are needed, edit the list of variables checked
# Before checking all the env vars, detect whether secrets, usually encrypted, are available or not.
# Secrets are not available when building a pull request, so the script will not check for those.
detect_secrets() {
SECRETS_AVAILABLE="true"
if [[ "$TRAVIS_PULL_REQUEST" != "" && "$TRAVIS_PULL_REQUEST" != "false" ]]; then
SECRETS_AVAILABLE="false"
echo "Warning: secrets and encrypted variables are not available when testing pull requests."
fi
}
detect_secrets
if [[ -z "$PCS_TELEMETRY_DOCUMENTDB_CONNSTRING" && "$SECRETS_AVAILABLE" = "true" ]]; then
echo "Error: the PCS_TELEMETRY_DOCUMENTDB_CONNSTRING environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_STORAGEADAPTER_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_STORAGEADAPTER_WEBSERVICE_URL environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_AUTH_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_AUTH_WEBSERVICE_URL environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_AUTH_ISSUER" ]]; then
echo "Error: the PCS_AUTH_ISSUER environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_AUTH_AUDIENCE" ]]; then
echo "Error: the PCS_AUTH_AUDIENCE environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_TELEMETRY_STORAGE_TYPE" ]]; then
echo "Error: the PCS_TELEMETRY_STORAGE_TYPE environment variable is not defined."
exit -1
fi
# The settings below are for Time Series Insights. If your deployment does not use
# Time Series Insights they are safe to remove.
if [[ -z "$PCS_AAD_TENANT" ]]; then
echo "Error: the PCS_AAD_TENANT environment variable is not defined."
exit -1
if [[ -z "$PCS_KEYVAULT_NAME" ]]; then
echo "Error: the PCS_KEYVAULT_NAME environment variable is not defined."
exit 1
fi
if [[ -z "$PCS_AAD_APPID" ]]; then
echo "Error: the PCS_AAD_APPID environment variable is not defined."
exit -1
exit 1
fi
if [[ -z "$PCS_AAD_APPSECRET" ]]; then
echo "Error: the PCS_AAD_APPSECRET environment variable is not defined."
exit -1
exit 1
fi
if [[ -z "$PCS_TSI_FQDN" ]]; then
echo "Error: the PCS_TSI_FQDN environment variable is not defined."
exit -1
fi
# Settings for actions
if [[ -z "$PCS_ACTION_EVENTHUB_NAME" ]]; then
echo "Error: the PCS_ACTION_EVENTHUB_NAME environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_ACTION_EVENTHUB_CONNSTRING" ]]; then
echo "Error: the PCS_ACTION_EVENTHUB_CONNSTRING environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_LOGICAPP_ENDPOINT_URL" ]]; then
echo "Error: the PCS_LOGICAPP_ENDPOINT_URL environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_AZUREBLOB_CONNSTRING" ]]; then
echo "Error: the PCS_AZUREBLOB_CONNSTRING environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_SOLUTION_WEBSITE_URL" ]]; then
echo "Error: the PCS_SOLUTION_WEBSITE_URL environment variable is not defined."
exit -1
fi

Просмотреть файл

@ -2,44 +2,8 @@
@ECHO off & setlocal enableextensions enabledelayedexpansion
:: Some settings are used to connect to an external dependency, e.g. Azure IoT Hub and IoT Hub Manager API
:: Depending on which settings and which dependencies are needed, edit the list of variables checked
IF "%PCS_TELEMETRY_DOCUMENTDB_CONNSTRING%" == "" (
echo Error: the PCS_TELEMETRY_DOCUMENTDB_CONNSTRING environment variable is not defined.
exit /B 1
)
IF "%PCS_STORAGEADAPTER_WEBSERVICE_URL%" == "" (
echo Error: the PCS_STORAGEADAPTER_WEBSERVICE_URL environment variable is not defined.
exit /B 1
)
IF "%PCS_AUTH_WEBSERVICE_URL%" == "" (
echo Error: the PCS_AUTH_WEBSERVICE_URL environment variable is not defined.
exit /B 1
)
IF "%PCS_AUTH_ISSUER%" == "" (
echo Error: the PCS_AUTH_ISSUER environment variable is not defined.
exit /B 1
)
IF "%PCS_AUTH_AUDIENCE%" == "" (
echo Error: the PCS_AUTH_AUDIENCE environment variable is not defined.
exit /B 1
)
IF "%PCS_TELEMETRY_STORAGE_TYPE%" == "" (
echo Error: the PCS_TELEMETRY_STORAGE_TYPE environment variable is not defined.
exit /B 1
)
:: The settings below are for Time Series Insights. If your deployment does not use
:: Time Series Insights they are safe to remove.
IF "%PCS_AAD_TENANT%" == "" (
echo Error: the PCS_AAD_TENANT environment variable is not defined.
IF "%PCS_KEYVAULT_NAME%" == "" (
echo Error: the PCS_KEYVAULT_NAME environment variable is not defined.
exit /B 1
)
@ -53,36 +17,4 @@ IF "%PCS_AAD_APPSECRET%" == "" (
exit /B 1
)
IF "%PCS_TSI_FQDN%" == "" (
echo Error: the PCS_TSI_FQDN environment variable is not defined.
exit /B 1
)
:: Settings for actions
IF "%PCS_ACTION_EVENTHUB_NAME%" == "" (
echo Error: the PCS_ACTION_EVENTHUB_NAME environment variable is not defined.
exit /B 1
)
IF "%PCS_ACTION_EVENTHUB_CONNSTRING%" == "" (
echo Error: the PCS_ACTION_EVENTHUB_CONNSTRING environment variable is not defined.
exit /B 1
)
IF "%PCS_LOGICAPP_ENDPOINT_URL%" == "" (
echo Error: the PCS_LOGICAPP_ENDPOINT_URL environment variable is not defined.
exit /B 1
)
IF "%PCS_AZUREBLOB_CONNSTRING%" == "" (
echo Error: the PCS_AZUREBLOB_CONNSTRING environment variable is not defined.
exit /B 1
)
IF "%PCS_SOLUTION_WEBSITE_URL%" == "" (
echo Error: the PCS_SOLUTION_WEBSITE_URL environment variable is not defined.
exit /B 1
)
endlocal

Просмотреть файл

@ -1,66 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Usage: source ./scripts/env-vars-setup
#
# IMPORTANT NOTES:
# * use "source" in front of the script path, so that variables are exported in your shell
# * the variables are set only in the current shell, run this script every time, or automate
# the setup using your `~/.bash_profile`.
# Prepare the environment variables used by the application.
# Some settings are used to connect to an external dependency, e.g. Azure IoT Hub and IoT Hub Manager API
# Depending on which settings and which dependencies are needed, edit the list of variables
# see: Shared access policies => key name => Connection string
export PCS_TELEMETRY_DOCUMENTDB_CONNSTRING="..."
# The URL where IoT Hub Manager web service is listening
export PCS_STORAGEADAPTER_WEBSERVICE_URL="http://127.0.0.1:9022/v1"
# The URL where Authentication web service is listening
export PCS_AUTH_WEBSERVICE_URL="http://127.0.0.1:9001/v1"
# The OpenId tokens issuer URL, e.g. https://sts.windows.net/12000000-3400-5600-0000-780000000000/
export PCS_AUTH_ISSUER="{enter the token issuer URL here}"
# The intended audience of the tokens, e.g. your Client Id
export PCS_AUTH_AUDIENCE="{enter the tokens audience here}"
# The tenant for the Azure Active Directory application
# see: Azure Portal => Azure Active Directory => Properties => Directory ID
export PCS_AAD_TENANT="{enter the Azure Active Directory Tenant for the application here}"
# The Application ID registered with Azure Active Directory
# see: Azure Portal => Azure Active Directory => App Registrations => Your App => Application ID
export PCS_AAD_APPID="{enter Azure Active Directory application ID here}"
# The Application Secret for your Azure Active Directory Application
# see: Azure Portal => Azure Active Directory => App Registrations => Your App => Settings => Passwords
export PCS_AAD_APPSECRET="{enter your application secret here}"
# The storage type for telemetry messages. Default is "tsi". Allowed values: ["cosmosdb", "tsi"]
export PCS_TELEMETRY_STORAGE_TYPE="tsi"
# The FQDN (Fully Qualified Domain Name) for the Time Series endpoint
# see: Azure Portal => Your Resource Group => Time Series Insights Environment => Data Access FQDN
export PCS_TSI_FQDN="{enter your Time Series FQDN here}"
# The name of the event hub that alarms with actions are written to
export PCS_ACTION_EVENTHUB_NAME="{Enter event hub name here}"
# The connection string of the event hub namespace that alarms with actions are written to
# see: Azure Portal => Your resource group => your event hub namespace => Shared access policies
export PCS_ACTION_EVENTHUB_CONNSTRING="{Endpoint=sb://....servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=...}"
# Endpoint of logic app workflow.
# See Azure Portal => Your resource group => Your Logic App => Logic App Designer => When a Http Request is received => HTTP POST URL
export PCS_LOGICAPP_ENDPOINT_URL="{Enter endpoint here}"
# Azure Blob Storage Connection String
# See Azure Portal => Your resource group => Your Storage Account => Access keys => Connection String
export PCS_AZUREBLOB_CONNSTRING="{Enter connection string here}"
# Url of your solution
export PCS_SOLUTION_WEBSITE_URL="{Enter solution url}"

Просмотреть файл

@ -1,58 +0,0 @@
:: Copyright (c) Microsoft. All rights reserved.
:: Prepare the environment variables used by the application.
:: Some settings are used to connect to an external dependency, e.g. Azure IoT Hub and IoT Hub Manager API
:: Depending on which settings and which dependencies are needed, edit the list of variables
:: see: Shared access policies => key name => Connection string
SETX PCS_TELEMETRY_DOCUMENTDB_CONNSTRING "..."
:: The URL where IoT Hub Manager web service is listening
SETX PCS_STORAGEADAPTER_WEBSERVICE_URL "http://127.0.0.1:9022/v1"
:: Endpoint to reach the authentication service
SETX PCS_AUTH_WEBSERVICE_URL "http://127.0.0.1:9001/v1"
:: The OpenId tokens issuer URL, e.g. https://sts.windows.net/12000000-3400-5600-0000-780000000000/
SETX PCS_AUTH_ISSUER "{enter the token issuer URL here}"
:: The intended audience of the tokens, e.g. your Client Id
SETX PCS_AUTH_AUDIENCE "{enter the tokens audience here}"
:: The tenant for the Azure Active Directory application
:: see: Azure Portal => Azure Active Directory => Properties => Directory ID
SETX PCS_AAD_TENANT="{enter the Azure Active Directory Tenant for the application here}"
:: The Application ID registered with Azure Active Directory
:: see: Azure Portal => Azure Active Directory => App Registrations => Your App => Application ID
SETX PCS_AAD_APPID="{enter Azure Active Directory application ID here}"
:: The Application Secret for your Azure Active Directory Application
:: see: Azure Portal => Azure Active Directory => App Registrations => Your App => Settings => Passwords
SETX PCS_AAD_APPSECRET="{enter your application secret here}"
:: The storage type for telemetry messages. Default is "tsi". Allowed values: ["cosmosdb", "tsi"]
SETX PCS_TELEMETRY_STORAGE_TYPE="tsi"
:: The FQDN (Fully Qualified Domain Name) for the Time Series endpoint
:: see: Azure Portal => Your Resource Group => Time Series Insights Environment => Data Access FQDN
SETX PCS_TSI_FQDN="{enter your Time Series FQDN here}"
:: The name of the event hub that alarms with actions are written to
SETX PCS_ACTION_EVENTHUB_NAME "{Enter event hub name here}"
:: The connection string of the event hub namespace that alarms with actions are written to
:: see: Azure Portal => Your resource group => your event hub namespace => Shared access policies
SETX PCS_ACTION_EVENTHUB_CONNSTRING "{Endpoint=sb://....servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=...}"
:: Endpoint of logic app workflow.
:: See Azure Portal => Your resource group => Your Logic App => Logic App Designer => When a Http Request is received => HTTP POST URL
SETX PCS_LOGICAPP_ENDPOINT_URL "{Enter endpoint here}"
:: Azure Blob Storage Connection String
:: See Azure Portal => Your resource group => Your Storage Account => Access keys => Connection String
SETX PCS_AZUREBLOB_CONNSTRING "{Enter connection string here}"
:: Url of your solution
SETX PCS_SOLUTION_WEBSITE_URL "{Enter solution url}"

Просмотреть файл

@ -70,21 +70,9 @@ run_in_sandbox() {
# edit the list of variables.
docker run -it \
-p 9004:9004 \
-e PCS_TELEMETRY_DOCUMENTDB_CONNSTRING \
-e PCS_STORAGEADAPTER_WEBSERVICE_URL \
-e PCS_AUTH_WEBSERVICE_URL \
-e PCS_AUTH_ISSUER \
-e PCS_AUTH_AUDIENCE \
-e PCS_AAD_TENANT \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
-e PCS_TELEMETRY_STORAGE_TYPE \
-e PCS_TSI_FQDN \
-e PCS_AZUREBLOB_CONNSTRING \
-e PCS_ACTION_EVENTHUB_CONNSTRING \
-e PCS_ACTION_EVENTHUB_NAME \
-e PCS_LOGICAPP_ENDPOINT_URL \
-e PCS_SOLUTION_WEBSITE_URL \
-v "$PCS_CACHE/sandbox/.config:/root/.config" \
-v "$PCS_CACHE/sandbox/.dotnet:/root/.dotnet" \
-v "$PCS_CACHE/sandbox/.nuget:/root/.nuget" \

Просмотреть файл

@ -63,21 +63,9 @@ IF "%1"=="--in-sandbox" GOTO :RunInSandbox
:: Start the sandbox and run the service
docker run -it ^
-p 9004:9004 ^
-e "PCS_TELEMETRY_DOCUMENTDB_CONNSTRING=%PCS_TELEMETRY_DOCUMENTDB_CONNSTRING%" ^
-e "PCS_STORAGEADAPTER_WEBSERVICE_URL=%PCS_STORAGEADAPTER_WEBSERVICE_URL%" ^
-e PCS_AUTH_WEBSERVICE_URL ^
-e "PCS_AUTH_ISSUER=%PCS_AUTH_ISSUER%" ^
-e "PCS_AUTH_AUDIENCE=%PCS_AUTH_AUDIENCE%" ^
-e "PCS_AAD_TENANT" ^
-e "PCS_AAD_APPID" ^
-e "PCS_AAD_APPSECRET" ^
-e "PCS_TELEMETRY_STORAGE_TYPE" ^
-e "PCS_TSI_FQDN" ^
-e "PCS_AZUREBLOB_CONNSTRING" ^
-e "PCS_ACTION_EVENTHUB_CONNSTRING" ^
-e "PCS_ACTION_EVENTHUB_NAME" ^
-e "PCS_LOGICAPP_ENDPOINT_URL" ^
-e "PCS_SOLUTION_WEBSITE_URL" ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
-v %PCS_CACHE%\sandbox\.config:/root/.config ^
-v %PCS_CACHE%\sandbox\.dotnet:/root/.dotnet ^
-v %PCS_CACHE%\sandbox\.nuget:/root/.nuget ^

Просмотреть файл

@ -1,30 +0,0 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Note: Windows Bash doesn't support shebang extra params
set -e
# Example usage (see "travis help" for more information):
# travis help
# travis login --pro
# travis whoami --pro
# travis accounts --pro
# travis history
# travis monitor --pro
# travis settings
# travis show
# travis status
# travis token --pro
# travis whatsup --pro
set -e
APP_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )/"
cd $APP_HOME
mkdir -p .travis
docker run -it \
-v $APP_HOME/.travis:/root/.travis \
-v $APP_HOME:/opt/code \
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh $*
set +e

Просмотреть файл

@ -1,30 +0,0 @@
:: Copyright (c) Microsoft. All rights reserved.
@ECHO off & setlocal enableextensions enabledelayedexpansion
:: Example usage (see "travis help" for more information:
:: travis help
:: travis login --pro
:: travis whoami --pro
:: travis accounts --pro
:: travis history
:: travis monitor --pro
:: travis settings
:: travis show
:: travis status
:: travis token --pro
:: travis whatsup --pro
:: strlen("\scripts\") => 9
SET APP_HOME=%~dp0
SET APP_HOME=%APP_HOME:~0,-9%
cd %APP_HOME%
mkdir .travis 2>NUL
docker run -it ^
-v %APP_HOME%\.travis:/root/.travis ^
-v %APP_HOME%:/opt/code ^
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh %*
endlocal

Просмотреть файл

@ -23,28 +23,38 @@ namespace Microsoft.Azure.IoTSolutions.IotHubManager.Services.Runtime
private readonly IConfigurationRoot configuration;
private readonly ILogger log;
// Key Vault
private KeyVault keyVault;
// Constants
private const string CLIENT_ID = "KeyVault:aadAppId";
private const string CLIENT_SECRET = "KeyVault:aadAppSecret";
private const string KEY_VAULT_NAME = "KeyVault:name";
public ConfigData(ILogger logger)
{
this.log = logger;
// More info about configuration at
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddIniFile("appsettings.ini", optional: true, reloadOnChange: true);
this.configuration = configurationBuilder.Build();
// Set up Key Vault
this.SetUpKeyVault();
}
public string GetString(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
var value = this.GetSecrets(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
public bool GetBool(string key, bool defaultValue = false)
{
var value = this.GetString(key, defaultValue.ToString()).ToLowerInvariant();
var value = this.GetSecrets(key, defaultValue.ToString()).ToLowerInvariant();
var knownTrue = new HashSet<string> { "true", "t", "yes", "y", "1", "-1" };
var knownFalse = new HashSet<string> { "false", "f", "no", "n", "0" };
@ -59,7 +69,7 @@ namespace Microsoft.Azure.IoTSolutions.IotHubManager.Services.Runtime
{
try
{
return Convert.ToInt32(this.GetString(key, defaultValue.ToString()));
return Convert.ToInt32(this.GetSecrets(key, defaultValue.ToString()));
}
catch (Exception e)
{
@ -67,6 +77,49 @@ namespace Microsoft.Azure.IoTSolutions.IotHubManager.Services.Runtime
}
}
private void SetUpKeyVault()
{
var clientId = this.GetEnvironmentVariable(CLIENT_ID, string.Empty);
var clientSecret = this.GetEnvironmentVariable(CLIENT_SECRET, string.Empty);
var keyVaultName = this.GetEnvironmentVariable(KEY_VAULT_NAME, string.Empty);
// Initailize key vault
this.keyVault = new KeyVault(keyVaultName, clientId, clientSecret, this.log);
}
private string GetSecrets(string key, string defaultValue = "")
{
string value = string.Empty;
value = this.GetLocalVariable(key, defaultValue);
// If secrets are not found locally, search in Key-Vault
if (string.IsNullOrEmpty(value))
{
log.Warn($"Value for secret {key} not found in local env. " +
$" Trying to get the secret from KeyVault.", () => { });
value = this.keyVault.GetSecret(key);
}
return !string.IsNullOrEmpty(value) ? value : defaultValue;
}
private string GetSecretsFromKeyVault(string key) {
return this.keyVault.GetSecret(key);
}
private string GetLocalVariable(string key, string defaultValue = "")
{
return this.configuration.GetValue(key, defaultValue);
}
public string GetEnvironmentVariable(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
private void ReplaceEnvironmentVariables(ref string value, string defaultValue = "")
{
if (string.IsNullOrEmpty(value)) return;

Просмотреть файл

@ -0,0 +1,71 @@
using Microsoft.Azure.IoTSolutions.IotHubManager.Services.Diagnostics;
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.Azure.IoTSolutions.IotHubManager.Services.Runtime
{
public class KeyVault
{
// Key Vault details and access
private readonly string name;
private readonly string clientId;
private readonly string clientSecret;
private ILogger log;
// Key Vault Client
private readonly KeyVaultClient keyVaultClient;
// Constants
private const string KEY_VAULT_URI = "https://{0}.vault.azure.net/secrets/{1}";
public KeyVault(
string name,
string clientId,
string clientSecret,
ILogger logger)
{
this.name = name;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.log = logger;
this.keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(this.GetToken));
}
public string GetSecret(string secretKey)
{
secretKey = secretKey.Split(':').Last();
var uri = string.Format(KEY_VAULT_URI, this.name, secretKey);
try
{
return this.keyVaultClient.GetSecretAsync(uri).Result.Value;
}
catch (Exception)
{
this.log.Error($"Secret {secretKey} not found in Key Vault.", () => { });
return null;
}
}
//the method that will be provided to the KeyVaultClient
private async Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
ClientCredential clientCred = new ClientCredential(this.clientId, this.clientSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
{
this.log.Debug($"Failed to obtain authentication token from key vault.", () => { });
throw new System.InvalidOperationException("Failed to obtain the JWT token");
}
return result.AccessToken;
}
}
}

Просмотреть файл

@ -9,5 +9,7 @@
<PackageReference Include="Microsoft.Azure.Devices" Version="1.17.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="2.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="4.5.0" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.3" />
</ItemGroup>
</Project>

Просмотреть файл

@ -13,9 +13,9 @@
"launchBrowser": true,
"launchUrl": "http://localhost:9002/v1/status",
"environmentVariables": {
"PCS_AUTH_WEBSERVICE_URL": "http://localhost:9001/v1",
"PCS_IOTHUB_CONNSTRING": "$(PCS_IOTHUB_CONNSTRING)",
"PCS_STORAGEADAPTER_WEBSERVICE_URL": "http://localhost:9022/v1"
"PCS_KEYVAULT_NAME": "$(PCS_KEYVAULT_NAME)",
"PCS_AAD_APPID": "$(PCS_AAD_APPID)",
"PCS_AAD_APPSECRET": "$(PCS_AAD_APPSECRET)"
},
"applicationUrl": "http://localhost:9002/v1/status"
}

Просмотреть файл

@ -22,29 +22,27 @@ namespace Microsoft.Azure.IoTSolutions.IotHubManager.WebService.Runtime
public class Config : IConfig
{
private const string APPLICATION_KEY = "IothubManagerService:";
private const string PORT_KEY = APPLICATION_KEY + "webservice_port";
private const string IOTHUB_CONNSTRING_KEY = APPLICATION_KEY + "iothub_connstring";
private const string PORT_KEY = APPLICATION_KEY + "webservicePort";
private const string IOTHUB_CONNSTRING_KEY = APPLICATION_KEY + "iotHubConnectionString";
private const string DEVICE_PROPERTIES_KEY = APPLICATION_KEY + "DevicePropertiesCache:";
private const string DEVICE_PROPERTIES_WHITELIST_KEY = DEVICE_PROPERTIES_KEY + "whitelist";
private const string DEVICE_PROPERTIES_TTL_KEY = DEVICE_PROPERTIES_KEY + "TTL";
private const string DEVICE_PROPERTIES_REBUILD_TIMEOUT_KEY = DEVICE_PROPERTIES_KEY + "rebuild_timeout";
private const string DEVICE_PROPERTIES_REBUILD_TIMEOUT_KEY = DEVICE_PROPERTIES_KEY + "rebuildTimeout";
private const string STORAGE_ADAPTER_KEY = "StorageAdapterService:";
private const string STORAGE_ADAPTER_URL_KEY = STORAGE_ADAPTER_KEY + "webservice_url";
private const string USER_MANAGEMENT_KEY = "UserManagementService:";
private const string USER_MANAGEMENT_URL_KEY = USER_MANAGEMENT_KEY + "webservice_url";
private const string EXTERNAL_DEPENDENCIES = "ExternalDependencies:";
private const string STORAGE_ADAPTER_URL_KEY = EXTERNAL_DEPENDENCIES + "storageAdapterWebServiceUrl";
private const string USER_MANAGEMENT_URL_KEY = EXTERNAL_DEPENDENCIES + "authWebServiceUrl";
private const string CLIENT_AUTH_KEY = APPLICATION_KEY + "ClientAuth:";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "cors_whitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "auth_type";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "auth_required";
private const string CORS_WHITELIST_KEY = CLIENT_AUTH_KEY + "corsWhitelist";
private const string AUTH_TYPE_KEY = CLIENT_AUTH_KEY + "authType";
private const string AUTH_REQUIRED_KEY = CLIENT_AUTH_KEY + "authRequired";
private const string JWT_KEY = APPLICATION_KEY + "ClientAuth:JWT:";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowed_algorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "issuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "audience";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clock_skew_seconds";
private const string JWT_ALGOS_KEY = JWT_KEY + "allowedAlgorithms";
private const string JWT_ISSUER_KEY = JWT_KEY + "authIssuer";
private const string JWT_AUDIENCE_KEY = JWT_KEY + "aadAppId";
private const string JWT_CLOCK_SKEW_KEY = JWT_KEY + "clockSkewSeconds";
public int Port { get; }
public IServicesConfig ServicesConfig { get; }

Просмотреть файл

@ -1,6 +1,6 @@
[IothubManagerService]
webservice_port = 9002
iothub_connstring = "${PCS_IOTHUB_CONNSTRING}"
webservicePort = 9002
iotHubConnectionString = ""
[IothubManagerService:DevicePropertiesCache]
; This is the list of device properties that will be whiletlisted from the list of device properties received from CosmosDB
@ -8,32 +8,30 @@ whitelist = "tags.*, reported.Protocol, reported.SupportedMethods, reported.Devi
; Expiration time for device properties in seconds
TTL = 3600
; How long, in seconds, to timeout before trying to build device properties again
rebuild_timeout = 20
rebuildTimeout = 20
[StorageAdapterService]
webservice_url = "${PCS_STORAGEADAPTER_WEBSERVICE_URL}"
[UserManagementService]
webservice_url = "${PCS_AUTH_WEBSERVICE_URL}"
[ExternalDependencies]
storageAdapterWebServiceUrl = ""
authWebServiceUrl = ""
[IothubManagerService:ClientAuth]
;; Current auth type, only "JWT" is currently supported.
auth_type="JWT"
authType="JWT"
;; This can be changed to false, for example during development,
;; to allow invalid/missing authorizations.
;; Default: true
auth_required="${?PCS_AUTH_REQUIRED}"
authRequired=""
;; Can be used when running services on multiple hostnames and/or ports
;; e.g. "{ 'origins': ['*'], 'methods': ['*'], 'headers': ['*'] }" to allow everything.
;; Comment it or leave it empty to disable CORS.
;; Default: empty
cors_whitelist = "${?PCS_CORS_WHITELIST}"
corsWhitelist = ""
[IothubManagerService:ClientAuth:JWT]
; Trusted algorithms
; Default: RS256, RS384, RS512
allowed_algorithms="RS256"
allowedAlgorithms="RS256"
; Identifies the security token service (STS) that constructs and returns the token.
; In the tokens that Azure AD returns, the issuer is sts.windows.net. The GUID in
; the Issuer claim value is the tenant ID of the Azure AD directory. The tenant ID
@ -42,15 +40,19 @@ allowed_algorithms="RS256"
; When using Azure Active Directory, the format of the Issuer is:
; https://sts.windows.net/<tenant Id>/
; example: issuer="https://sts.windows.net/fa01ade2-2365-4dd1-a084-a6ef027090fc/"
issuer="${?PCS_AUTH_ISSUER}"
authIssuer=""
; Used to verify that tokens are issued to be given to this service
; Also referenced as "Application Id" and "Resource Id"
; example: audience="2814e709-6a0e-4861-9594-d3b6e2b81331"
audience="${?PCS_AUTH_AUDIENCE}"
aadAppId=""
; When validating the token expiration, allows some clock skew
; Default: 2 minutes
clock_skew_seconds = 300
clockSkewSeconds = 300
[KeyVault]
aadAppId = ${PCS_AAD_APPID}
aadAppSecret = ${PCS_AAD_APPSECRET}
name = ${PCS_KEYVAULT_NAME}
; For more information about ASP.NET logging see
; https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging
@ -58,7 +60,7 @@ clock_skew_seconds = 300
; internal logs generated by ASP.NET
; ASP.NET log levels: Trace, Debug, Information, Warning, Error, Critical
[Logging]
IncludeScopes = true
includeScopes = true
LogLevel:Default = "Warning"
LogLevel:System = "Warning"
LogLevel:Microsoft = "Warning"

Просмотреть файл

@ -13,11 +13,9 @@ run_container() {
echo "Starting IoT Hub Manager ..."
docker run -it -p 9002:9002 \
-e PCS_IOTHUB_CONNSTRING \
-e PCS_STORAGEADAPTER_WEBSERVICE_URL \
-e PCS_AUTH_WEBSERVICE_URL \
-e PCS_AUTH_ISSUER \
-e PCS_AUTH_AUDIENCE \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
"$DOCKER_IMAGE:testing"
}

Просмотреть файл

@ -19,11 +19,9 @@ IF %ERRORLEVEL% NEQ 0 GOTO FAIL
:: Start the application
echo Starting IoT Hub Manager ...
docker run -it -p 9002:9002 ^
-e PCS_IOTHUB_CONNSTRING ^
-e PCS_STORAGEADAPTER_WEBSERVICE_URL ^
-e PCS_AUTH_WEBSERVICE_URL ^
-e PCS_AUTH_ISSUER ^
-e PCS_AUTH_AUDIENCE ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
%DOCKER_IMAGE%:testing
:: - - - - - - - - - - - - - -

Просмотреть файл

@ -1,38 +1,17 @@
#!/usr/bin/env bash
# Copyright (c) Microsoft. All rights reserved.
# Before checking all the env vars, detect whether secrets, usually encrypted, are available or not.
# Secrets are not available when building a pull request, so the script will not check for those.
detect_secrets() {
SECRETS_AVAILABLE="true"
if [[ "$TRAVIS_PULL_REQUEST" != "" && "$TRAVIS_PULL_REQUEST" != "false" ]]; then
SECRETS_AVAILABLE="false"
echo "Warning: secrets and encrypted variables are not available when testing pull requests."
fi
}
detect_secrets
if [[ -z "$PCS_IOTHUB_CONNSTRING" && "$SECRETS_AVAILABLE" = "true" ]]; then
echo "Error: the PCS_IOTHUB_CONNSTRING environment variable is not defined."
exit -1
if [[ -z "$PCS_KEYVAULT_NAME" ]]; then
echo "Error: the PCS_KEYVAULT_NAME environment variable is not defined."
exit 1
fi
if [[ -z "$PCS_STORAGEADAPTER_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_STORAGEADAPTER_WEBSERVICE_URL environment variable is not defined."
exit -1
if [[ -z "$PCS_AAD_APPID" ]]; then
echo "Error: the PCS_AAD_APPID environment variable is not defined."
exit 1
fi
if [[ -z "$PCS_AUTH_WEBSERVICE_URL" ]]; then
echo "Error: the PCS_AUTH_WEBSERVICE_URL environment variable is not defined."
exit -1
if [[ -z "$PCS_AAD_APPSECRET" ]]; then
echo "Error: the PCS_AAD_APPSECRET environment variable is not defined."
exit 1
fi
if [[ -z "$PCS_AUTH_ISSUER" ]]; then
echo "Error: the PCS_AUTH_ISSUER environment variable is not defined."
exit -1
fi
if [[ -z "$PCS_AUTH_AUDIENCE" ]]; then
echo "Error: the PCS_AUTH_AUDIENCE environment variable is not defined."
exit -1
fi

Просмотреть файл

@ -1,28 +1,19 @@
@ECHO off
setlocal enableextensions enabledelayedexpansion
:: Copyright (c) Microsoft. All rights reserved.
IF "%PCS_IOTHUB_CONNSTRING%" == "" (
echo Error: the PCS_IOTHUB_CONNSTRING environment variable is not defined.
@ECHO off & setlocal enableextensions enabledelayedexpansion
IF "%PCS_KEYVAULT_NAME%" == "" (
echo Error: the PCS_KEYVAULT_NAME environment variable is not defined.
exit /B 1
)
IF "%PCS_STORAGEADAPTER_WEBSERVICE_URL%" == "" (
echo Error: the PCS_STORAGEADAPTER_WEBSERVICE_URL environment variable is not defined.
IF "%PCS_AAD_APPID%" == "" (
echo Error: the PCS_AAD_APPID environment variable is not defined.
exit /B 1
)
IF "%PCS_AUTH_WEBSERVICE_URL%" == "" (
echo Error: the PCS_AUTH_WEBSERVICE_URL environment variable is not defined.
exit /B 1
)
IF "%PCS_AUTH_ISSUER%" == "" (
echo Error: the PCS_AUTH_ISSUER environment variable is not defined.
exit /B 1
)
IF "%PCS_AUTH_AUDIENCE%" == "" (
echo Error: the PCS_AUTH_AUDIENCE environment variable is not defined.
IF "%PCS_AAD_APPSECRET%" == "" (
echo Error: the PCS_AAD_APPSECRET environment variable is not defined.
exit /B 1
)

Просмотреть файл

@ -1,24 +0,0 @@
#!/usr/bin/env bash
# Prepare the environment variables used by the application.
#
# For more information about finding IoT Hub settings, more information here:
#
# * https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-create-through-portal#endpoints
# * https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-csharp-csharp-getstarted
#
# see: Shared access policies => key name => Connection string
export PCS_IOTHUB_CONNSTRING="..."
# The URL where Storage Adapter web service is listening
export PCS_STORAGEADAPTER_WEBSERVICE_URL="http://127.0.0.1:9022/v1"
# The URL where Authentication web service is listening
export PCS_AUTH_WEBSERVICE_URL="http://127.0.0.1:9001/v1"
# The OpenId tokens issuer URL, e.g. https://sts.windows.net/12000000-3400-5600-0000-780000000000/
export PCS_AUTH_ISSUER="{enter the token issuer URL here}"
# The intended audience of the tokens, e.g. your Client Id
export PCS_AUTH_AUDIENCE="{enter the tokens audience here}"

Просмотреть файл

@ -1,22 +0,0 @@
:: Prepare the environment variables used by the application.
::
:: For more information about finding IoT Hub settings, more information here:
::
:: * https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-create-through-portal#endpoints
:: * https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-csharp-csharp-getstarted
::
:: see: Shared access policies => key name => Connection string
SETX PCS_IOTHUB_CONNSTRING "..."
:: Endpoint to reach the storage adapter
SETX PCS_STORAGEADAPTER_WEBSERVICE_URL "http://127.0.0.1:9022/v1"
:: Endpoint to reach the authentication service
SETX PCS_AUTH_WEBSERVICE_URL "http://127.0.0.1:9001/v1"
:: The OpenId tokens issuer URL, e.g. https://sts.windows.net/12000000-3400-5600-0000-780000000000/
SETX PCS_AUTH_ISSUER "{enter the token issuer URL here}"
:: The intended audience of the tokens, e.g. your Client Id
SETX PCS_AUTH_AUDIENCE "{enter the tokens audience here}"

Просмотреть файл

@ -64,11 +64,9 @@ run_in_sandbox() {
docker run -it \
-p 9002:9002 \
-e PCS_IOTHUB_CONNSTRING \
-e PCS_STORAGEADAPTER_WEBSERVICE_URL \
-e PCS_AUTH_WEBSERVICE_URL \
-e PCS_AUTH_ISSUER \
-e PCS_AUTH_AUDIENCE \
-e PCS_KEYVAULT_NAME \
-e PCS_AAD_APPID \
-e PCS_AAD_APPSECRET \
-v "$PCS_CACHE/sandbox/.config:/root/.config" \
-v "$PCS_CACHE/sandbox/.dotnet:/root/.dotnet" \
-v "$PCS_CACHE/sandbox/.nuget:/root/.nuget" \

Просмотреть файл

@ -61,11 +61,9 @@ IF "%1"=="--in-sandbox" GOTO :RunInSandbox
:: Start the sandbox and run the application
docker run -it ^
-p 9002:9002 ^
-e PCS_IOTHUB_CONNSTRING ^
-e PCS_STORAGEADAPTER_WEBSERVICE_URL ^
-e PCS_AUTH_WEBSERVICE_URL ^
-e PCS_AUTH_ISSUER ^
-e PCS_AUTH_AUDIENCE ^
-e PCS_KEYVAULT_NAME ^
-e PCS_AAD_APPID ^
-e PCS_AAD_APPSECRET ^
-v %PCS_CACHE%\sandbox\.config:/root/.config ^
-v %PCS_CACHE%\sandbox\.dotnet:/root/.dotnet ^
-v %PCS_CACHE%\sandbox\.nuget:/root/.nuget ^

Просмотреть файл

@ -1,27 +0,0 @@
#!/usr/bin/env bash
# Example usage (see "travis help" for more information):
# travis help
# travis login --pro
# travis whoami --pro
# travis accounts --pro
# travis history
# travis monitor --pro
# travis settings
# travis show
# travis status
# travis token --pro
# travis whatsup --pro
set -e
APP_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )/"
cd $APP_HOME
mkdir -p .travis
docker run -it \
-v $APP_HOME/.travis:/root/.travis \
-v $APP_HOME:/opt/code \
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh $*
set +e

Просмотреть файл

@ -1,28 +0,0 @@
@ECHO off & setlocal enableextensions enabledelayedexpansion
:: Example usage (see "travis help" for more information:
:: travis help
:: travis login --pro
:: travis whoami --pro
:: travis accounts --pro
:: travis history
:: travis monitor --pro
:: travis settings
:: travis show
:: travis status
:: travis token --pro
:: travis whatsup --pro
:: strlen("\scripts\") => 9
SET APP_HOME=%~dp0
SET APP_HOME=%APP_HOME:~0,-9%
cd %APP_HOME%
mkdir .travis 2>NUL
docker run -it ^
-v %APP_HOME%\.travis:/root/.travis ^
-v %APP_HOME%:/opt/code ^
azureiotpcs/travis-cli:1.8.8 /root/bin/travis.sh %*
endlocal

Просмотреть файл

@ -14,10 +14,10 @@ spec:
servicePort: 10080
tls:
- hosts:
- DNSGIVENNAME.REGION.cloudapp.azure.com
- DNSGIVENNAME.REGION.southeastasia.cloudapp.azure.com
secretName: tls-secret
rules:
- host: DNSGIVENNAME.REGION.cloudapp.azure.com
- host: DNSGIVENNAME.REGION.southeastasia.cloudapp.azure.com
http:
paths:
- path: /storageadapter/(.*)

Просмотреть файл

@ -46,15 +46,9 @@ services:
auth:
image: azureiotpcs/pcs-auth-dotnet:testing
environment:
- PCS_AUTH_ISSUER
- PCS_AUTH_AUDIENCE
- PCS_AUTH_REQUIRED
- PCS_AAD_ENDPOINT_URL
- PCS_AAD_TENANT
- PCS_KEYVAULT_NAME
- PCS_AAD_APPID
- PCS_AAD_APPSECRET
- PCS_ARM_ENDPOINT_URL
- PCS_CORS_WHITELIST
- PCS_APPLICATION_SECRET
iothubmanager:
image: azureiotpcs/iothub-manager-dotnet:testing
@ -62,27 +56,18 @@ services:
- auth
- storageadapter
environment:
- PCS_AUTH_WEBSERVICE_URL=http://auth:9001/v1
- PCS_IOTHUB_CONNSTRING
- PCS_STORAGEADAPTER_WEBSERVICE_URL=http://storageadapter:9022/v1
- PCS_AUTH_ISSUER
- PCS_AUTH_AUDIENCE
- PCS_AUTH_REQUIRED
- PCS_CORS_WHITELIST
- PCS_APPLICATION_SECRET
- PCS_KEYVAULT_NAME
- PCS_AAD_APPID
- PCS_AAD_APPSECRET
devicesimulation:
image: azureiotpcs/device-simulation-dotnet:DS-1.0.3
depends_on:
- storageadapter
environment:
- PCS_IOTHUB_CONNSTRING
- PCS_STORAGEADAPTER_WEBSERVICE_URL=http://storageadapter:9022/v1
- PCS_AUTH_ISSUER
- PCS_AUTH_AUDIENCE
- PCS_AUTH_REQUIRED
- PCS_CORS_WHITELIST
- PCS_APPLICATION_SECRET
- PCS_KEYVAULT_NAME
- PCS_AAD_APPID
- PCS_AAD_APPSECRET
# How one could mount custom device models
# NOTE: Volumes disabled for local development
# volumes:
@ -94,25 +79,9 @@ services:
- auth
- storageadapter
environment:
- PCS_STORAGEADAPTER_WEBSERVICE_URL=http://storageadapter:9022/v1
- PCS_AUTH_WEBSERVICE_URL=http://auth:9001/v1
- PCS_DIAGNOSTICS_WEBSERVICE_URL=http://diagnostics:9006/v1
- PCS_TELEMETRY_DOCUMENTDB_CONNSTRING
- PCS_AUTH_ISSUER
- PCS_AUTH_AUDIENCE
- PCS_AUTH_REQUIRED
- PCS_CORS_WHITELIST
- PCS_APPLICATION_SECRET
- PCS_AAD_TENANT
- PCS_KEYVAULT_NAME
- PCS_AAD_APPID
- PCS_AAD_APPSECRET
- PCS_TELEMETRY_STORAGE_TYPE
- PCS_TSI_FQDN
- PCS_AZUREBLOB_CONNSTRING
- PCS_ACTION_EVENTHUB_CONNSTRING
- PCS_ACTION_EVENTHUB_NAME
- PCS_LOGICAPP_ENDPOINT_URL
- PCS_SOLUTION_WEBSITE_URL
config:
image: azureiotpcs/pcs-config-dotnet:testing
@ -122,32 +91,16 @@ services:
- devicesimulation
- telemetry
environment:
- PCS_AUTH_WEBSERVICE_URL=http://auth:9001/v1
- PCS_STORAGEADAPTER_WEBSERVICE_URL=http://storageadapter:9022/v1
- PCS_DEVICESIMULATION_WEBSERVICE_URL=http://devicesimulation:9003/v1
- PCS_TELEMETRY_WEBSERVICE_URL=http://telemetry:9004/v1
- PCS_SOLUTION_TYPE
- PCS_AZUREMAPS_KEY
- PCS_AUTH_ISSUER
- PCS_AUTH_AUDIENCE
- PCS_AUTH_REQUIRED
- PCS_CORS_WHITELIST
- PCS_APPLICATION_SECRET
- PCS_SEED_TEMPLATE
- PCS_OFFICE365_CONNECTION_URL
- PCS_SOLUTION_NAME
- PCS_SUBSCRIPTION_ID
- PCS_ARM_ENDPOINT_URL
- PCS_KEYVAULT_NAME
- PCS_AAD_APPID
- PCS_AAD_APPSECRET
storageadapter:
image: azureiotpcs/pcs-storage-adapter-dotnet:testing
environment:
- PCS_STORAGEADAPTER_DOCUMENTDB_CONNSTRING
- PCS_AUTH_ISSUER
- PCS_AUTH_AUDIENCE
- PCS_AUTH_REQUIRED
- PCS_CORS_WHITELIST
- PCS_APPLICATION_SECRET
- PCS_KEYVAULT_NAME
- PCS_AAD_APPID
- PCS_AAD_APPSECRET
asamanager:
image: azureiotpcs/asa-manager-dotnet:testing
@ -156,37 +109,15 @@ services:
- iothubmanager
- config
environment:
- PCS_TELEMETRY_DOCUMENTDB_CONNSTRING
- PCS_TELEMETRY_WEBSERVICE_URL=http://telemetry:9004/v1
- PCS_CONFIG_WEBSERVICE_URL=http://config:9005/v1
- PCS_IOTHUBMANAGER_WEBSERVICE_URL=http://iothubmanager:9002/v1
- PCS_ASA_DATA_AZUREBLOB_ACCOUNT
- PCS_ASA_DATA_AZUREBLOB_KEY
- PCS_ASA_DATA_AZUREBLOB_ENDPOINT_SUFFIX
- PCS_EVENTHUB_CONNSTRING
- PCS_EVENTHUB_NAME
- PCS_AUTH_REQUIRED
- PCS_CORS_WHITELIST
- PCS_AUTH_ISSUER
- PCS_AUTH_AUDIENCE
- PCS_APPLICATION_SECRET
- PCS_TELEMETRY_STORAGE_TYPE
- PCS_KEYVAULT_NAME
- PCS_AAD_APPID
- PCS_AAD_APPSECRET
diagnostics:
image: azureiotpcs/pcs-diagnostics-dotnet:testing
depends_on:
- config
environment:
- PCS_LOG_LEVEL
- PCS_AUTH_ISSUER
- PCS_AUTH_AUDIENCE
- PCS_AUTH_REQUIRED
- PCS_CORS_WHITELIST
- PCS_CLOUD_TYPE
- PCS_SUBSCRIPTION_ID
- PCS_SOLUTION_TYPE
- PCS_SOLUTION_NAME
- PCS_DEPLOYMENT_ID
- PCS_IOTHUB_NAME
- PCS_DIAGNOSTICS_ENDPOINT_URL
- PCS_CONFIG_WEBSERVICE_URL=http://config:9005/v1
- PCS_KEYVAULT_NAME
- PCS_AAD_APPID
- PCS_AAD_APPSECRET

Просмотреть файл

@ -0,0 +1,197 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Azure.IoTSolutions.StorageAdapter.Services.Diagnostics;
using Microsoft.Azure.IoTSolutions.StorageAdapter.Services.Exceptions;
using Microsoft.Extensions.Configuration;
namespace Microsoft.Azure.IoTSolutions.StorageAdapter.Services.Runtime
{
public interface IConfigData
{
string GetString(string key, string defaultValue = "");
bool GetBool(string key, bool defaultValue = false);
int GetInt(string key, int defaultValue = 0);
}
public class ConfigData : IConfigData
{
private readonly IConfigurationRoot configuration;
private readonly ILogger log;
// Key Vault
private KeyVault keyVault;
// Constants
private const string CLIENT_ID = "KeyVault:aadAppId";
private const string CLIENT_SECRET = "KeyVault:aadAppSecret";
private const string KEY_VAULT_NAME = "KeyVault:name";
public ConfigData(ILogger logger)
{
this.log = logger;
// More info about configuration at
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddIniFile("appsettings.ini", optional: true, reloadOnChange: true);
this.configuration = configurationBuilder.Build();
// Set up Key Vault
this.SetUpKeyVault();
}
public string GetString(string key, string defaultValue = "")
{
var value = this.GetSecrets(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
public bool GetBool(string key, bool defaultValue = false)
{
var value = this.GetSecrets(key, defaultValue.ToString()).ToLowerInvariant();
var knownTrue = new HashSet<string> { "true", "t", "yes", "y", "1", "-1" };
var knownFalse = new HashSet<string> { "false", "f", "no", "n", "0" };
if (knownTrue.Contains(value)) return true;
if (knownFalse.Contains(value)) return false;
return defaultValue;
}
public int GetInt(string key, int defaultValue = 0)
{
try
{
return Convert.ToInt32(this.GetSecrets(key, defaultValue.ToString()));
}
catch (Exception e)
{
throw new InvalidConfigurationException($"Unable to load configuration value for '{key}'", e);
}
}
private void SetUpKeyVault()
{
var clientId = this.GetEnvironmentVariable(CLIENT_ID, string.Empty);
var clientSecret = this.GetEnvironmentVariable(CLIENT_SECRET, string.Empty);
var keyVaultName = this.GetEnvironmentVariable(KEY_VAULT_NAME, string.Empty);
// Initailize key vault
this.keyVault = new KeyVault(keyVaultName, clientId, clientSecret, this.log);
}
private string GetSecrets(string key, string defaultValue = "")
{
string value = string.Empty;
value = this.GetLocalVariable(key, defaultValue);
// If secrets are not found locally, search in Key-Vault
if (string.IsNullOrEmpty(value))
{
log.Warn($"Value for secret {key} not found in local env. " +
$" Trying to get the secret from KeyVault.", () => { });
value = this.keyVault.GetSecret(key);
}
return !string.IsNullOrEmpty(value) ? value : defaultValue;
}
private string GetLocalVariable(string key, string defaultValue = "")
{
return this.configuration.GetValue(key, defaultValue);
}
public string GetEnvironmentVariable(string key, string defaultValue = "")
{
var value = this.configuration.GetValue(key, defaultValue);
this.ReplaceEnvironmentVariables(ref value, defaultValue);
return value;
}
private void ReplaceEnvironmentVariables(ref string value, string defaultValue = "")
{
if (string.IsNullOrEmpty(value)) return;
this.ProcessMandatoryPlaceholders(ref value);
this.ProcessOptionalPlaceholders(ref value, out bool notFound);
if (notFound && string.IsNullOrEmpty(value))
{
value = defaultValue;
}
}
private void ProcessMandatoryPlaceholders(ref string value)
{
// Pattern for mandatory replacements: ${VAR_NAME}
const string PATTERN = @"\${([a-zA-Z_][a-zA-Z0-9_]*)}";
// Search
var keys = (from Match m in Regex.Matches(value, PATTERN)
select m.Groups[1].Value).Distinct().ToArray();
// Replace
foreach (DictionaryEntry x in Environment.GetEnvironmentVariables())
{
if (keys.Contains(x.Key))
{
value = value.Replace("${" + x.Key + "}", x.Value.ToString());
}
}
// Non replaced placeholders cause an exception
keys = (from Match m in Regex.Matches(value, PATTERN)
select m.Groups[1].Value).ToArray();
if (keys.Length > 0)
{
var varsNotFound = keys.Aggregate(", ", (current, k) => current + k);
this.log.Error("Environment variables not found", () => new { varsNotFound });
throw new InvalidConfigurationException("Environment variables not found: " + varsNotFound);
}
}
private void ProcessOptionalPlaceholders(ref string value, out bool notFound)
{
notFound = false;
// Pattern for optional replacements: ${?VAR_NAME}
const string PATTERN = @"\${\?([a-zA-Z_][a-zA-Z0-9_]*)}";
// Search
var keys = (from Match m in Regex.Matches(value, PATTERN)
select m.Groups[1].Value).Distinct().ToArray();
// Replace
foreach (DictionaryEntry x in Environment.GetEnvironmentVariables())
{
if (keys.Contains(x.Key))
{
value = value.Replace("${?" + x.Key + "}", x.Value.ToString());
}
}
// Non replaced placeholders cause an exception
keys = (from Match m in Regex.Matches(value, PATTERN)
select m.Groups[1].Value).ToArray();
if (keys.Length > 0)
{
// Remove placeholders
value = keys.Aggregate(value, (current, k) => current.Replace("${?" + k + "}", string.Empty));
var varsNotFound = keys.Aggregate(", ", (current, k) => current + k);
this.log.Warn("Environment variables not found", () => new { varsNotFound });
notFound = true;
}
}
}
}

Просмотреть файл

@ -0,0 +1,71 @@
using Microsoft.Azure.IoTSolutions.StorageAdapter.Services.Diagnostics;
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.Azure.IoTSolutions.StorageAdapter.Services.Runtime
{
public class KeyVault
{
// Key Vault details and access
private readonly string name;
private readonly string clientId;
private readonly string clientSecret;
private ILogger log;
// Key Vault Client
private readonly KeyVaultClient keyVaultClient;
// Constants
private const string KEY_VAULT_URI = "https://{0}.vault.azure.net/secrets/{1}";
public KeyVault(
string name,
string clientId,
string clientSecret,
ILogger logger)
{
this.name = name;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.log = logger;
this.keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(this.GetToken));
}
public string GetSecret(string secretKey)
{
secretKey = secretKey.Split(':').Last();
var uri = string.Format(KEY_VAULT_URI, this.name, secretKey);
try
{
return this.keyVaultClient.GetSecretAsync(uri).Result.Value;
}
catch (Exception e)
{
this.log.Error($"Secret {secretKey} not found in Key Vault.", () => { });
return null;
}
}
//the method that will be provided to the KeyVaultClient
private async Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
ClientCredential clientCred = new ClientCredential(this.clientId, this.clientSecret);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
if (result == null)
{
this.log.Debug($"Failed to obtain authentication token from key vault.", () => { });
throw new System.InvalidOperationException("Failed to obtain the JWT token");
}
return result.AccessToken;
}
}
}

Просмотреть файл

@ -8,5 +8,9 @@
<ItemGroup>
<PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="1.4.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="2.0.6" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="4.5.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.0" />
</ItemGroup>
</Project>

Просмотреть файл

@ -49,19 +49,19 @@ namespace Microsoft.Azure.IoTSolutions.StorageAdapter.WebService
/// <summary>Setup Custom rules overriding autowired ones.</summary>
private static void SetupCustomRules(ContainerBuilder builder)
{
// Instantiate only one logger
// TODO: read log level from configuration
var logger = new Logger(Uptime.ProcessId, LogLevel.Debug);
builder.RegisterInstance(logger).As<ILogger>().SingleInstance();
// Make sure the configuration is read only once.
var config = new Config(new ConfigData());
var config = new Config(new ConfigData(logger));
builder.RegisterInstance(config).As<IConfig>().SingleInstance();
// Service configuration is generated by the entry point, so we
// prepare the instance here.
builder.RegisterInstance(config.ServicesConfig).As<IServicesConfig>().SingleInstance();
// Instantiate only one logger
// TODO: read log level from configuration
var logger = new Logger(Uptime.ProcessId, LogLevel.Debug);
builder.RegisterInstance(logger).As<ILogger>().SingleInstance();
// By default Autofac uses a request lifetime, creating new objects
// for each request, which is good to reduce the risk of memory
// leaks, but not so good for the overall performance.

Просмотреть файл

@ -2,6 +2,8 @@
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Azure.IoTSolutions.StorageAdapter.Services.Diagnostics;
using Microsoft.Azure.IoTSolutions.StorageAdapter.Services.Runtime;
using Microsoft.Azure.IoTSolutions.StorageAdapter.WebService.Runtime;
namespace Microsoft.Azure.IoTSolutions.StorageAdapter.WebService
@ -11,7 +13,7 @@ namespace Microsoft.Azure.IoTSolutions.StorageAdapter.WebService
{
public static void Main(string[] args)
{
var config = new Config(new ConfigData());
var config = new Config(new ConfigData(new Logger(Uptime.ProcessId, LogLevel.Info)));
/*
Print some information to help development and debugging, like

Просмотреть файл

@ -1,21 +1,23 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:9022/",
"sslPort": 0
}
},
"profiles": {
"WebService": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "http://localhost:9022/v1/status",
"environmentVariables": {
"PCS_STORAGEADAPTER_DOCUMENTDB_CONNSTRING": "$(PCS_STORAGEADAPTER_DOCUMENTDB_CONNSTRING)"
},
"applicationUrl": "http://localhost:9022/v1/status"
}
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:9022/",
"sslPort": 0
}
}
},
"profiles": {
"WebService": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "http://localhost:9022/v1/status",
"environmentVariables": {
"PCS_KEYVAULT_NAME": "",
"PCS_AAD_APPID": "",
"PCS_AAD_APPSECRET": ""
},
"applicationUrl": "http://localhost:9022/v1/status"
}
}
}

Просмотреть файл

@ -18,12 +18,12 @@ namespace Microsoft.Azure.IoTSolutions.StorageAdapter.WebService.Runtime
public class Config : IConfig
{
private const string APPLICATION_KEY = "StorageAdapter:";
private const string PORT_KEY = APPLICATION_KEY + "webservice_port";
private const string PORT_KEY = APPLICATION_KEY + "webservicePort";
private const string STORAGE_TYPE_KEY = APPLICATION_KEY + "storageType";
private const string DOCUMENT_DB_CONNECTION_STRING_KEY = APPLICATION_KEY + "documentdb_connstring";
private const string DOCUMENT_DB_DATABASE_KEY = APPLICATION_KEY + "documentdb_database";
private const string DOCUMENT_DB_COLLECTION_KEY = APPLICATION_KEY + "documentdb_collection";
private const string DOCUMENT_DB_RUS_KEY = APPLICATION_KEY + "documentdb_RUs";
private const string DOCUMENT_DB_CONNECTION_STRING_KEY = APPLICATION_KEY + "documentDBConnectionString";
private const string DOCUMENT_DB_DATABASE_KEY = APPLICATION_KEY + "documentDBdatabase";
private const string DOCUMENT_DB_COLLECTION_KEY = APPLICATION_KEY + "documentDBcollection";
private const string DOCUMENT_DB_RUS_KEY = APPLICATION_KEY + "documentDBRUs";
/// <summary>Web service listening port</summary>
public int Port { get; }

Просмотреть файл

@ -1,73 +0,0 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Azure.IoTSolutions.StorageAdapter.Services.Exceptions;
using Microsoft.Extensions.Configuration;
namespace Microsoft.Azure.IoTSolutions.StorageAdapter.WebService.Runtime
{
public interface IConfigData
{
string GetString(string key);
int GetInt(string key);
}
public class ConfigData : IConfigData
{
private readonly IConfigurationRoot configuration;
public ConfigData()
{
// More info about configuration at
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration
var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddIniFile("appsettings.ini", optional: true, reloadOnChange: true);
this.configuration = configurationBuilder.Build();
}
public string GetString(string key)
{
var value = this.configuration.GetValue<string>(key);
return ReplaceEnvironmentVariables(value);
}
public int GetInt(string key)
{
try
{
return Convert.ToInt32(this.GetString(key));
}
catch (Exception e)
{
throw new InvalidConfigurationException($"Unable to load configuration value for '{key}'", e);
}
}
private static string ReplaceEnvironmentVariables(string value)
{
if (string.IsNullOrEmpty(value)) return value;
// Extract the name of all the substitutions required
// using the following pattern, e.g. ${VAR_NAME}
const string pattern = @"\${(?'key'[a-zA-Z_][a-zA-Z0-9_]*)}";
var keys = (from Match m
in Regex.Matches(value, pattern)
select m.Groups[1].Value).ToArray();
foreach (DictionaryEntry x in Environment.GetEnvironmentVariables())
{
if (keys.Contains(x.Key))
{
value = value.Replace("${" + x.Key + "}", x.Value.ToString());
}
}
return value;
}
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше