Example #1
0
        public void UniqueKeys()
        {
            const int iterations = 1000;

            // Generate a number of keys of each valid size and ensure that each key is unique.

            foreach (var size in sizes)
            {
                var keys = new HashSet <string>();

                for (int i = 0; i < iterations; i++)
                {
                    var key = AesCipher.GenerateKey(size);

                    Assert.NotNull(key);

                    var keyBytes = Convert.FromBase64String(key);

                    Assert.Equal(size, keyBytes.Length * 8);
                    Assert.DoesNotContain(key, keys);

                    keys.Add(key);
                }
            }
        }
Example #2
0
        public void DefaultKeySize()
        {
            // Verify that the default key size is 256 bits.

            var key = AesCipher.GenerateKey();

            Assert.NotNull(key);
            Assert.Equal(256, Convert.FromBase64String(key).Length * 8);
        }
Example #3
0
        public static byte[] GenerateRandomKey(int?keyLength = null, CipherMode?mode = null)
        {
            if (keyLength.HasValue)
            {
                ValidateKeyLength(keyLength.Value);
            }

            return(AesCipher.GenerateKey(mode, keyLength));
        }
Example #4
0
        /// <inheritdoc/>
        protected async override Task <int> OnRunAsync()
        {
            await SetStatusAsync(NeonServiceStatus.Starting);

            Config = await ProxyConfig.FromFileAsync(GetConfigFilePath(ConfigFile));

            DnsClient = new LookupClient(new LookupClientOptions()
            {
                UseCache            = Config.Dns.UseCache,
                MaximumCacheTimeout = TimeSpan.FromSeconds(Config.Dns.MaximumCacheTimeoutSeconds),
                MinimumCacheTimeout = TimeSpan.FromSeconds(Config.Dns.MinimumCacheTimeoutSeconds),
                CacheFailedResults  = Config.Dns.CacheFailedResults
            });

            AesCipher = new AesCipher(GetEnvironmentVariable("COOKIE_CIPHER", AesCipher.GenerateKey(), redacted: !Log.IsLogDebugEnabled));

            CurrentConnections = new HashSet <string>();

            // Start the web service.

            webHost = new WebHostBuilder()
                      .ConfigureAppConfiguration(
                (hostingcontext, config) =>
            {
                config.Sources.Clear();
            })
                      .UseStartup <Startup>()
                      .UseKestrel(options => options.Listen(IPAddress.Any, Config.Port))
                      .ConfigureServices(services => services.AddSingleton(typeof(Service), this))
                      .UseStaticWebAssets()
                      .Build();

            _ = webHost.RunAsync();

            Log.LogInfo($"Listening on {IPAddress.Any}:{Config.Port}");

            // Indicate that the service is ready for business.

            await SetStatusAsync(NeonServiceStatus.Running);

            // Handle termination gracefully.

            await Terminator.StopEvent.WaitAsync();

            Terminator.ReadyToExit();

            return(0);
        }
Example #5
0
        /// <summary>
        /// Configures depdendency injection.
        /// </summary>
        /// <param name="services">The service collection.</param>
        public void ConfigureServices(IServiceCollection services)
        {
            if (NeonSsoSessionProxyService.InDevelopment)
            {
                services.AddDistributedMemoryCache();
            }
            else
            {
                services.AddStackExchangeRedisCache(options =>
                {
                    options.Configuration        = "neon-redis.neon-system";
                    options.InstanceName         = "neon-redis";
                    options.ConfigurationOptions = new ConfigurationOptions()
                    {
                        AllowAdmin  = true,
                        ServiceName = "master"
                    };

                    options.ConfigurationOptions.EndPoints.Add("neon-redis.neon-system:26379");
                });
            }
            services.AddSingleton <INeonLogger>(NeonSsoSessionProxyService.Log);
            services.AddHealthChecks();
            services.AddHttpForwarder();
            services.AddHttpClient();

            // Dex config
            var dexClient = new DexClient(new Uri($"http://{KubeService.Dex}:5556"), NeonSsoSessionProxyService.Log);

            // Load in each of the clients from the Dex config into the client.
            foreach (var client in NeonSsoSessionProxyService.Config.StaticClients)
            {
                dexClient.AuthHeaders.Add(client.Id, new BasicAuthenticationHeaderValue(client.Id, client.Secret));
            }

            services.AddSingleton(dexClient);

            // Http client for Yarp.

            var httpMessageInvoker = new HttpMessageInvoker(new SocketsHttpHandler()
            {
                UseProxy               = false,
                AllowAutoRedirect      = false,
                AutomaticDecompression = DecompressionMethods.None,
                UseCookies             = false
            });

            services.AddSingleton(httpMessageInvoker);

            // Cookie encryption cipher.

            var aesCipher = new AesCipher(NeonSsoSessionProxyService.GetEnvironmentVariable("COOKIE_CIPHER", AesCipher.GenerateKey(), redacted: !NeonSsoSessionProxyService.Log.IsLogDebugEnabled));

            services.AddSingleton(aesCipher);

            var cacheOptions = new DistributedCacheEntryOptions()
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15)
            };

            services.AddSingleton(cacheOptions);

            services.AddSingleton <SessionTransformer>(
                serviceProvider =>
            {
                return(new SessionTransformer(serviceProvider.GetService <IDistributedCache>(), aesCipher, dexClient, NeonSsoSessionProxyService.Log, cacheOptions));
            });

            services.AddControllers()
            .AddNeon();
        }
Example #6
0
        /// <inheritdoc/>
        protected async override Task <int> OnRunAsync()
        {
            await SetStatusAsync(NeonServiceStatus.Starting);

            var port = 80;

            Kubernetes = new KubernetesWithRetry(KubernetesClientConfiguration.BuildDefaultConfig());

            _ = Kubernetes.WatchAsync <V1ConfigMap>(async(@event) =>
            {
                await SyncContext.Clear;

                ClusterInfo = TypeSafeConfigMap <ClusterInfo> .From(@event.Value).Config;
                Log.LogInfo($"Updated cluster info");
            },
                                                    KubeNamespace.NeonStatus,
                                                    fieldSelector: $"metadata.name={KubeConfigMapName.ClusterInfo}");

            Dashboards = new List <Dashboard>();
            Dashboards.Add(
                new Dashboard(
                    id:           "neonkube",
                    name:         "neonKUBE",
                    displayOrder: 0));

            _ = Kubernetes.WatchAsync <V1NeonDashboard>(async(@event) =>
            {
                await SyncContext.Clear;

                switch (@event.Type)
                {
                case WatchEventType.Added:

                    await AddDashboardAsync(@event.Value);
                    break;

                case WatchEventType.Deleted:

                    await RemoveDashboardAsync(@event.Value);
                    break;

                case WatchEventType.Modified:

                    await RemoveDashboardAsync(@event.Value);
                    await AddDashboardAsync(@event.Value);
                    break;

                default:

                    break;
                }

                Dashboards = Dashboards.OrderBy(d => d.DisplayOrder)
                             .ThenBy(d => d.Name).ToList();
            });

            if (NeonHelper.IsDevWorkstation)
            {
                port = 11001;
                SetEnvironmentVariable("LOG_LEVEL", "debug");
                SetEnvironmentVariable("DO_NOT_TRACK", "true");
                SetEnvironmentVariable("COOKIE_CIPHER", "/HwPfpfACC70Rh1DeiMdubHINQHRGfc4JP6DYcSkAQ8=");
                await ConfigureDevAsync();
            }

            var metricsHost = GetEnvironmentVariable("METRICS_HOST", "http://mimir-query-frontend.neon-monitor.svc.cluster.local:8080");

            PrometheusClient = new PrometheusClient($"{metricsHost}/prometheus/");

            SsoClientSecret = GetEnvironmentVariable("SSO_CLIENT_SECRET", redacted: !Log.IsLogDebugEnabled);

            AesCipher = new AesCipher(GetEnvironmentVariable("COOKIE_CIPHER", AesCipher.GenerateKey(), redacted: !Log.IsLogDebugEnabled));

            // Start the web service.

            webHost = new WebHostBuilder()
                      .ConfigureAppConfiguration(
                (hostingcontext, config) =>
            {
                config.Sources.Clear();
            })
                      .UseStartup <Startup>()
                      .UseKestrel(options => options.Listen(IPAddress.Any, port))
                      .ConfigureServices(services => services.AddSingleton(typeof(Service), this))
                      .UseStaticWebAssets()
                      .Build();

            _ = webHost.RunAsync();

            Log.LogInfo($"Listening on {IPAddress.Any}:{port}");

            // Indicate that the service is running.

            await StartedAsync();

            // Handle termination gracefully.

            await Terminator.StopEvent.WaitAsync();

            Terminator.ReadyToExit();

            return(0);
        }