fix(site-secrets): one shared secret: reference parser for scanner and MxGateway adapter
Final review M3: SecretReferenceScanner.TryParseSecretReference (trimmed, case-insensitive
prefix, trimmed name, empty = not a reference, ${secret:} never matches) is used by the scanner
and by MxGatewayDataConnection's ApiKey resolution, so a padded or case-variant reference
resolves the name central ships. A bare 'secret:' ApiKey now fails closed. M7: unit test pins
stamped hash == ComputeCurrentArtifactHashesAsync with a non-empty Secrets list.
This commit is contained in:
+37
@@ -52,6 +52,43 @@ public class MxGatewayDataConnectionSecretsTests
|
||||
Assert.Contains("mxgateway/testconn/api-key", resolver.Requested);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("secret:mxgw-key ")]
|
||||
[InlineData(" SECRET: mxgw-key")]
|
||||
[InlineData("Secret:mxgw-key")]
|
||||
public async Task ConnectAsync_resolves_padded_or_case_variant_ref_to_the_name_the_scanner_ships(string apiKey)
|
||||
{
|
||||
// Final review M3: the adapter and central's SecretReferenceScanner share one parser,
|
||||
// so the name looked up is exactly the name that was deployed.
|
||||
var shipped = Assert.Single(ZB.MOM.WW.ScadaBridge.Commons.Types.Secrets.SecretReferenceScanner.Scan([
|
||||
new ZB.MOM.WW.ScadaBridge.Commons.Messages.Artifacts.DataConnectionArtifact(
|
||||
"GW", "MxGateway", System.Text.Json.JsonSerializer.Serialize(new { ApiKey = apiKey }), null, 3),
|
||||
])).Name;
|
||||
|
||||
var fake = new FakeMxGatewayClient();
|
||||
var resolver = new FakeSecretResolver("resolved-plaintext-key");
|
||||
var adapter = new MxGatewayDataConnection(fake, NullLogger<MxGatewayDataConnection>.Instance, resolver);
|
||||
|
||||
await adapter.ConnectAsync(Details(apiKey));
|
||||
|
||||
Assert.Equal("mxgw-key", shipped);
|
||||
Assert.Equal([shipped], resolver.Requested);
|
||||
Assert.Equal("resolved-plaintext-key", fake.ConnectedWith!.ApiKey);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ConnectAsync_fails_closed_on_a_secret_ref_with_no_name()
|
||||
{
|
||||
var fake = new FakeMxGatewayClient();
|
||||
var resolver = new FakeSecretResolver("SHOULD-NOT-BE-USED");
|
||||
var adapter = new MxGatewayDataConnection(fake, NullLogger<MxGatewayDataConnection>.Instance, resolver);
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => adapter.ConnectAsync(Details("secret: ")));
|
||||
|
||||
Assert.Null(fake.ConnectedWith);
|
||||
Assert.Empty(resolver.Requested);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ConnectAsync_passes_literal_apikey_unchanged_and_does_not_call_resolver()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user