feat: disable ssl verification, close #1024#1084
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request implements a new feature that allows disabling SSL certificate verification for outgoing HTTP requests. This is controlled by a new configuration setting, primarily intended for scenarios involving self-signed certificates in trusted environments. The change ensures that this setting is consistently applied across different parts of the application when HTTP clients are initialized, especially when proxy configurations are in use. Highlights
Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new DisableSSLVerify configuration option, allowing users to disable SSL certificate verification for upstream HTTP requests. The change involves adding this flag to the main configuration, server-specific configurations, and the proxy configuration struct. The NewHttpClientWithProxy function is updated to respect this flag by setting InsecureSkipVerify on the TLS client configuration. The DisableSSLVerify flag is then propagated and used across various API handlers (Antigravity, ClaudeCode, Codex, Copilot) and business logic services (ChannelService, ModelFetcher, ProviderQuotaService) to conditionally disable SSL verification when creating HTTP clients, especially when a proxy is involved. Review comments suggest refactoring to avoid modifying req.Proxy directly by creating a copy, ensuring consistent logic for disableSSLVerify in channel_llm.go, and reducing code duplication in model_fetcher.go and codex_checker.go by reusing or extracting common proxy configuration logic.
internal/server/api/antigravity.go
Outdated
| if h.disableSSLVerify { | ||
| req.Proxy.InsecureSkipVerify = true | ||
| } | ||
| httpClient = httpclient.NewHttpClientWithProxy(req.Proxy) |
There was a problem hiding this comment.
To avoid side effects, it's better to create a copy of the proxy configuration instead of modifying the input request object req.Proxy directly. This improves code clarity and prevents unexpected behavior if the request object is used elsewhere.
proxyConf := *req.Proxy
if h.disableSSLVerify {
proxyConf.InsecureSkipVerify = true
}
httpClient = httpclient.NewHttpClientWithProxy(&proxyConf)
internal/server/api/claudecode.go
Outdated
| if h.disableSSLVerify { | ||
| req.Proxy.InsecureSkipVerify = true | ||
| } | ||
| httpClient = httpclient.NewHttpClientWithProxy(req.Proxy) |
There was a problem hiding this comment.
To avoid side effects, it's better to create a copy of the proxy configuration instead of modifying the input request object req.Proxy directly. This improves code clarity and prevents unexpected behavior if the request object is used elsewhere.
proxyConf := *req.Proxy
if h.disableSSLVerify {
proxyConf.InsecureSkipVerify = true
}
httpClient = httpclient.NewHttpClientWithProxy(&proxyConf)
internal/server/api/codex.go
Outdated
| if h.disableSSLVerify { | ||
| req.Proxy.InsecureSkipVerify = true | ||
| } | ||
| httpClient = httpclient.NewHttpClientWithProxy(req.Proxy) |
There was a problem hiding this comment.
To avoid side effects, it's better to create a copy of the proxy configuration instead of modifying the input request object req.Proxy directly. This improves code clarity and prevents unexpected behavior if the request object is used elsewhere.
proxyConf := *req.Proxy
if h.disableSSLVerify {
proxyConf.InsecureSkipVerify = true
}
httpClient = httpclient.NewHttpClientWithProxy(&proxyConf)
internal/server/api/copilot.go
Outdated
| if h.disableSSLVerify { | ||
| req.Proxy.InsecureSkipVerify = true | ||
| } | ||
| httpClient = httpclient.NewHttpClientWithProxy(req.Proxy) |
There was a problem hiding this comment.
To avoid side effects, it's better to create a copy of the proxy configuration instead of modifying the input request object req.Proxy directly. This improves code clarity and prevents unexpected behavior if the request object is used elsewhere.
proxyConf := *req.Proxy
if h.disableSSLVerify {
proxyConf.InsecureSkipVerify = true
}
httpClient = httpclient.NewHttpClientWithProxy(&proxyConf)
internal/server/api/copilot.go
Outdated
| if h.disableSSLVerify { | ||
| req.Proxy.InsecureSkipVerify = true | ||
| } | ||
| httpClient = httpclient.NewHttpClientWithProxy(req.Proxy) |
There was a problem hiding this comment.
To avoid side effects, it's better to create a copy of the proxy configuration instead of modifying the input request object req.Proxy directly. This improves code clarity and prevents unexpected behavior if the request object is used elsewhere.
proxyConf := *req.Proxy
if h.disableSSLVerify {
proxyConf.InsecureSkipVerify = true
}
httpClient = httpclient.NewHttpClientWithProxy(&proxyConf)
internal/server/biz/channel_llm.go
Outdated
| if svc.disableSSLVerify && !proxy.InsecureSkipVerify { | ||
| proxy.InsecureSkipVerify = true | ||
| } |
There was a problem hiding this comment.
The logic here is slightly different from other places where disableSSLVerify is used. Here, you check !proxy.InsecureSkipVerify before setting it to true. In other files, it's an unconditional assignment. For consistency, it might be better to use the same logic everywhere. An unconditional assignment proxy.InsecureSkipVerify = svc.disableSSLVerify would be simpler and align with the behavior in other parts of the code, assuming the intent is for the global flag to always take precedence.
| if svc.disableSSLVerify && !proxy.InsecureSkipVerify { | |
| proxy.InsecureSkipVerify = true | |
| } | |
| if svc.disableSSLVerify { | |
| proxy.InsecureSkipVerify = true | |
| } |
internal/server/biz/model_fetcher.go
Outdated
| proxyConfig = f.channelService.getProxyConfig(ch.Settings) | ||
| } else if f.channelService.disableSSLVerify { | ||
| proxyConfig = &httpclient.ProxyConfig{ | ||
| Type: httpclient.ProxyTypeEnvironment, | ||
| InsecureSkipVerify: true, | ||
| } | ||
| } |
There was a problem hiding this comment.
This logic for handling disableSSLVerify seems to be duplicated from internal/server/biz/channel_llm.go. Instead of reimplementing it here, you could reuse the getProxyConfig method from the channelService. This would reduce code duplication and ensure consistent behavior.
For example:
if ch.Settings != nil {
proxyConfig = f.channelService.getProxyConfig(ch.Settings)
} else {
// When ch.Settings is nil, getProxyConfig will correctly handle
// the disableSSLVerify flag and return a default proxy config.
proxyConfig = f.channelService.getProxyConfig(nil)
}| proxyConfig := ch.Settings.Proxy | ||
| if c.disableSSLVerify { | ||
| proxyConfig.InsecureSkipVerify = true | ||
| } | ||
|
|
||
| wrappedClient := httpclient.NewHttpClientWithProxy(proxyConfig) | ||
| client = wrappedClient.GetNativeClient() | ||
| } else if c.disableSSLVerify { | ||
| wrappedClient := httpclient.NewHttpClientWithProxy(&httpclient.ProxyConfig{ | ||
| Type: httpclient.ProxyTypeEnvironment, | ||
| InsecureSkipVerify: true, | ||
| }) | ||
| client = wrappedClient.GetNativeClient() |
There was a problem hiding this comment.
This block has duplicated logic for creating a proxy-configured HTTP client. The logic for handling disableSSLVerify is also repeated. It would be beneficial to extract this into a shared function to ensure consistency and reduce code duplication. For instance, a helper could take the channel settings and the global disableSSLVerify flag and return a correctly configured *http.Client.
|
@gemini-code-assist review |
There was a problem hiding this comment.
Code Review
This pull request introduces a new configuration option, DisableSSLVerify, allowing users to disable SSL certificate verification for HTTP clients, primarily for self-signed certificates. The change involves adding this option to the main configuration, exposing it in example configurations and documentation, and integrating it into the application's HTTP client creation logic. Specifically, the httpclient.HttpClient now supports ClientOptions to configure TLS settings, and proxy-configured HTTP clients are updated to inherit these options from the default client. This ensures consistent SSL verification behavior across various API handlers, channel services, model fetchers, and provider quota checkers, centralizing HTTP client management and options inheritance throughout the system.
|
@gemini-code-assist review |
There was a problem hiding this comment.
Code Review
This pull request introduces a new configuration option to disable SSL verification, enhancing flexibility in environments with self-signed certificates. It modifies the configuration structure, adds a default value, and propagates the setting to HTTP clients. The changes span across configuration files, documentation, and internal server components to ensure consistent behavior. Additionally, comments related to nolint:gosec directives have been clarified with explicit reasons for suppression.
| if options.insecureSkipVerify { | ||
| transport.TLSClientConfig = &tls.Config{ | ||
| InsecureSkipVerify: true, //nolint:gosec // User-configured option for self-signed certificates | ||
| } | ||
| } |
There was a problem hiding this comment.
This change introduces the ability to skip TLS verification, which is useful for environments using self-signed certificates. However, disabling TLS verification can introduce security risks. Ensure users are aware of the implications and only enable this option in trusted environments. Consider adding a warning log when this option is enabled.
| return Config{}, fmt.Errorf("failed to unmarshal config: %w", err) | ||
| } | ||
|
|
||
| config.DisableSSLVerify = config.APIServer.DisableSSLVerify |
There was a problem hiding this comment.
internal/server/api/antigravity.go
Outdated
| httpClient := h.httpClient | ||
| if req.Proxy != nil && req.Proxy.Type == httpclient.ProxyTypeURL && req.Proxy.URL != "" { | ||
| httpClient = httpclient.NewHttpClientWithProxy(req.Proxy) | ||
| httpClient = httpclient.NewHttpClientWithProxy(req.Proxy, h.httpClient.Options()...) |
internal/server/biz/channel_llm.go
Outdated
| func (svc *ChannelService) getHttpClient(channelSettings *objects.ChannelSettings) *httpclient.HttpClient { | ||
| if channelSettings == nil || channelSettings.Proxy == nil { | ||
| return svc.httpClient | ||
| } | ||
|
|
||
| return httpclient.NewHttpClientWithProxy(channelSettings.Proxy, svc.httpClient.Options()...) |
There was a problem hiding this comment.
internal/server/biz/model_fetcher.go
Outdated
| httpClient := f.httpClient | ||
| if proxyConfig != nil { | ||
| httpClient = httpclient.NewHttpClientWithProxy(proxyConfig) | ||
| } else { | ||
| httpClient = f.httpClient | ||
| httpClient = httpclient.NewHttpClientWithProxy(proxyConfig, f.httpClient.Options()...) |
| if p.httpClient == nil { | ||
| return nil, errors.New("http client is nil") | ||
| } |
| provider = NewTokenProvider(TokenProviderParams{ | ||
| OAuthUrls: OAuthUrls{TokenUrl: "http://example.com/token"}, | ||
| }) | ||
| _, err = provider.refresh(context.Background(), &OAuthCredentials{RefreshToken: "refresh"}) | ||
| require.EqualError(t, err, "http client is nil") |
| var opts []httpclient.ClientOption | ||
| if channel.HTTPClient != nil { | ||
| opts = channel.HTTPClient.Options() | ||
| } | ||
|
|
||
| customizedExecutor = httpclient.NewHttpClientWithProxy(p.state.Proxy, opts...) |
|
|
||
| if options.insecureSkipVerify { | ||
| transport.TLSClientConfig = &tls.Config{ | ||
| InsecureSkipVerify: true, //nolint:gosec // User-configured option for self-signed certificates |
There was a problem hiding this comment.
This comment is a nolint directive to suppress a gosec warning. It's important to ensure that the reason for suppressing the warning is valid and documented. In this case, it's a user-configured option, which is acceptable, but the comment should explicitly state that.
| InsecureSkipVerify: true, //nolint:gosec // User-configured option for self-signed certificates | |
| InsecureSkipVerify: true, //nolint:gosec // User-configured option for self-signed certificates in trusted environments |
| } else { | ||
| transport.TLSClientConfig = transport.TLSClientConfig.Clone() | ||
| } | ||
| transport.TLSClientConfig.InsecureSkipVerify = true //nolint:gosec // User-configured option for self-signed certificates |
There was a problem hiding this comment.
This comment is a nolint directive to suppress a gosec warning. It's important to ensure that the reason for suppressing the warning is valid and documented. In this case, it's a user-configured option, which is acceptable, but the comment should explicitly state that.
| transport.TLSClientConfig.InsecureSkipVerify = true //nolint:gosec // User-configured option for self-signed certificates | |
| transport.TLSClientConfig.InsecureSkipVerify = true //nolint:gosec // User-configured option for self-signed certificates in trusted environments |
No description provided.