Skip to content

Commit d5985d6

Browse files
v-imohammadanandagopal6anjanaNandagopal
authored
v3.20.1 hotfix (#9450)
* backport to v3 (#9362) Co-authored-by: anandagopal <[email protected]> * hotfix v3.20.1 --------- Co-authored-by: Anjana Nandagopal <[email protected]> Co-authored-by: anandagopal <[email protected]>
1 parent 71193d6 commit d5985d6

File tree

5 files changed

+116
-11
lines changed

5 files changed

+116
-11
lines changed

build/common.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<LangVersion>latest</LangVersion>
66
<MajorVersion>3</MajorVersion>
77
<MinorVersion>20</MinorVersion>
8-
<PatchVersion>0</PatchVersion>
8+
<PatchVersion>1</PatchVersion>
99
<VersionPrefix>$(MajorVersion).$(MinorVersion).$(PatchVersion)</VersionPrefix>
1010
<Version Condition=" '$(BuildNumber)' != '' ">$(VersionPrefix)-$(BuildNumber)</Version>
1111
<Version Condition=" '$(Version)' == '' ">$(VersionPrefix)</Version>

src/WebJobs.Script.WebHost/Management/InstanceManager.cs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,25 +63,37 @@ public async Task<string> SpecializeMSISidecar(HostAssignmentContext context)
6363

6464
if (msiEnabled)
6565
{
66-
if (context.MSIContext == null)
66+
if (context.MSIContext == null && context.EncryptedTokenServiceSpecializationPayload == null)
6767
{
68-
_logger.LogWarning("Skipping specialization of MSI sidecar since MSIContext was absent");
68+
_logger.LogWarning("Skipping specialization of MSI sidecar since MSIContext and EncryptedTokenServiceSpecializationPayload were absent");
6969
await _meshServiceClient.NotifyHealthEvent(ContainerHealthEventType.Fatal, this.GetType(),
70-
"Could not specialize MSI sidecar since MSIContext was empty");
70+
"Could not specialize MSI sidecar since MSIContext and EncryptedTokenServiceSpecializationPayload were empty");
7171
}
7272
else
7373
{
7474
using (_metricsLogger.LatencyEvent(MetricEventNames.LinuxContainerSpecializationMSIInit))
7575
{
7676
var uri = new Uri(endpoint);
77-
var address = $"http://{uri.Host}:{uri.Port}{ScriptConstants.LinuxMSISpecializationStem}";
77+
var addressStem = GetMsiSpecializationRequestAddressStem(context);
78+
79+
var address = $"http://{uri.Host}:{uri.Port}{addressStem}";
7880

7981
_logger.LogDebug($"Specializing sidecar at {address}");
8082

83+
StringContent payload;
84+
if (string.IsNullOrEmpty(context.EncryptedTokenServiceSpecializationPayload))
85+
{
86+
payload = new StringContent(JsonConvert.SerializeObject(context.MSIContext),
87+
Encoding.UTF8, "application/json");
88+
}
89+
else
90+
{
91+
payload = new StringContent(context.EncryptedTokenServiceSpecializationPayload, Encoding.UTF8);
92+
}
93+
8194
var requestMessage = new HttpRequestMessage(HttpMethod.Post, address)
8295
{
83-
Content = new StringContent(JsonConvert.SerializeObject(context.MSIContext),
84-
Encoding.UTF8, "application/json")
96+
Content = payload
8597
};
8698

8799
var response = await _client.SendAsync(requestMessage);
@@ -103,6 +115,23 @@ await _meshServiceClient.NotifyHealthEvent(ContainerHealthEventType.Fatal, this.
103115
return null;
104116
}
105117

118+
private string GetMsiSpecializationRequestAddressStem(HostAssignmentContext context)
119+
{
120+
var stem = ScriptConstants.LinuxMSISpecializationStem;
121+
122+
if (!string.IsNullOrEmpty(context.EncryptedTokenServiceSpecializationPayload))
123+
{
124+
_logger.LogDebug("Using encrypted TokenService payload format");
125+
126+
// use default encrypted API endpoint if endpoint not provided in context
127+
stem = string.IsNullOrEmpty(context.TokenServiceApiEndpoint)
128+
? ScriptConstants.LinuxEncryptedTokenServiceSpecializationStem
129+
: context.TokenServiceApiEndpoint;
130+
}
131+
132+
return stem;
133+
}
134+
106135
public bool StartAssignment(HostAssignmentContext context)
107136
{
108137
if (!_webHostEnvironment.InStandbyMode)

src/WebJobs.Script.WebHost/Models/HostAssignmentContext.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ public class HostAssignmentContext
2727
[JsonProperty("MSISpecializationPayload")]
2828
public MSIContext MSIContext { get; set; }
2929

30+
[JsonProperty("EncryptedTokenServiceSpecializationPayload")]
31+
public string EncryptedTokenServiceSpecializationPayload { get; set; }
32+
33+
[JsonProperty("TokenServiceApiEndpoint")]
34+
public string TokenServiceApiEndpoint { get; set; }
35+
3036
[JsonProperty("CorsSpecializationPayload")]
3137
public CorsSettings CorsSettings { get; set; }
3238

src/WebJobs.Script/ScriptConstants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ public static class ScriptConstants
164164
public const string LinuxFunctionDetailsEventStreamName = "MS_FUNCTION_DETAILS";
165165
public const string LinuxAzureMonitorEventStreamName = "MS_FUNCTION_AZURE_MONITOR_EVENT";
166166
public const string LinuxMSISpecializationStem = "/api/specialize?api-version=2017-09-01";
167+
public const string LinuxEncryptedTokenServiceSpecializationStem = "/api/specialize?api-version=2023-05-01";
167168

168169
public const string DurableTaskPropertyName = "durableTask";
169170
public const string DurableTaskHubName = "HubName";

test/WebJobs.Script.Tests.Integration/Management/InstanceManagerTests.cs

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ public async Task DoesNotSpecializeMSISidecar_WhenMSIContextNull()
701701

702702
var meshServiceClient = new Mock<IMeshServiceClient>(MockBehavior.Strict);
703703
meshServiceClient.Setup(c => c.NotifyHealthEvent(ContainerHealthEventType.Fatal,
704-
It.Is<Type>(t => t == typeof(InstanceManager)), "Could not specialize MSI sidecar since MSIContext was empty")).Returns(Task.CompletedTask);
704+
It.Is<Type>(t => t == typeof(InstanceManager)), "Could not specialize MSI sidecar since MSIContext and EncryptedTokenServiceSpecializationPayload were empty")).Returns(Task.CompletedTask);
705705

706706
var instanceManager = GetInstanceManagerForMSISpecialization(assignmentContext, HttpStatusCode.BadRequest, meshServiceClient.Object);
707707

@@ -711,10 +711,73 @@ public async Task DoesNotSpecializeMSISidecar_WhenMSIContextNull()
711711
var logs = _loggerProvider.GetAllLogMessages().Select(p => p.FormattedMessage).ToArray();
712712
Assert.Collection(logs,
713713
p => Assert.StartsWith("MSI enabled status: True", p),
714-
p => Assert.StartsWith("Skipping specialization of MSI sidecar since MSIContext was absent", p));
714+
p => Assert.StartsWith("Skipping specialization of MSI sidecar since MSIContext and EncryptedTokenServiceSpecializationPayload were absent", p));
715715

716716
meshServiceClient.Verify(c => c.NotifyHealthEvent(ContainerHealthEventType.Fatal,
717-
It.Is<Type>(t => t == typeof(InstanceManager)), "Could not specialize MSI sidecar since MSIContext was empty"), Times.Once);
717+
It.Is<Type>(t => t == typeof(InstanceManager)), "Could not specialize MSI sidecar since MSIContext and EncryptedTokenServiceSpecializationPayload were empty"), Times.Once);
718+
}
719+
720+
[Fact]
721+
public async Task SpecializeMSISidecar_Succeeds_EncryptedMSIContextWithoutProvidedEndpoint()
722+
{
723+
var environment = new Dictionary<string, string>()
724+
{
725+
{ EnvironmentSettingNames.MsiEndpoint, "http://localhost:8081" },
726+
{ EnvironmentSettingNames.MsiSecret, "secret" }
727+
};
728+
var assignmentContext = new HostAssignmentContext
729+
{
730+
SiteId = 1234,
731+
SiteName = "TestSite",
732+
Environment = environment,
733+
IsWarmupRequest = false,
734+
MSIContext = new MSIContext(),
735+
EncryptedTokenServiceSpecializationPayload = "TestContext"
736+
};
737+
738+
var instanceManager = GetInstanceManagerForMSISpecialization(assignmentContext, HttpStatusCode.OK, null);
739+
740+
string error = await instanceManager.SpecializeMSISidecar(assignmentContext);
741+
Assert.Null(error);
742+
743+
var logs = _loggerProvider.GetAllLogMessages().Select(p => p.FormattedMessage).ToArray();
744+
Assert.Collection(logs,
745+
p => Assert.StartsWith("MSI enabled status: True", p),
746+
p => Assert.StartsWith("Using encrypted TokenService payload format", p),
747+
p => Assert.Equal($"Specializing sidecar at http://localhost:8081{ScriptConstants.LinuxEncryptedTokenServiceSpecializationStem}", p),
748+
p => Assert.StartsWith("Specialize MSI sidecar returned OK", p));
749+
}
750+
751+
[Fact]
752+
public async Task SpecializeMSISidecar_Succeeds_EncryptedMSIContextWithProvidedEndpoint()
753+
{
754+
var environment = new Dictionary<string, string>()
755+
{
756+
{ EnvironmentSettingNames.MsiEndpoint, "http://localhost:8081" },
757+
{ EnvironmentSettingNames.MsiSecret, "secret" }
758+
};
759+
var assignmentContext = new HostAssignmentContext
760+
{
761+
SiteId = 1234,
762+
SiteName = "TestSite",
763+
Environment = environment,
764+
IsWarmupRequest = false,
765+
MSIContext = new MSIContext(),
766+
EncryptedTokenServiceSpecializationPayload = "TestContext",
767+
TokenServiceApiEndpoint = "/api/TestEndpoint"
768+
};
769+
770+
var instanceManager = GetInstanceManagerForMSISpecialization(assignmentContext, HttpStatusCode.OK, null);
771+
772+
string error = await instanceManager.SpecializeMSISidecar(assignmentContext);
773+
Assert.Null(error);
774+
775+
var logs = _loggerProvider.GetAllLogMessages().Select(p => p.FormattedMessage).ToArray();
776+
Assert.Collection(logs,
777+
p => Assert.StartsWith("MSI enabled status: True", p),
778+
p => Assert.StartsWith("Using encrypted TokenService payload format", p),
779+
p => Assert.Equal($"Specializing sidecar at http://localhost:8081{assignmentContext.TokenServiceApiEndpoint}", p),
780+
p => Assert.StartsWith("Specialize MSI sidecar returned OK", p));
718781
}
719782

720783
[Fact]
@@ -1258,9 +1321,15 @@ private InstanceManager GetInstanceManagerForMSISpecialization(HostAssignmentCon
12581321

12591322
var msiEndpoint = hostAssignmentContext.Environment[EnvironmentSettingNames.MsiEndpoint] + ScriptConstants.LinuxMSISpecializationStem;
12601323

1324+
var defaultEncryptedMsiEndpoint = hostAssignmentContext.Environment[EnvironmentSettingNames.MsiEndpoint] + ScriptConstants.LinuxEncryptedTokenServiceSpecializationStem;
1325+
1326+
var providedEncryptedMsiEndpoint = hostAssignmentContext.Environment[EnvironmentSettingNames.MsiEndpoint] + hostAssignmentContext.TokenServiceApiEndpoint;
1327+
12611328
handlerMock.Protected().Setup<Task<HttpResponseMessage>>("SendAsync",
12621329
ItExpr.Is<HttpRequestMessage>(request => request.Method == HttpMethod.Post
1263-
&& request.RequestUri.AbsoluteUri.Equals(msiEndpoint)
1330+
&& (request.RequestUri.AbsoluteUri.Equals(msiEndpoint)
1331+
|| request.RequestUri.AbsoluteUri.Equals(defaultEncryptedMsiEndpoint)
1332+
|| request.RequestUri.AbsoluteUri.Equals(providedEncryptedMsiEndpoint))
12641333
&& request.Content != null),
12651334
ItExpr.IsAny<CancellationToken>()).ReturnsAsync(new HttpResponseMessage
12661335
{

0 commit comments

Comments
 (0)