public async Task KeyVaultSecretProvider_WithUserAssignedManagedIdentity_GetSecret_NonExistingSecret_ThrowsSecretNotFoundException()
        {
            // Arrange
            var    keyVaultUri = Configuration.GetValue <string>("Arcus:KeyVault:Uri");
            string tenantId    = Configuration.GetTenantId();
            string clientId    = Configuration.GetServicePrincipalClientId();
            string clientKey   = Configuration.GetServicePrincipalClientSecret();

            using (TemporaryEnvironmentVariable.Create(Constants.AzureTenantIdEnvironmentVariable, tenantId))
                using (TemporaryEnvironmentVariable.Create(Constants.AzureServicePrincipalClientIdVariable, clientId))
                    using (TemporaryEnvironmentVariable.Create(Constants.AzureServicePrincipalClientSecretVariable, clientKey))
                    {
                        var notExistingSecretName  = $"secret-{Guid.NewGuid():N}";
                        var keyVaultSecretProvider = new KeyVaultSecretProvider(
                            tokenCredential: new ChainedTokenCredential(new ManagedIdentityCredential(clientId), new EnvironmentCredential()),
                            vaultConfiguration: new KeyVaultConfiguration(keyVaultUri));

                        // Assert
                        await Assert.ThrowsAsync <SecretNotFoundException>(async() =>
                        {
                            // Act
                            await keyVaultSecretProvider.GetSecretAsync(notExistingSecretName);
                        });
                    }
        }
        public async Task KeyVaultSecretProvider_WithUserAssignedManagedIdentity_GetSecret_Succeeds()
        {
            // Arrange
            var    keyVaultUri = Configuration.GetValue <string>("Arcus:KeyVault:Uri");
            string tenantId    = Configuration.GetTenantId();
            string clientId    = Configuration.GetServicePrincipalClientId();
            string clientKey   = Configuration.GetServicePrincipalClientSecret();
            var    secretName  = Configuration.GetValue <string>("Arcus:KeyVault:TestKeyName");

            using (TemporaryEnvironmentVariable.Create(Constants.AzureTenantIdEnvironmentVariable, tenantId))
                using (TemporaryEnvironmentVariable.Create(Constants.AzureServicePrincipalClientIdVariable, clientId))
                    using (TemporaryEnvironmentVariable.Create(Constants.AzureServicePrincipalClientSecretVariable, clientKey))
                    {
                        var keyVaultSecretProvider = new KeyVaultSecretProvider(
                            tokenCredential: new ChainedTokenCredential(new ManagedIdentityCredential(clientId), new EnvironmentCredential()),
                            vaultConfiguration: new KeyVaultConfiguration(keyVaultUri));

                        // Act
                        Secret secret = await keyVaultSecretProvider.GetSecretAsync(secretName);

                        // Assert
                        Assert.NotNull(secret);
                        Assert.NotNull(secret.Value);
                        Assert.NotNull(secret.Version);
                    }
        }
        public async Task KeyVaultSecretProvider_StoreSecret_Succeeds()
        {
            // Arrange
            var    keyVaultUri = Configuration.GetValue <string>("Arcus:KeyVault:Uri");
            string tenantId    = Configuration.GetTenantId();
            string clientId    = Configuration.GetServicePrincipalClientId();
            string clientKey   = Configuration.GetServicePrincipalClientSecret();

            var secretName  = $"Test-Secret-{Guid.NewGuid()}";
            var secretValue = Guid.NewGuid().ToString();

            using (TemporaryEnvironmentVariable.Create(Constants.AzureTenantIdEnvironmentVariable, tenantId))
                using (TemporaryEnvironmentVariable.Create(Constants.AzureServicePrincipalClientIdVariable, clientId))
                    using (TemporaryEnvironmentVariable.Create(Constants.AzureServicePrincipalClientSecretVariable, clientKey))
                    {
                        var keyVaultSecretProvider = new KeyVaultSecretProvider(
                            tokenCredential: new ChainedTokenCredential(new ManagedIdentityCredential(clientId), new EnvironmentCredential()),
                            vaultConfiguration: new KeyVaultConfiguration(keyVaultUri));
                        var cachedSecretProvider = new KeyVaultCachedSecretProvider(keyVaultSecretProvider);

                        // Act
                        Secret secret = await cachedSecretProvider.StoreSecretAsync(secretName, secretValue);

                        // Assert
                        Assert.NotNull(secret);
                        Assert.NotNull(secret.Value);
                        Assert.NotNull(secret.Version);
                        Secret fetchedSecret = await cachedSecretProvider.GetSecretAsync(secretName);

                        Assert.Equal(secretValue, fetchedSecret.Value);
                        Assert.Equal(secret.Version, fetchedSecret.Version);
                        Assert.Equal(secret.Expires, fetchedSecret.Expires);
                    }
        }
        public async Task ConfigureSecretStore_AddEnvironmentVariablesWithOptions_UsesEnvironmentVariableSecrets()
        {
            // Arrange
            string secretKey = "MySecret";
            string expected  = $"secret-{Guid.NewGuid()}";

            var builder = new HostBuilder();

            using (TemporaryEnvironmentVariable.Create(secretKey, expected))
            {
                // Act
                builder.ConfigureSecretStore((config, stores) =>
                {
                    stores.AddEnvironmentVariables(target: EnvironmentVariableTarget.Process, prefix: null, name: null, mutateSecretName: null);
                });

                // Assert
                IHost host     = builder.Build();
                var   provider = host.Services.GetRequiredService <ISecretProvider>();

                string actual = await provider.GetRawSecretAsync(secretKey);

                Assert.Equal(expected, actual);
            }
        }
Esempio n. 5
0
        public void LogEventWithPodNameProperty_WithKubernetesEnricher_HasEnvironmentInformation()
        {
            // Arrange
            string expectedPodName = $"pod-{Guid.NewGuid()}";
            string ignoredPodName  = $"pod-{Guid.NewGuid()}";

            var     spy    = new InMemoryLogSink();
            ILogger logger = new LoggerConfiguration()
                             .Enrich.With <KubernetesEnricher>()
                             .WriteTo.Sink(spy)
                             .CreateLogger();

            using (TemporaryEnvironmentVariable.Create(PodNameVariable, ignoredPodName))
            {
                // Act
                logger.Information("This log even already has a Kubernetes PodName {PodName}", expectedPodName);
            }

            // Assert
            LogEvent logEvent = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(logEvent);

            Assert.True(logEvent.ContainsProperty(ContextProperties.Kubernetes.PodName, expectedPodName), "Log event should contain pod name property");
            Assert.DoesNotContain(logEvent.Properties, prop => prop.Key == ContextProperties.Kubernetes.NodeName);
            Assert.DoesNotContain(logEvent.Properties, prop => prop.Key == ContextProperties.Kubernetes.Namespace);
        }
Esempio n. 6
0
        public void LogEvent_WithKubernetesEnricher_HasEnvironmentInformation()
        {
            // Arrange
            string nodeName   = $"node-{Guid.NewGuid()}";
            string podName    = $"pod-{Guid.NewGuid()}";
            string @namespace = $"namespace-{Guid.NewGuid()}";

            var     spy    = new InMemoryLogSink();
            ILogger logger = new LoggerConfiguration()
                             .Enrich.With <KubernetesEnricher>()
                             .WriteTo.Sink(spy)
                             .CreateLogger();

            using (TemporaryEnvironmentVariable.Create(NodeNameVariable, nodeName))
                using (TemporaryEnvironmentVariable.Create(PodNameVariable, podName))
                    using (TemporaryEnvironmentVariable.Create(NamespaceVariable, @namespace))
                    {
                        // Act
                        logger.Information("This log event should be enriched with Kubernetes information");
                    }

            // Assert
            LogEvent logEvent = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(logEvent);

            Assert.True(logEvent.ContainsProperty(ContextProperties.Kubernetes.NodeName, nodeName), "Log event should contain node name property");
            Assert.True(logEvent.ContainsProperty(ContextProperties.Kubernetes.PodName, podName), "Log event should contain pod name property");
            Assert.True(logEvent.ContainsProperty(ContextProperties.Kubernetes.Namespace, @namespace), "Log event should contain namespace property");
        }
Esempio n. 7
0
        public async Task ServiceBusQueueMessagePumpUsingManagedIdentity_PublishServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);
            ServiceBusConnectionStringProperties properties = ServiceBusConnectionStringProperties.Parse(connectionString);

            ServicePrincipal servicePrincipal = config.GetServiceBusServicePrincipal();
            string           tenantId         = config.GetTenantId();

            using (TemporaryEnvironmentVariable.Create(EnvironmentVariables.AzureTenantId, tenantId))
                using (TemporaryEnvironmentVariable.Create(EnvironmentVariables.AzureServicePrincipalClientId, servicePrincipal.ClientId))
                    using (TemporaryEnvironmentVariable.Create(EnvironmentVariables.AzureServicePrincipalClientSecret, servicePrincipal.ClientSecret))
                    {
                        var options = new WorkerOptions();
                        options.AddEventGridPublisher(config)
                        .AddServiceBusQueueMessagePumpUsingManagedIdentity(
                            queueName: properties.EntityPath,
                            serviceBusNamespace: properties.FullyQualifiedNamespace,
                            clientId: servicePrincipal.ClientId,
                            configureMessagePump: opt => opt.AutoComplete = true)
                        .WithServiceBusMessageHandler <OrdersAzureServiceBusMessageHandler, Order>();

                        // Act
                        await using (var worker = await Worker.StartNewAsync(options))
                            await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                            {
                                // Assert
                                await service.SimulateMessageProcessingAsync(connectionString);
                            }
                    }
        }
        public async Task KeyVaultSecretProvider_StoreSecret_Succeeds()
        {
            // Arrange
            var keyVaultUri            = Configuration.GetValue <string>("Arcus:KeyVault:Uri");
            var connectionString       = Configuration.GetValue <string>("Arcus:MSI:AzureServicesAuth:ConnectionString");
            var secretName             = $"Test-Secret-{Guid.NewGuid()}";
            var secretValue            = Guid.NewGuid().ToString();
            var keyVaultSecretProvider = new KeyVaultSecretProvider(
                authentication: new ManagedServiceIdentityAuthentication(),
                vaultConfiguration: new KeyVaultConfiguration(keyVaultUri));

            using (TemporaryEnvironmentVariable.Create(KeyVaultConnectionStringEnvironmentVariable, connectionString))
            {
                // Act
                Secret secret = await keyVaultSecretProvider.StoreSecretAsync(secretName, secretValue);

                // Assert
                Assert.NotNull(secret);
                Assert.NotNull(secret.Value);
                Assert.NotNull(secret.Version);
                Secret fetchedSecret = await keyVaultSecretProvider.GetSecretAsync(secretName);

                Assert.Equal(secretValue, fetchedSecret.Value);
                Assert.Equal(secret.Version, fetchedSecret.Version);
                Assert.Equal(secret.Expires, fetchedSecret.Expires);
            }
        }
        public async Task ConfigureSecretStore_AddEnvironmentVariables_UsesEnvironmentVariableSecrets()
        {
            // Arrange
            string secretKey   = "MySecret";
            string secretValue = $"secret-{Guid.NewGuid()}";

            var builder = new HostBuilder();

            using (TemporaryEnvironmentVariable.Create(secretKey, secretValue))
            {
                // Act
                builder.ConfigureSecretStore((config, stores) => stores.AddEnvironmentVariables());

                // Assert
                IHost host     = builder.Build();
                var   provider = host.Services.GetRequiredService <ISecretProvider>();
                Assert.Equal(secretValue, await provider.GetRawSecretAsync(secretKey));
            }
        }
        public async Task ConfigureSecretStore_AddEnvironmentVariablesWithPrefix_CantFindEnvironmentVariableWithPrefix()
        {
            // Arrange
            string unknownPrefix = "UNKNOWN_";
            string secretKey     = "MySecret";

            var builder = new HostBuilder();

            using (TemporaryEnvironmentVariable.Create(secretKey, value: $"secret-{Guid.NewGuid()}"))
            {
                // Act
                builder.ConfigureSecretStore((config, stores) => stores.AddEnvironmentVariables(prefix: unknownPrefix));

                // Assert
                IHost host     = builder.Build();
                var   provider = host.Services.GetRequiredService <ISecretProvider>();

                await Assert.ThrowsAsync <SecretNotFoundException>(() => provider.GetRawSecretAsync(secretKey));
            }
        }
        public async Task ConfigureSecretStore_AddEnvironmentVariablesWithWrongMutation_CantFindEnvironmentVariable()
        {
            // Arrange
            var builder = new HostBuilder();

            using (TemporaryEnvironmentVariable.Create("ARCUS_ENVIRONMENT_SECRET", Guid.NewGuid().ToString()))
            {
                // Act
                builder.ConfigureSecretStore((config, stores) =>
                {
                    stores.AddEnvironmentVariables(mutateSecretName: name => name.Replace("_", "."));
                });

                // Assert
                IHost host     = builder.Build();
                var   provider = host.Services.GetRequiredService <ISecretProvider>();

                await Assert.ThrowsAsync <SecretNotFoundException>(() => provider.GetSecretAsync("ARCUS_ENVIRONMENT_SECRET"));
            }
        }
        public async Task KeyVaultSecretProvider_WithDefaultManagedServiceIdentity_GetSecret_NonExistingSecret_ThrowsSecretNotFoundException()
        {
            // Arrange
            var keyVaultUri            = Configuration.GetValue <string>("Arcus:KeyVault:Uri");
            var connectionString       = Configuration.GetValue <string>("Arcus:MSI:AzureServicesAuth:ConnectionString");
            var notExistingSecretName  = $"secret-{Guid.NewGuid():N}";
            var keyVaultSecretProvider = new KeyVaultSecretProvider(
                authentication: new ManagedServiceIdentityAuthentication(),
                vaultConfiguration: new KeyVaultConfiguration(keyVaultUri));

            using (TemporaryEnvironmentVariable.Create(KeyVaultConnectionStringEnvironmentVariable, connectionString))
            {
                // Assert
                await Assert.ThrowsAsync <SecretNotFoundException>(async() =>
                {
                    // Act
                    await keyVaultSecretProvider.GetSecretAsync(notExistingSecretName);
                });
            }
        }
        public async Task KeyVaultSecretProvider_WithDefaultManagedServiceIdentity_GetSecret_Succeeds()
        {
            // Arrange
            var keyVaultUri            = Configuration.GetValue <string>("Arcus:KeyVault:Uri");
            var connectionString       = Configuration.GetValue <string>("Arcus:MSI:AzureServicesAuth:ConnectionString");
            var secretName             = Configuration.GetValue <string>("Arcus:KeyVault:TestKeyName");
            var keyVaultSecretProvider = new KeyVaultSecretProvider(
                authentication: new ManagedServiceIdentityAuthentication(),
                vaultConfiguration: new KeyVaultConfiguration(keyVaultUri));

            using (TemporaryEnvironmentVariable.Create(KeyVaultConnectionStringEnvironmentVariable, connectionString))
            {
                // Act
                Secret secret = await keyVaultSecretProvider.GetSecretAsync(secretName);

                // Assert
                Assert.NotNull(secret);
                Assert.NotNull(secret.Value);
                Assert.NotNull(secret.Version);
            }
        }
Esempio n. 14
0
        public async Task LogEventWithKubernetesInfo_SinksToApplicationInsights_ResultsInTelemetryWithKubernetesInfo()
        {
            // Arrange
            string nodeName   = $"node-{Guid.NewGuid()}";
            string podName    = $"pod-{Guid.NewGuid()}";
            string @namespace = $"namespace-{Guid.NewGuid()}";
            var    message    = "This message will have Kubernetes information";

            using (TemporaryEnvironmentVariable.Create(KubernetesEnricher.NodeNameVariable, nodeName))
                using (TemporaryEnvironmentVariable.Create(KubernetesEnricher.PodNameVariable, podName))
                    using (TemporaryEnvironmentVariable.Create(KubernetesEnricher.NamespaceVariable, @namespace))
                        using (ILoggerFactory loggerFactory = CreateLoggerFactory(config => config.Enrich.WithKubernetesInfo()))
                        {
                            ILogger logger = loggerFactory.CreateLogger <ApplicationInsightsSinkTests>();

                            // Act
                            logger.LogInformation(message);
                        }

            // Assert
            using (ApplicationInsightsDataClient client = CreateApplicationInsightsClient())
            {
                await RetryAssertUntilTelemetryShouldBeAvailableAsync(async() =>
                {
                    EventsResults <EventsTraceResult> traceEvents = await client.Events.GetTraceEventsAsync(ApplicationId, filter: OnlyLastHourFilter);
                    Assert.Contains(traceEvents.Value, trace =>
                    {
                        return(message == trace.Trace.Message &&
                               trace.CustomDimensions.TryGetValue(ContextProperties.Kubernetes.NodeName, out string actualNodeName) &&
                               nodeName == actualNodeName &&
                               trace.CustomDimensions.TryGetValue(ContextProperties.Kubernetes.PodName, out string actualPodName) &&
                               podName == actualPodName &&
                               trace.CustomDimensions.TryGetValue(ContextProperties.Kubernetes.Namespace, out string actualNamespace) &&
                               @namespace == actualNamespace);
                    });
                });
            }
        }
Esempio n. 15
0
        public void LogEventWithCustomNamespacePropertyName_WithKubernetesEnricher_HasEnvironmentInformation()
        {
            // Arrange
            string  expected     = $"namespace-{Guid.NewGuid()}";
            string  propertyName = $"namespace-name-{Guid.NewGuid():N}";
            var     spy          = new InMemoryLogSink();
            ILogger logger       = new LoggerConfiguration()
                                   .Enrich.WithKubernetesInfo(namespacePropertyName: propertyName)
                                   .WriteTo.Sink(spy)
                                   .CreateLogger();

            using (TemporaryEnvironmentVariable.Create(NamespaceVariable, expected))
            {
                // Act
                logger.Information("This log event should contain the custom configured Kubernetes property");
            }

            // Assert
            LogEvent logEvent = Assert.Single(spy.CurrentLogEmits);

            Assert.NotNull(logEvent);
            Assert.True(logEvent.ContainsProperty(propertyName, expected), $"Log event contain property '{propertyName}' with value '{expected}'");
        }
        public async Task ConfigureSecretStore_AddEnvironmentVariablesWithDotsToUpperAndUnderscores_FindsEnvironmentVariable()
        {
            // Arrange
            string expected = $"secret-{Guid.NewGuid()}";
            var    builder  = new HostBuilder();

            using (TemporaryEnvironmentVariable.Create("ARCUS_ENVIRONMENT_SECRET", expected))
            {
                // Act
                builder.ConfigureSecretStore((config, stores) =>
                {
                    stores.AddEnvironmentVariables(mutateSecretName: name => name.ToUpper().Replace(".", "_"));
                });

                // Assert
                IHost host     = builder.Build();
                var   provider = host.Services.GetRequiredService <ISecretProvider>();

                string actual = await provider.GetRawSecretAsync("Arcus.Environment.Secret");

                Assert.Equal(expected, actual);
            }
        }
        public async Task ConfigureSecretStore_AddEnvironmentVariablesWithPrefix_UsesEnvironmentVariableSecrets()
        {
            // Arrange
            string prefix    = "ARCUS_";
            string secretKey = prefix + "MySecret";
            string expected  = $"secret-{Guid.NewGuid()}";

            var builder = new HostBuilder();

            using (TemporaryEnvironmentVariable.Create(secretKey, expected))
            {
                // Act
                builder.ConfigureSecretStore((config, stores) => stores.AddEnvironmentVariables(prefix: prefix));

                // Assert
                IHost host     = builder.Build();
                var   provider = host.Services.GetRequiredService <ISecretProvider>();

                string nonPrefixedSecret = secretKey.Substring(prefix.Length);
                string actual            = await provider.GetRawSecretAsync(nonPrefixedSecret);

                Assert.Equal(expected, actual);
            }
        }