Skip to content

Commit

Permalink
Add source and site instance information to secret files. Fixes #2094
Browse files Browse the repository at this point in the history
  • Loading branch information
alrod committed Jan 4, 2018
1 parent 5867f55 commit d02ec26
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 11 deletions.
14 changes: 14 additions & 0 deletions src/WebJobs.Script.WebHost/Security/KeyManagement/ScriptSecrets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs.Script.Config;
using Newtonsoft.Json;

namespace Microsoft.Azure.WebJobs.Script.WebHost
Expand All @@ -15,6 +17,9 @@ public abstract class ScriptSecrets
{
protected ScriptSecrets()
{
HostName = ScriptSettingsManager.Instance.GetSetting(EnvironmentSettingNames.AzureWebsiteHostName);
InstanceId = ScriptSettingsManager.Instance.InstanceId;
Source = ScriptConstants.Runtime;
}

[JsonIgnore]
Expand All @@ -23,6 +28,15 @@ protected ScriptSecrets()
[JsonIgnore]
public abstract ScriptSecretsType SecretsType { get; }

[JsonProperty(PropertyName = "hostName")]
public string HostName { get; set; }

[JsonProperty(PropertyName = "instanceId")]
public string InstanceId { get; set; }

[JsonProperty(PropertyName = "source")]
public string Source { get; set; }

protected abstract ICollection<Key> GetKeys(string keyScope);

public abstract ScriptSecrets Refresh(IKeyValueConverterFactory factory);
Expand Down
11 changes: 11 additions & 0 deletions src/WebJobs.Script/Config/ScriptSettingsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ public virtual string AzureWebsiteUniqueSlotName
}
}

public virtual string InstanceId
{
get
{
string instanceId = GetSetting(EnvironmentSettingNames.AzureWebsiteInstanceId)
?? Environment.MachineName.GetHashCode().ToString("X").PadLeft(32, '0');

return instanceId.Substring(0, 32);
}
}

public virtual string ApplicationInsightsInstrumentationKey
{
get => GetSettingFromCache(EnvironmentSettingNames.AppInsightsInstrumentationKey);
Expand Down
5 changes: 1 addition & 4 deletions src/WebJobs.Script/Host/ScriptHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,7 @@ public string InstanceId
{
if (_instanceId == null)
{
_instanceId = _settingsManager.GetSetting(EnvironmentSettingNames.AzureWebsiteInstanceId)
?? Environment.MachineName.GetHashCode().ToString("X").PadLeft(32, '0');

_instanceId = _instanceId.Substring(0, 32);
_instanceId = _settingsManager.InstanceId;
}

return _instanceId;
Expand Down
1 change: 1 addition & 0 deletions src/WebJobs.Script/ScriptConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public static class ScriptConstants
public static readonly ImmutableArray<string> HttpMethods = ImmutableArray.Create("get", "post", "delete", "head", "patch", "put", "options");
public const string HttpMethodConstraintName = "httpMethod";
public static readonly ImmutableArray<string> AssemblyFileTypes = ImmutableArray.Create(".dll", ".exe");
public const string Runtime = "runtime";

public const int MaximumHostIdLength = 32;
public const int DynamicSkuConnectionLimit = 50;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Azure.WebJobs.Script.Config;
using Microsoft.Azure.WebJobs.Script.WebHost;
using Newtonsoft.Json.Linq;
using Xunit;
Expand Down Expand Up @@ -40,16 +41,23 @@ public void SerializeFunctionSecrets_ReturnsExpectedResult()

var jsonObject = JObject.Parse(serializedSecret);
var serializedSecrets = jsonObject.Property("keys")?.Value?.ToObject<List<Key>>();
var source = jsonObject.Property("source")?.Value;
var hostName = jsonObject.Property("hostName")?.Value;
var instanceId = jsonObject.Property("instanceId")?.Value;

Assert.NotNull(serializedSecret);
AssertKeyCollectionsEquality(secrets.Keys, serializedSecrets);
Assert.Equal(source, secrets.Source);
Assert.Equal(hostName, secrets.HostName);
Assert.Equal(instanceId, secrets.InstanceId);
}

[Fact]
public void DeserializeFunctionSecrets_ReturnsExpectedResult()
[Theory]
[InlineData("{ 'keys': [ { 'name': 'Key1', 'value': 'Value1', 'encrypted': false }, { 'name': 'Key2', 'value': 'Value2', 'encrypted': true } ] }", null)]
[InlineData("{ 'keys': [ { 'name': 'Key1', 'value': 'Value1', 'encrypted': false }, { 'name': 'Key2', 'value': 'Value2', 'encrypted': true } ], 'hostName': 'test', 'source': 'runtime'}", "test")]
public void DeserializeFunctionSecrets_ReturnsExpectedResult(string serializedSecret, string hostName)
{
var serializer = new ScriptSecretSerializerV1();
var serializedSecret = "{ 'keys': [ { 'name': 'Key1', 'value': 'Value1', 'encrypted': false }, { 'name': 'Key2', 'value': 'Value2', 'encrypted': true } ] }";
var expected = new List<Key>
{
new Key
Expand All @@ -67,14 +75,16 @@ public void DeserializeFunctionSecrets_ReturnsExpectedResult()
};

FunctionSecrets actual = serializer.DeserializeSecrets<FunctionSecrets>(JObject.Parse(serializedSecret));
Assert.Equal(hostName, actual.HostName);
AssertKeyCollectionsEquality(expected, actual.Keys);
}

[Fact]
public void DeserializeHostSecrets_ReturnsExpectedResult()
[Theory]
[InlineData("{'masterKey':{'name':'master','value':'1234','encrypted':false},'functionKeys':[{'name':'Key1','value':'Value1','encrypted':false},{'name':'Key2','value':'Value2','encrypted':true}]}", null)]
[InlineData("{'masterKey':{'name':'master','value':'1234','encrypted':false},'functionKeys':[{'name':'Key1','value':'Value1','encrypted':false},{'name':'Key2','value':'Value2','encrypted':true}], 'hostName': 'test', 'source': 'runtime' }", "test")]
public void DeserializeHostSecrets_ReturnsExpectedResult(string serializedSecret, string hostName)
{
var serializer = new ScriptSecretSerializerV1();
var serializedSecret = "{'masterKey':{'name':'master','value':'1234','encrypted':false},'functionKeys':[{'name':'Key1','value':'Value1','encrypted':false},{'name':'Key2','value':'Value2','encrypted':true}]}";
var expected = new HostSecrets
{
MasterKey = new Key { Name = "master", Value = "1234" },
Expand All @@ -92,13 +102,16 @@ public void DeserializeHostSecrets_ReturnsExpectedResult()
Value = "Value2",
IsEncrypted = true
}
}
},
HostName = hostName
};

HostSecrets actual = serializer.DeserializeSecrets<HostSecrets>(JObject.Parse(serializedSecret));

Assert.NotNull(actual);
Assert.Equal(expected.MasterKey, actual.MasterKey);
Assert.Equal(actual.HostName, hostName);
Assert.Equal(expected.Source, ScriptConstants.Runtime);
AssertKeyCollectionsEquality(expected.FunctionKeys, actual.FunctionKeys);
}

Expand Down Expand Up @@ -132,17 +145,20 @@ public void SerializeHostSecrets_ReturnsExpectedResult()
var jsonObject = JObject.Parse(serializedSecret);
var functionSecrets = jsonObject.Property("functionKeys")?.Value?.ToObject<List<Key>>();
var masterKey = jsonObject.Property("masterKey")?.Value?.ToObject<Key>();
var instanceId = jsonObject.Property("instanceId")?.Value;

Assert.NotNull(serializedSecret);
Assert.Equal(secrets.MasterKey, masterKey);
AssertKeyCollectionsEquality(secrets.FunctionKeys, functionSecrets);
Assert.Equal(instanceId, secrets.InstanceId);
}

[Theory]
[InlineData(typeof(HostSecrets), false, "{'masterKey': 'masterKeySecretString','functionKey': 'functionKeySecretString'}")]
[InlineData(typeof(FunctionSecrets), false, "{'key':'functionKeySecretString'}")]
[InlineData(typeof(HostSecrets), true, "{'masterKey': {'name': 'master','value': '1234','encrypted': false},'functionKeys': [{'name': 'Key1','value': 'Value1','encrypted': false},{'name': 'Key2','value': 'Value2','encrypted': true}]}")]
[InlineData(typeof(FunctionSecrets), true, "{'keys': [{'name': 'Key1','value': 'Value1','encrypted': false},{'name': 'Key2','value': 'Value2','encrypted': true}]}")]
[InlineData(typeof(HostSecrets), false, "{'masterKey': 'masterKeySecretString','functionKey': 'functionKeySecretString', 'hostName': 'test1', 'instanceId': 'test2', 'source': 'test3'}")]
public void CanSerialize_WithValidHostPayload_ReturnsTrue(Type type, bool expectedResult, string input)
{
var serializer = new ScriptSecretSerializerV1();
Expand Down

0 comments on commit d02ec26

Please sign in to comment.