Esempio n. 1
0
        public override async Task <CreateLdapCredentialReply> CreateLdapCredential(CreateLdapCredentialRequest request, ServerCallContext context)
        {
            Guid appId  = new Guid(request.Id);
            Guid userId = new Guid(_userManager.GetUserId(context.GetHttpContext().User));

            LdapAppSettings ldapAppSettings = await _authDbContext.LdapAppSettings
                                              .Where(a => a.AuthApp.UserGroups.Any(u => u.Members.Any(m => m.Id == userId)))
                                              .SingleAsync(l => l.AuthApp.Id == appId);

            AppUser user = await _userManager.GetUserAsync(context.GetHttpContext().User);

            string plainTextPassword = _secureRandom.GetRandomString(16);
            string hashedPassword    = _hasher.Hash(plainTextPassword);

            LdapAppUserCredentials credentials = new LdapAppUserCredentials
            {
                HashedPassword  = hashedPassword,
                LdapAppSettings = ldapAppSettings,
                User            = user,
            };

            _authDbContext.Add(credentials);
            await _authDbContext.SaveChangesAsync();

            return(new CreateLdapCredentialReply {
                Password = plainTextPassword
            });
        }
Esempio n. 2
0
        public override async Task <StartSetupReply> StartSetup(Empty request, ServerCallContext context)
        {
            bool isInstalled = await IsAlreadyInstalled();

            string?existingAuthKey = await GetSetupAuthKey();

            if (isInstalled || existingAuthKey != null)
            {
                return(new StartSetupReply
                {
                    Success = false,
                });
            }

            string        newAuthKey     = _secureRandom.GetRandomString(16);
            SystemSetting authKeySetting = new SystemSetting
            {
                Name  = AUTH_KEY,
                Value = newAuthKey,
            };

            _authDbContext.Add(authKeySetting);
            await _authDbContext.SaveChangesAsync();

            return(new StartSetupReply
            {
                Success = true,
                AuthToken = newAuthKey,
            });
        }
Esempio n. 3
0
        private async Task <string> SetNewAuthToken()
        {
            SystemSetting?authKeySetting = await _authDbContext.SystemSettings
                                           .SingleOrDefaultAsync(s => s.Name == AUTH_KEY);

            string newAuthKey = _secureRandom.GetRandomString(16);

            if (authKeySetting == null)
            {
                authKeySetting = new SystemSetting
                {
                    Name = AUTH_KEY,
                };
                _authDbContext.Add(authKeySetting);
            }
            authKeySetting.Value = newAuthKey;

            await _authDbContext.SaveChangesAsync();

            return(newAuthKey);
        }
Esempio n. 4
0
        public override async Task <AddNewAppReply> AddNewApp(AddNewAppRequest request, ServerCallContext context)
        {
            AuthApp app = new AuthApp
            {
                Name        = request.Name,
                Url         = request.Url,
                Description = request.Description,
            };

            _authDbContext.Add(app);

            switch (request.HostingType)
            {
            case HostingType.NonWeb:
                app.HostingType = AuthApp.HostingTypeEnum.NON_WEB;
                break;

            case HostingType.WebGatekeeperProxy:
                app.HostingType = AuthApp.HostingTypeEnum.WEB_GATEKEEPER_PROXY;
                break;

            case HostingType.WebGeneric:
                app.HostingType = AuthApp.HostingTypeEnum.WEB_GENERIC;
                break;

            default:
                throw new NotImplementedException("Auth mode is not implemented");
            }

            switch (request.DirectoryChoice)
            {
            case AddNewAppRequest.Types.DirectoryChoice.NoneDirectory:
                app.DirectoryMethod = AuthApp.DirectoryMethodEnum.NONE;
                break;

            case AddNewAppRequest.Types.DirectoryChoice.LdapDirectory:
                app.DirectoryMethod = AuthApp.DirectoryMethodEnum.LDAP;
                break;

            case AddNewAppRequest.Types.DirectoryChoice.ScimDirectory:
                app.DirectoryMethod = AuthApp.DirectoryMethodEnum.SCIM;
                break;
            }

            switch (request.AuthChoice)
            {
            case AddNewAppRequest.Types.AuthChoice.LdapAuth:
                app.AuthMethod = AuthApp.AuthMethodEnum.LDAP;
                break;

            case AddNewAppRequest.Types.AuthChoice.OidcAuth:
                app.AuthMethod = AuthApp.AuthMethodEnum.OIDC;
                break;
            }

            if (app.AuthMethod == AuthApp.AuthMethodEnum.LDAP || app.DirectoryMethod == AuthApp.DirectoryMethodEnum.LDAP)
            {
                string assembledBaseDn  = "dc=" + app.Id;
                string bindUserPassword = _ldapSettingsDataProtector.Protect(_secureRandom.GetRandomString(16));
                string bindUser         = "******" + assembledBaseDn;

                LdapAppSettings ldapAppSettings = new LdapAppSettings
                {
                    AuthApp = app,
                    UseForAuthentication = (app.AuthMethod == AuthApp.AuthMethodEnum.LDAP),
                    UseForIdentity       = (app.DirectoryMethod == AuthApp.DirectoryMethodEnum.LDAP),
                    BaseDn           = assembledBaseDn,
                    BindUser         = bindUser,
                    BindUserPassword = bindUserPassword,
                };

                _authDbContext.Add(ldapAppSettings);
                app.LdapAppSettings = ldapAppSettings;
            }

            if (app.HostingType == AuthApp.HostingTypeEnum.WEB_GATEKEEPER_PROXY)
            {
                ProxyAppSettings proxyAppSettings = new ProxyAppSettings
                {
                    AuthApp          = app,
                    InternalHostname = request.ProxySetting.InternalHostname,
                    PublicHostname   = request.ProxySetting.PublicHostname,
                };
                _authDbContext.Add(proxyAppSettings);
                app.ProxyAppSettings = proxyAppSettings;

                _configurationProvider.TryGet("tls.acme.support", out string isAcmeSupported);
                if (isAcmeSupported == "true")
                {
                    // FIXME: Passing an empty email is a hack here. The email is already passed in InstallService. Could be refactored.
                    BackgroundJob.Enqueue <IRequestAcmeCertificateJob>(job => job.Request("", request.ProxySetting.PublicHostname));
                }
            }

            if (app.AuthMethod == AuthApp.AuthMethodEnum.OIDC)
            {
                OIDCAppSettings oidcAppSettings = new OIDCAppSettings
                {
                    RedirectUrl  = request.OidcSetting.RedirectUri,
                    AuthApp      = app,
                    ClientId     = Guid.NewGuid().ToString(),
                    ClientSecret = _secureRandom.GetRandomString(32),
                    Audience     = "FIX_ME",
                };
                _authDbContext.Add(oidcAppSettings);
                app.OidcAppSettings = oidcAppSettings;
            }

            if (app.DirectoryMethod == AuthApp.DirectoryMethodEnum.SCIM)
            {
                SCIMAppSettings scimAppSettings = new SCIMAppSettings
                {
                    AuthApp     = app,
                    Endpoint    = request.ScimSetting.Endpoint,
                    Credentials = request.ScimSetting.Credentials,
                };
                _authDbContext.Add(scimAppSettings);
                app.ScimAppSettings = scimAppSettings;
            }

            foreach (string groupId in request.GroupIds)
            {
                Guid      groupIdGuid = new Guid(groupId);
                UserGroup group       = await _authDbContext.UserGroup
                                        .Include(g => g.AuthApps)
                                        .SingleAsync(g => g.Id == groupIdGuid);

                group.AuthApps.Add(app);
            }

            await _authDbContext.SaveChangesAsync();

            // fixme: this should be done outside a service
            await _memoryPopulator.PopulateFromDatabase();

            return(new AddNewAppReply
            {
                Success = true,
            });
        }
Esempio n. 5
0
        public async Task Invoke(
            HttpContext context,
            AuthenticationManager authenticationManager,
            SingleSignOnHandler singleSignOnHandler,
            ConfigurationProvider configurationProvider,
            SecureRandom secureRandom
            )
        {
            MemorySingletonProxyConfigProvider.Route?route = GetMatchingRoute(context);

            if (route != null)
            {
                bool shouldHandle = true;

                PathString requestPath = context.Request.Path;
                if (requestPath.StartsWithSegments("/.well-known/acme-challenge"))
                {
                    string challenge = ((string)requestPath).Split('/').Last();
                    if (_acmeChallengeSingleton.Challenges.ContainsKey(challenge))
                    {
                        shouldHandle = false;
                    }
                }

                if (shouldHandle)
                {
                    configurationProvider.TryGet(AuthServer.Server.GRPC.InstallService.PRIMARY_DOMAIN_KEY, out string primaryDomain);

                    bool isAuthRequest = singleSignOnHandler.IsAuthRequest(context);
                    if (isAuthRequest)
                    {
                        singleSignOnHandler.Handle(context);
                        return;
                    }

                    bool isPublicEndpoint = route.PublicRoutes.Contains(context.Request.Path);

                    if (!isPublicEndpoint)
                    {
                        bool isAuthenticated = authenticationManager.IsAuthenticated(context, out Guid? sessionId);

                        if (!isAuthenticated)
                        {
                            string csrf = secureRandom.GetRandomString(16);
                            context.Response.Cookies.Append("gatekeeper.csrf", csrf);

                            Dictionary <string, string> queryDictionary = new Dictionary <string, string>()
                            {
                                { "id", route.ProxySettingId.ToString() },
                                { "csrf", csrf },
                            };

                            UriBuilder uriBuilder = new UriBuilder();
                            uriBuilder.Scheme = "https";
                            uriBuilder.Host   = primaryDomain;
                            uriBuilder.Path   = "/auth/sso-connect";
                            uriBuilder.Query  = await((new System.Net.Http.FormUrlEncodedContent(queryDictionary)).ReadAsStringAsync());

                            context.Response.Redirect(uriBuilder.ToString(), false);
                            return;
                        }
                        else
                        {
                            if (sessionId == null)
                            {
                                // This should never happen
                                return;
                            }

                            bool isAuthorized = await authenticationManager.IsAuthorizedAsync((Guid)sessionId, route);

                            if (!isAuthorized)
                            {
                                context.Response.Redirect("https://" + primaryDomain + "/auth/403");
                                return;
                            }
                        }
                    }

                    Dictionary <string, RequestHeaderTransform> requestHeaderTransforms = new Dictionary <string, RequestHeaderTransform>()
                    {
                        {
                            "X-Forwarded-For",
                            new RequestHeaderValueTransform(context.Connection.RemoteIpAddress.ToString(), append: false)
                        },
                        {
                            "X-Forwarded-Host",
                            new RequestHeaderValueTransform(route.PublicHostname, append: false)
                        },
                        {
                            HeaderNames.Host,
                            new RequestHeaderValueTransform(String.Empty, append: false)
                        }
                    };

                    if (context.Request.Cookies.TryGetValue(AuthenticationManager.AUTH_COOKIE, out string?authCookieValue))
                    {
                        // FIXME: This is currently also sent as cookie. Remove this and only send it as header.
                        requestHeaderTransforms.Add(
                            "X-Gatekeeper-Jwt-Assertion",
                            new RequestHeaderValueTransform(authCookieValue, append: false)
                            );
                    }

                    RequestProxyOptions proxyOptions = new RequestProxyOptions()
                    {
                        RequestTimeout = TimeSpan.FromSeconds(100),
                        Transforms     = new Transforms(
                            copyRequestHeaders: true,
                            requestTransforms: Array.Empty <RequestParametersTransform>(),
                            requestHeaderTransforms: requestHeaderTransforms,
                            responseHeaderTransforms: new Dictionary <string, ResponseHeaderTransform>(),
                            responseTrailerTransforms: new Dictionary <string, ResponseHeaderTransform>()
                            )
                    };

                    await _httpProxy.ProxyAsync(context, route.InternalHostname, _httpClient, proxyOptions);

                    return;
                }
            }

            await _nextMiddleware(context);
        }
Esempio n. 6
0
        public void TestGetRandomString()
        {
            SecureRandom random = new SecureRandom();

            Assert.Equal(23, random.GetRandomString(23).Length);
        }
Esempio n. 7
0
        public async Task Invoke(
            HttpContext context,
            AuthenticationManager authenticationManager,
            SingleSignOnHandler singleSignOnHandler,
            ConfigurationProvider configurationProvider,
            SecureRandom secureRandom
            )
        {
            MemorySingletonProxyConfigProvider.Route?route = GetMatchingRoute(context);

            if (route != null)
            {
                bool shouldHandle = true;

                PathString requestPath = context.Request.Path;
                if (requestPath.StartsWithSegments("/.well-known/acme-challenge"))
                {
                    string challenge = ((string)requestPath).Split('/').Last();
                    if (_acmeChallengeSingleton.Challenges.ContainsKey(challenge))
                    {
                        shouldHandle = false;
                    }
                }

                if (shouldHandle)
                {
                    configurationProvider.TryGet(AuthServer.Server.GRPC.InstallService.PRIMARY_DOMAIN_KEY, out string primaryDomain);

                    bool isAuthRequest = singleSignOnHandler.IsAuthRequest(context);
                    if (isAuthRequest)
                    {
                        singleSignOnHandler.Handle(context);
                        return;
                    }

                    bool isPublicEndpoint = route.PublicRoutes.Contains(context.Request.Path);

                    if (!isPublicEndpoint)
                    {
                        bool isAuthenticated = authenticationManager.IsAuthenticated(context, out Guid? sessionId);

                        if (!isAuthenticated)
                        {
                            string csrf = secureRandom.GetRandomString(16);
                            context.Response.Cookies.Append("gatekeeper.csrf", csrf);

                            Dictionary <string, string> queryDictionary = new Dictionary <string, string>()
                            {
                                { "id", route.ProxySettingId.ToString() },
                                { "csrf", csrf },
                            };

                            UriBuilder uriBuilder = new UriBuilder();
                            uriBuilder.Scheme = "https";
                            uriBuilder.Host   = primaryDomain;
                            uriBuilder.Path   = "/auth/sso-connect";
                            uriBuilder.Query  = await((new System.Net.Http.FormUrlEncodedContent(queryDictionary)).ReadAsStringAsync());

                            context.Response.Redirect(uriBuilder.ToString(), false);
                            return;
                        }
                        else
                        {
                            if (sessionId == null)
                            {
                                // This should never happen
                                return;
                            }

                            bool isAuthorized = await authenticationManager.IsAuthorizedAsync((Guid)sessionId, route);

                            if (!isAuthorized)
                            {
                                context.Response.Redirect("https://" + primaryDomain + "/auth/403");
                                return;
                            }
                        }
                    }

                    RequestProxyOptions proxyOptions = new RequestProxyOptions(
                        TimeSpan.FromSeconds(100),
                        null
                        );

                    await _httpProxy.ProxyAsync(
                        context,
                        route.InternalHostname,
                        _httpClient,
                        proxyOptions,
                        new Gatekeeper.Server.Web.Services.ReverseProxy.Transformer.RequestTransformer(route)
                        );

                    return;
                }
            }

            await _nextMiddleware(context);
        }