Skip to content

Commit 3549e73

Browse files
Copilotcoopernetes
andcommitted
Add YAML configuration layer to Jetty module
- JettyConfigurationLoader: Parse git-proxy.yml/git-proxy-local.yml with env var overrides (GITPROXY_ prefix) - JettyConfigurationBuilder: Build providers and whitelist filters from configuration - Updated GitProxyJettyApplication to use YAML configuration instead of hardcoded values - Added SnakeYAML 2.2 dependency - Added git-proxy.yml (base) and git-proxy-local.yml (local overrides) resource files - Added CONFIGURATION.md with detailed documentation - Updated README.md Jetty section to reference YAML configuration Co-authored-by: coopernetes <57812123+coopernetes@users.noreply.github.com>
1 parent 36eb0ab commit 3549e73

8 files changed

Lines changed: 608 additions & 39 deletions

File tree

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,12 @@ The core module provides pluggable configuration through:
6666
- Default in-memory implementations
6767

6868
### Jetty Module
69-
Configuration is done programmatically in the `GitProxyJettyApplication` class. You can:
70-
- Add/remove providers
71-
- Configure filters
72-
- Set up whitelists
69+
The Jetty module uses YAML-based configuration loaded from `git-proxy.yml` and `git-proxy-local.yml`:
70+
- **Providers**: Configure GitHub, GitLab, Bitbucket, and custom providers
71+
- **Filters**: Configure whitelist filters for repository access control
72+
- **Environment overrides**: Use `GITPROXY_` prefixed environment variables
73+
74+
See [`jgit-proxy-jetty/CONFIGURATION.md`](jgit-proxy-jetty/CONFIGURATION.md) for detailed configuration options.
7375

7476
### Spring Module
7577
Configuration is done through:

jgit-proxy-jetty/CONFIGURATION.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Jetty Module Configuration
2+
3+
The Jetty server implementation uses YAML-based configuration to dynamically configure providers, filters, and server settings. This is separate from the Spring Boot configuration (`application.yml`).
4+
5+
## Configuration Files
6+
7+
| File | Purpose |
8+
|------|---------|
9+
| `git-proxy.yml` | Base configuration shipped with the jar |
10+
| `git-proxy-local.yml` | Local overrides for development (optional) |
11+
12+
Files are loaded from the classpath in order, with `git-proxy-local.yml` values taking priority.
13+
14+
## Environment Variable Overrides
15+
16+
Configuration values can be overridden using environment variables with the `GITPROXY_` prefix:
17+
18+
| Environment Variable | Configuration Key | Example |
19+
|---|---|---|
20+
| `GITPROXY_SERVER_PORT` | `server.port` | `9090` |
21+
| `GITPROXY_GITPROXY_BASEPATH` | `git-proxy.base-path` | `/git` |
22+
| `GITPROXY_PROVIDERS_<NAME>_ENABLED` | `git-proxy.providers.<name>.enabled` | `true` |
23+
24+
> **Note:** Whitelist filter configuration is not supported via environment variables due to its complex nested structure. Use YAML files instead.
25+
26+
## Server Settings
27+
28+
```yaml
29+
server:
30+
port: 8080
31+
```
32+
33+
## Provider Configuration
34+
35+
Providers define the upstream Git hosting services to proxy. Built-in providers (github, gitlab, bitbucket) use well-known URIs. Custom providers require an explicit URI.
36+
37+
```yaml
38+
git-proxy:
39+
providers:
40+
# Built-in providers (use well-known URIs)
41+
github:
42+
enabled: true
43+
gitlab:
44+
enabled: true
45+
bitbucket:
46+
enabled: true
47+
48+
# Custom provider with explicit URI
49+
internal-gitlab:
50+
enabled: true
51+
servlet-path: /enterprise
52+
uri: https://gitlab.internal.example.com
53+
54+
# Another custom provider
55+
debian-gitlab:
56+
enabled: true
57+
servlet-path: /debian
58+
uri: https://salsa.debian.org/
59+
```
60+
61+
### Provider Properties
62+
63+
| Property | Type | Default | Description |
64+
|----------|------|---------|-------------|
65+
| `enabled` | boolean | `true` | Whether the provider is active |
66+
| `servlet-path` | string | `""` | Additional path prefix for the provider |
67+
| `uri` | string | _(built-in default)_ | Base URI for the upstream Git server |
68+
69+
## Filter Configuration
70+
71+
### Whitelist Filters
72+
73+
Whitelist filters control which repositories are allowed to be accessed through the proxy. Multiple whitelists can be defined, each scoped to specific providers and operations.
74+
75+
```yaml
76+
git-proxy:
77+
filters:
78+
whitelists:
79+
# Allow specific repos by slug (owner/name)
80+
- enabled: true
81+
order: 1100
82+
operations:
83+
- FETCH
84+
- PUSH
85+
providers:
86+
- github
87+
slugs:
88+
- finos/git-proxy
89+
- coopernetes/test-repo
90+
91+
# Allow all repos from an owner
92+
- enabled: true
93+
order: 1200
94+
operations:
95+
- FETCH
96+
providers:
97+
- github
98+
owners:
99+
- finos
100+
101+
# Allow repos by name across all providers
102+
- enabled: true
103+
order: 1300
104+
operations:
105+
- FETCH
106+
names:
107+
- hello-world
108+
```
109+
110+
### Whitelist Properties
111+
112+
| Property | Type | Default | Description |
113+
|----------|------|---------|-------------|
114+
| `enabled` | boolean | `true` | Whether this whitelist is active |
115+
| `order` | int | `1100` | Filter execution order (1000-1999 range) |
116+
| `operations` | list | _none_ | Git operations to match: `FETCH`, `PUSH` |
117+
| `providers` | list | _all_ | Provider names this whitelist applies to |
118+
| `slugs` | list | _none_ | Repository slugs (e.g., `owner/repo`) |
119+
| `owners` | list | _none_ | Repository owners/orgs |
120+
| `names` | list | _none_ | Repository names |
121+
122+
## Running
123+
124+
```shell
125+
# Default configuration
126+
./gradlew :jgit-proxy-jetty:run
127+
128+
# Override port via environment variable
129+
GITPROXY_SERVER_PORT=9090 ./gradlew :jgit-proxy-jetty:run
130+
```

jgit-proxy-jetty/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ dependencies {
2727
// Core module
2828
implementation project(':jgit-proxy-core')
2929

30+
// YAML configuration
31+
implementation 'org.yaml:snakeyaml:2.2'
32+
3033
// Lombok
3134
compileOnly 'org.projectlombok:lombok:1.18.34'
3235
annotationProcessor 'org.projectlombok:lombok:1.18.34'

jgit-proxy-jetty/src/main/java/org/finos/gitproxy/jetty/GitProxyJettyApplication.java

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.finos.gitproxy.jetty;
22

33
import jakarta.servlet.DispatcherType;
4-
import java.util.ArrayList;
54
import java.util.EnumSet;
65
import java.util.List;
76
import lombok.extern.slf4j.Slf4j;
@@ -13,41 +12,47 @@
1312
import org.eclipse.jetty.util.thread.QueuedThreadPool;
1413
import org.finos.gitproxy.config.InMemoryProviderConfigurationSource;
1514
import org.finos.gitproxy.git.LocalRepositoryCache;
16-
import org.finos.gitproxy.provider.BitbucketProvider;
17-
import org.finos.gitproxy.provider.GitHubProvider;
18-
import org.finos.gitproxy.provider.GitLabProvider;
15+
import org.finos.gitproxy.jetty.config.JettyConfigurationBuilder;
16+
import org.finos.gitproxy.jetty.config.JettyConfigurationLoader;
1917
import org.finos.gitproxy.provider.GitProxyProvider;
2018
import org.finos.gitproxy.servlet.GitProxyServlet;
2119
import org.finos.gitproxy.servlet.filter.*;
2220

2321
/**
24-
* Standalone Jetty server application for the JGit proxy. This application uses the core module's reusable servlet and
25-
* filter code to create a standalone proxy server without Spring dependencies.
22+
* Standalone Jetty server application for the JGit proxy. This application uses YAML-based configuration loaded from
23+
* {@code git-proxy.yml} and {@code git-proxy-local.yml} to dynamically configure providers and filters.
24+
*
25+
* <p>Configuration can be overridden using environment variables with the {@code GITPROXY_} prefix. See
26+
* {@link JettyConfigurationLoader} for details.
2627
*/
2728
@Slf4j
2829
public class GitProxyJettyApplication {
2930

3031
public static void main(String[] args) throws Exception {
3132
log.info("Starting JGit Proxy Jetty Application...");
3233

34+
// Load configuration from YAML files and environment variables
35+
var configLoader = new JettyConfigurationLoader();
36+
var configBuilder = new JettyConfigurationBuilder(configLoader);
37+
3338
// Create thread pool for the server
3439
var threadPool = new QueuedThreadPool();
3540
threadPool.setName("jgit-proxy-server");
3641

3742
// Create the Jetty server
3843
var server = new Server(threadPool);
3944

40-
// Configure connector
45+
// Configure connector using configured port
4146
var connector = new ServerConnector(server);
42-
connector.setPort(getPort());
47+
connector.setPort(configBuilder.getServerPort());
4348
server.addConnector(connector);
4449

4550
// Initialize the local repository cache
4651
var repositoryCache = new LocalRepositoryCache();
4752
log.info("Initialized LocalRepositoryCache");
4853

49-
// Configure providers
50-
List<GitProxyProvider> providers = createProviders();
54+
// Configure providers from YAML configuration
55+
List<GitProxyProvider> providers = configBuilder.buildProviders();
5156
var providerConfig = new InMemoryProviderConfigurationSource(providers);
5257

5358
// Create servlet context
@@ -57,7 +62,7 @@ public static void main(String[] args) throws Exception {
5762
for (GitProxyProvider provider : providerConfig.getProviders()) {
5863
log.info("Registering proxy for provider: {}", provider.getName());
5964
registerProxyServlet(context, provider);
60-
registerFilters(context, provider, repositoryCache);
65+
registerFilters(context, provider, repositoryCache, configBuilder);
6166
}
6267

6368
server.setHandler(context);
@@ -72,22 +77,6 @@ public static void main(String[] args) throws Exception {
7277
server.join();
7378
}
7479

75-
private static int getPort() {
76-
String portStr = System.getProperty("port", System.getenv().getOrDefault("PORT", "8080"));
77-
return Integer.parseInt(portStr);
78-
}
79-
80-
private static List<GitProxyProvider> createProviders() {
81-
List<GitProxyProvider> providers = new ArrayList<>();
82-
83-
// Add default providers
84-
providers.add(new GitHubProvider(""));
85-
providers.add(new GitLabProvider(""));
86-
providers.add(new BitbucketProvider(""));
87-
88-
return providers;
89-
}
90-
9180
private static void registerProxyServlet(ServletContextHandler context, GitProxyProvider provider) {
9281
var proxyServlet = new GitProxyServlet();
9382
var proxyServletHolder = new ServletHolder(proxyServlet);
@@ -99,7 +88,10 @@ private static void registerProxyServlet(ServletContextHandler context, GitProxy
9988
}
10089

10190
private static void registerFilters(
102-
ServletContextHandler context, GitProxyProvider provider, LocalRepositoryCache repositoryCache) {
91+
ServletContextHandler context,
92+
GitProxyProvider provider,
93+
LocalRepositoryCache repositoryCache,
94+
JettyConfigurationBuilder configBuilder) {
10395
String urlPattern = provider.servletMapping();
10496

10597
// Force Git client filter (must be first)
@@ -120,13 +112,15 @@ private static void registerFilters(
120112
enrichCommitsFilterHolder.setAsyncSupported(true);
121113
context.addFilter(enrichCommitsFilterHolder, urlPattern, EnumSet.of(DispatcherType.REQUEST));
122114

123-
// Example whitelist filter (can be configured based on requirements)
124-
var whitelistFilters = List.of(new WhitelistByUrlFilter(
125-
1100, provider, List.of("finos/git-proxy", "coopernetes/test-repo"), RepositoryUrlFilter.Target.SLUG));
126-
var whitelistAggregateFilter = new WhitelistAggregateFilter(1000, provider, whitelistFilters);
127-
var whitelistAggFilterHolder = new FilterHolder(whitelistAggregateFilter);
128-
whitelistAggFilterHolder.setAsyncSupported(true);
129-
context.addFilter(whitelistAggFilterHolder, urlPattern, EnumSet.of(DispatcherType.REQUEST));
115+
// Whitelist filters from configuration
116+
List<WhitelistByUrlFilter> whitelistFilters = configBuilder.buildWhitelistFilters(provider);
117+
if (!whitelistFilters.isEmpty()) {
118+
var whitelistAggregateFilter = new WhitelistAggregateFilter(1000, provider, whitelistFilters);
119+
var whitelistAggFilterHolder = new FilterHolder(whitelistAggregateFilter);
120+
whitelistAggFilterHolder.setAsyncSupported(true);
121+
context.addFilter(whitelistAggFilterHolder, urlPattern, EnumSet.of(DispatcherType.REQUEST));
122+
log.info("Registered {} whitelist filter(s) for provider {}", whitelistFilters.size(), provider.getName());
123+
}
130124

131125
// Audit filter (should be last)
132126
var auditFilter = new AuditLogFilter();

0 commit comments

Comments
 (0)