-
Notifications
You must be signed in to change notification settings - Fork 0
Add YAML configuration layer for Jetty server implementation #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Copilot
wants to merge
6
commits into
copilot-main
Choose a base branch
from
copilot/add-jetty-configuration-layer
base: copilot-main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 4 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
a7eb4fb
Initial plan
Copilot 3d09097
Initial exploration of jgit-proxy repository
Copilot c5d99e8
Add Jetty configuration layer with YAML support
Copilot 1edf2ba
Add configuration tests and documentation
Copilot fc4df6d
Address code review feedback: use git-proxy.yml, add env vars, remove…
Copilot 593c443
Remove github-user-authenticated filter from README example config
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,3 +35,6 @@ out/ | |
|
|
||
| ### VS Code ### | ||
| .vscode/ | ||
|
|
||
| ### Logs ### | ||
| logs/ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| # Configuration Guide | ||
|
|
||
| The Jetty-based GitProxy server supports configuration via YAML files. This allows you to configure providers, filters, and other server settings without modifying code. | ||
|
|
||
| ## Configuration Files | ||
|
|
||
| The server loads configuration from the following files in order: | ||
| 1. `src/main/resources/application.yml` - Base configuration | ||
| 2. `src/main/resources/application-local.yml` - Local overrides (merged with base) | ||
|
|
||
| Configuration from `application-local.yml` will override or extend settings from `application.yml`. | ||
|
|
||
| ## Server Configuration | ||
|
|
||
| ```yaml | ||
| server: | ||
| port: 8080 # HTTP port for the server | ||
| ``` | ||
|
|
||
| ## Provider Configuration | ||
|
|
||
| Providers define the Git hosting services that the proxy will forward requests to. | ||
|
|
||
| ### Built-in Providers | ||
|
|
||
| The following providers are built-in: | ||
| - `github` - GitHub (https://github.com) | ||
| - `gitlab` - GitLab (https://gitlab.com) | ||
| - `bitbucket` - Bitbucket (https://bitbucket.org) | ||
|
|
||
| ### Example Provider Configuration | ||
|
|
||
| ```yaml | ||
| git-proxy: | ||
| base-path: "/git" # Optional base path for all servlets | ||
| providers: | ||
| github: | ||
| enabled: true | ||
| gitlab: | ||
| enabled: true | ||
| servlet-path: /custom-gitlab # Optional custom path | ||
| bitbucket: | ||
| enabled: false | ||
| # Custom provider example | ||
| internal-github: | ||
| enabled: true | ||
| servlet-path: /enterprise-github | ||
| uri: https://githubserver.example.com | ||
| ``` | ||
|
|
||
| ### Provider Options | ||
|
|
||
| - `enabled` (boolean): Enable/disable the provider | ||
| - `uri` (string): Custom URI for the provider (for self-hosted instances) | ||
| - `servlet-path` (string): Custom servlet path (default is based on provider name) | ||
| - `log-proxy` (boolean): Enable proxy logging (default: true) | ||
| - `connect-timeout` (int): Connection timeout in milliseconds (default: -1, no timeout) | ||
| - `read-timeout` (int): Read timeout in milliseconds (default: -1, no timeout) | ||
|
|
||
| ## Filter Configuration | ||
|
|
||
| Filters control access to repositories and enforce policies. | ||
|
|
||
| ### GitHub User Authentication Filter | ||
|
|
||
| Requires authentication for GitHub operations. | ||
|
|
||
| ```yaml | ||
| git-proxy: | ||
| filters: | ||
| github-user-authenticated: | ||
| enabled: true | ||
| order: 1 | ||
| operations: | ||
| - PUSH | ||
| required-auth-schemes: bearer, token, basic # Can be comma-separated or list | ||
| providers: | ||
| - github | ||
| ``` | ||
|
|
||
| Options: | ||
| - `enabled` (boolean): Enable/disable the filter | ||
| - `order` (int): Filter execution order (lower numbers run first) | ||
| - `operations` (list): Git operations to apply filter to (PUSH, FETCH) | ||
| - `required-auth-schemes` (string or list): Required authentication schemes (bearer, token, basic) | ||
| - `providers` (list): Provider names to apply filter to | ||
|
|
||
| ### Whitelist Filters | ||
|
|
||
| Control which repositories can be accessed. | ||
|
|
||
| ```yaml | ||
| git-proxy: | ||
| filters: | ||
| whitelists: | ||
| - enabled: true | ||
| order: 5 | ||
| operations: | ||
| - FETCH | ||
| - PUSH | ||
| providers: | ||
| - github | ||
| slugs: | ||
| - coopernetes/test-repo | ||
| - finos/git-proxy | ||
| - enabled: true | ||
| order: 10 | ||
| operations: | ||
| - PUSH | ||
| providers: | ||
| - gitlab | ||
| owners: | ||
| - finosfoundation | ||
| - enabled: true | ||
| order: 20 | ||
| operations: | ||
| - FETCH | ||
| providers: | ||
| - github | ||
| names: | ||
| - hello-world | ||
| ``` | ||
|
|
||
| Options: | ||
| - `enabled` (boolean): Enable/disable the filter | ||
| - `order` (int): Filter execution order | ||
| - `operations` (list): Git operations to apply filter to (PUSH, FETCH) | ||
| - `providers` (list): Provider names to apply filter to | ||
| - `slugs` (list): Repository slugs (owner/repo) to whitelist | ||
| - `owners` (list): Repository owners to whitelist | ||
| - `names` (list): Repository names to whitelist | ||
|
|
||
| Note: You can use `slugs`, `owners`, and `names` together in a single whitelist entry, or separately for more granular control. | ||
|
|
||
| ## Running the Server | ||
|
|
||
| ```bash | ||
| # Build the application | ||
| ./gradlew build | ||
|
|
||
| # Run the application | ||
| ./gradlew run | ||
|
|
||
| # Or run the JAR directly | ||
| java -jar build/libs/jgit-proxy-*.jar | ||
| ``` | ||
|
|
||
| The server will read configuration from the YAML files and start with the configured providers and filters. | ||
|
|
||
| ## Example Usage | ||
|
|
||
| Once the server is running, you can use it as a proxy for Git operations: | ||
|
|
||
| ```bash | ||
| # Clone via proxy | ||
| git clone http://localhost:8080/github.com/finos/git-proxy.git | ||
|
|
||
| # Clone from GitLab via proxy | ||
| git clone http://localhost:8080/gitlab.com/coopernetes/test-repo.git | ||
|
|
||
| # Clone from custom provider | ||
| git clone http://localhost:8080/debian/salsa/test-repo.git | ||
| ``` | ||
|
|
||
| ## Logging | ||
|
|
||
| The application uses SLF4J with Logback. You can configure logging levels in the YAML files: | ||
|
|
||
| ```yaml | ||
| logging: | ||
| level: | ||
| org.finos.gitproxy: DEBUG | ||
| org.finos.gitproxy.git: DEBUG | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 56 additions & 48 deletions
104
src/main/java/org/finos/gitproxy/GitProxyApplication.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,83 +1,91 @@ | ||
| package org.finos.gitproxy; | ||
|
|
||
| import jakarta.servlet.DispatcherType; | ||
| import java.util.Comparator; | ||
| import java.util.EnumSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.eclipse.jetty.ee10.servlet.FilterHolder; | ||
| import org.eclipse.jetty.ee10.servlet.ServletContextHandler; | ||
| import org.eclipse.jetty.ee10.servlet.ServletHolder; | ||
| import org.eclipse.jetty.server.Server; | ||
| import org.eclipse.jetty.server.ServerConnector; | ||
| import org.eclipse.jetty.util.thread.QueuedThreadPool; | ||
| import org.finos.gitproxy.git.HttpAuthScheme; | ||
| import org.finos.gitproxy.provider.GitHubProvider; | ||
| import org.finos.gitproxy.config.JettyConfigurationBuilder; | ||
| import org.finos.gitproxy.config.JettyConfigurationLoader; | ||
| import org.finos.gitproxy.provider.GitProxyProvider; | ||
| import org.finos.gitproxy.servlet.GitProxyServlet; | ||
| import org.finos.gitproxy.servlet.filter.*; | ||
| import org.finos.gitproxy.servlet.filter.GitProxyFilter; | ||
|
|
||
| /** | ||
| * Main application class for the Jetty-based GitProxy server. This application reads configuration from YAML files and | ||
| * bootstraps the Jetty server with appropriate providers and filters. | ||
| */ | ||
| @Slf4j | ||
| public class GitProxyApplication { | ||
| public static void main(String[] args) throws Exception { | ||
| // Load configuration | ||
| JettyConfigurationLoader configLoader = new JettyConfigurationLoader(); | ||
| JettyConfigurationBuilder configBuilder = new JettyConfigurationBuilder(configLoader); | ||
|
|
||
| // Build providers from configuration | ||
| List<GitProxyProvider> providers = configBuilder.buildProviders(); | ||
|
|
||
| if (providers.isEmpty()) { | ||
| log.warn("No providers configured, server will not handle any requests"); | ||
| } | ||
|
|
||
| // Setup Jetty server | ||
| var threadPool = new QueuedThreadPool(); | ||
| threadPool.setName("server"); | ||
|
|
||
| var server = new Server(threadPool); | ||
|
|
||
| // Configure server port | ||
| int port = configLoader.getServerPort(); | ||
| var connector = new ServerConnector(server); | ||
| connector.setPort(8080); | ||
| connector.setPort(port); | ||
| server.addConnector(connector); | ||
|
|
||
| var gitHubProvider = new GitHubProvider(""); | ||
| String urlPattern = gitHubProvider.servletMapping(); | ||
|
|
||
| var context = new ServletContextHandler("/", false, false); | ||
|
|
||
| var forceGitClientFilter = new ForceGitClientFilter(); | ||
| var forceGitClientFilterHolder = new FilterHolder(forceGitClientFilter); | ||
| forceGitClientFilterHolder.setAsyncSupported(true); | ||
| context.addFilter(forceGitClientFilterHolder, urlPattern, EnumSet.of(DispatcherType.REQUEST)); | ||
| // Setup each provider with its filters and servlet | ||
| for (GitProxyProvider provider : providers) { | ||
| log.info("Configuring provider: {} at {}", provider.getName(), provider.servletMapping()); | ||
|
|
||
| var parseRequestFilter = new ParseGitRequestFilter(gitHubProvider); | ||
| var parseRequestFilterHolder = new FilterHolder(parseRequestFilter); | ||
| parseRequestFilterHolder.setAsyncSupported(true); | ||
| context.addFilter(parseRequestFilterHolder, urlPattern, EnumSet.of(DispatcherType.REQUEST)); | ||
| String urlPattern = provider.servletMapping(); | ||
|
|
||
| var githubAuthorizedFilter = new GitHubUserAuthenticatedFilter( | ||
| 10, gitHubProvider, Set.of(HttpAuthScheme.BASIC, HttpAuthScheme.TOKEN, HttpAuthScheme.BEARER)); | ||
| var ghFilterHolder = new FilterHolder(githubAuthorizedFilter); | ||
| context.addFilter(ghFilterHolder, urlPattern, EnumSet.of(DispatcherType.REQUEST)); | ||
| // Build and add filters for this provider | ||
| List<GitProxyFilter> filters = configBuilder.buildFiltersForProvider(provider); | ||
|
|
||
| var whitelistFilters = List.of( | ||
| // new WhitelistByUrlFilter(100, gitHubProvider, List.of("coopernetes"), | ||
| // RepositoryUrlFilter.Target.OWNER), | ||
| // new WhitelistByUrlFilter( | ||
| // 101, gitHubProvider, List.of("jgit-proxy", "test-repo"), | ||
| // RepositoryUrlFilter.Target.NAME), | ||
| new WhitelistByUrlFilter( | ||
| 102, | ||
| gitHubProvider, | ||
| List.of("finos/git-proxy", "coopernetes/test-repo"), | ||
| RepositoryUrlFilter.Target.SLUG)); | ||
| var whitelistAggregateFilter = new WhitelistAggregateFilter(20, gitHubProvider, whitelistFilters); | ||
| var whitelistAggFilterHolder = new FilterHolder(whitelistAggregateFilter); | ||
| whitelistAggFilterHolder.setAsyncSupported(true); | ||
| context.addFilter(whitelistAggFilterHolder, urlPattern, EnumSet.of(DispatcherType.REQUEST)); | ||
| // Sort filters by order | ||
| filters.sort(Comparator.comparingInt(GitProxyFilter::getOrder)); | ||
|
|
||
| var auditFilter = new AuditLogFilter(); | ||
| var auditFilterHolder = new FilterHolder(auditFilter); | ||
| auditFilterHolder.setAsyncSupported(true); | ||
| context.addFilter(auditFilterHolder, urlPattern, EnumSet.of(DispatcherType.REQUEST)); | ||
| for (GitProxyFilter filter : filters) { | ||
| var filterHolder = new FilterHolder(filter); | ||
| filterHolder.setAsyncSupported(true); | ||
| context.addFilter(filterHolder, urlPattern, EnumSet.of(DispatcherType.REQUEST)); | ||
| log.debug( | ||
| "Added filter {} (order={}) for {}", | ||
| filter.getClass().getSimpleName(), | ||
| filter.getOrder(), | ||
| provider.getName()); | ||
| } | ||
|
|
||
| var proxyServlet = new GitProxyServlet(); | ||
| var proxyServletHolder = new ServletHolder(proxyServlet); | ||
| proxyServletHolder.setInitParameter("proxyTo", "https://github.com"); | ||
| proxyServletHolder.setInitParameter("prefix", "/github.com"); | ||
| proxyServletHolder.setInitParameter("hostHeader", "github.com"); | ||
| proxyServletHolder.setInitParameter("preserveHost", "false"); | ||
| context.addServlet(proxyServletHolder, urlPattern); | ||
| // Add proxy servlet for this provider | ||
| var proxyServlet = new GitProxyServlet(); | ||
| var proxyServletHolder = new ServletHolder(proxyServlet); | ||
| proxyServletHolder.setInitParameter("proxyTo", provider.getUri().toString()); | ||
| proxyServletHolder.setInitParameter("prefix", provider.servletPath()); | ||
| proxyServletHolder.setInitParameter("hostHeader", provider.getUri().getHost()); | ||
| proxyServletHolder.setInitParameter("preserveHost", "false"); | ||
| context.addServlet(proxyServletHolder, urlPattern); | ||
| log.info("Added servlet for {} proxying to {}", provider.getName(), provider.getUri()); | ||
| } | ||
|
|
||
| server.setHandler(context); | ||
|
|
||
| server.start(); | ||
| System.out.println("Server started at http://localhost:8080/"); | ||
| log.info("Server started at http://localhost:{}/", port); | ||
| System.out.println("Server started at http://localhost:" + port + "/"); | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this example config section since we removed that filter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the github-user-authenticated filter section from the README.md example configuration in commit 593c443.