Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.

Commit d01837b

Browse files
authored
Merge pull request #268 from stacklok/copilot-prov
CoPilot Implementation
2 parents c5ccd2a + d90a303 commit d01837b

File tree

15 files changed

+1956
-23
lines changed

15 files changed

+1956
-23
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,6 @@ weaviate_data/
4545

4646
# Codegate Dashboard DB
4747
codegate.db
48+
49+
# certificate directory
50+
certs/

cert_gen.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
from cryptography import x509
2+
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
3+
from cryptography.hazmat.primitives import hashes, serialization
4+
from cryptography.hazmat.primitives.asymmetric import rsa
5+
import datetime
6+
import os
7+
8+
def generate_certificates(cert_dir="certs"):
9+
"""Generate self-signed certificates with proper extensions for HTTPS proxy"""
10+
# Create certificates directory if it doesn't exist
11+
if not os.path.exists(cert_dir):
12+
print("Making: ", cert_dir)
13+
os.makedirs(cert_dir)
14+
15+
# Generate private key
16+
ca_private_key = rsa.generate_private_key(
17+
public_exponent=65537,
18+
key_size=4096, # Increased key size for better security
19+
)
20+
21+
# Generate public key
22+
ca_public_key = ca_private_key.public_key()
23+
24+
# CA BEGIN
25+
name = x509.Name([
26+
x509.NameAttribute(NameOID.COMMON_NAME, "Proxy Pilot CA"),
27+
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Proxy Pilot"),
28+
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, "Development"),
29+
x509.NameAttribute(NameOID.COUNTRY_NAME, "UK"),
30+
])
31+
32+
builder = x509.CertificateBuilder()
33+
builder = builder.subject_name(name)
34+
builder = builder.issuer_name(name)
35+
builder = builder.public_key(ca_public_key)
36+
builder = builder.serial_number(x509.random_serial_number())
37+
builder = builder.not_valid_before(datetime.datetime.utcnow())
38+
builder = builder.not_valid_after(
39+
datetime.datetime.utcnow() + datetime.timedelta(days=3650) # 10 years
40+
)
41+
42+
builder = builder.add_extension(
43+
x509.BasicConstraints(ca=True, path_length=None),
44+
critical=True,
45+
)
46+
47+
builder = builder.add_extension(
48+
x509.KeyUsage(
49+
digital_signature=True,
50+
content_commitment=False,
51+
key_encipherment=True,
52+
data_encipherment=False,
53+
key_agreement=False,
54+
key_cert_sign=True, # This is a CA
55+
crl_sign=True,
56+
encipher_only=False,
57+
decipher_only=False
58+
),
59+
critical=True,
60+
)
61+
62+
ca_cert = builder.sign(
63+
private_key=ca_private_key,
64+
algorithm=hashes.SHA256(),
65+
)
66+
67+
# Save CA certificate and key
68+
69+
with open("certs/ca.crt", "wb") as f:
70+
f.write(ca_cert.public_bytes(serialization.Encoding.PEM))
71+
72+
with open("certs/ca.key", "wb") as f:
73+
f.write(ca_private_key.private_bytes(
74+
encoding=serialization.Encoding.PEM,
75+
format=serialization.PrivateFormat.PKCS8,
76+
encryption_algorithm=serialization.NoEncryption()
77+
))
78+
# CA END
79+
80+
# SERVER BEGIN
81+
82+
## Generate new certificate for domain
83+
server_key = rsa.generate_private_key(
84+
public_exponent=65537,
85+
key_size=2048, # 2048 bits is sufficient for domain certs
86+
)
87+
88+
name = x509.Name([
89+
x509.NameAttribute(NameOID.COMMON_NAME, "Proxy Pilot CA"),
90+
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Proxy Pilot Generated"),
91+
])
92+
93+
builder = x509.CertificateBuilder()
94+
builder = builder.subject_name(name)
95+
builder = builder.issuer_name(ca_cert.subject)
96+
builder = builder.public_key(server_key.public_key())
97+
builder = builder.serial_number(x509.random_serial_number())
98+
builder = builder.not_valid_before(datetime.datetime.utcnow())
99+
builder = builder.not_valid_after(
100+
datetime.datetime.utcnow() + datetime.timedelta(days=365)
101+
)
102+
103+
# Add domain to SAN
104+
builder = builder.add_extension(
105+
x509.SubjectAlternativeName([x509.DNSName("localhost")]),
106+
critical=False,
107+
)
108+
109+
# Add extended key usage
110+
builder = builder.add_extension(
111+
x509.ExtendedKeyUsage([
112+
ExtendedKeyUsageOID.SERVER_AUTH,
113+
ExtendedKeyUsageOID.CLIENT_AUTH,
114+
]),
115+
critical=False,
116+
)
117+
118+
# Basic constraints (not a CA)
119+
builder = builder.add_extension(
120+
x509.BasicConstraints(ca=False, path_length=None),
121+
critical=True,
122+
)
123+
124+
certificate = builder.sign(
125+
private_key=ca_private_key,
126+
algorithm=hashes.SHA256(),
127+
)
128+
129+
with open("certs/server.crt", "wb") as f:
130+
f.write(certificate.public_bytes(serialization.Encoding.PEM))
131+
132+
with open("certs/server.key", "wb") as f:
133+
f.write(server_key.private_bytes(
134+
encoding=serialization.Encoding.PEM,
135+
format=serialization.PrivateFormat.PKCS8,
136+
encryption_algorithm=serialization.NoEncryption()
137+
))
138+
139+
140+
print("Certificates generated successfully in the 'certs' directory")
141+
print("\nTo trust these certificates:")
142+
print("\nOn macOS:")
143+
print("sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain certs/server.crt")
144+
print("\nOn Windows (PowerShell as Admin):")
145+
print("Import-Certificate -FilePath \"certs\\server.crt\" -CertStoreLocation Cert:\\LocalMachine\\Root")
146+
print("\nOn Linux:")
147+
print("sudo cp certs/server.crt /usr/local/share/ca-certificates/proxy-pilot.crt")
148+
print("sudo update-ca-certificates")
149+
print("\nFor VSCode, add to settings.json:")
150+
print('''{
151+
"http.proxy": "https://localhost:8989",
152+
"http.proxySupport": "on",
153+
"github.copilot.advanced": {
154+
"debug.testOverrideProxyUrl": "https://localhost:8989",
155+
"debug.overrideProxyUrl": "https://localhost:8989"
156+
}
157+
}''')
158+
159+
if __name__ == "__main__":
160+
generate_certificates()

config.yaml.example

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22

33
# Network settings
44
port: 8989 # Port to listen on (1-65535)
5+
proxy_port: 8990 # Proxy port to listen on (1-65535)
56
host: "localhost" # Host to bind to (use localhost for all interfaces)
67

78
# Logging configuration
89
log_level: "INFO" # One of: ERROR, WARNING, INFO, DEBUG
910

1011
# Note: This configuration can be overridden by:
11-
# 1. CLI arguments (--port, --host, --log-level)
12-
# 2. Environment variables (CODEGATE_APP_PORT, CODEGATE_APP_HOST, CODEGATE_APP_LOG_LEVEL)
12+
# 1. CLI arguments (--port, --proxy-port, --host, --log-level)
13+
# 2. Environment variables (CODEGATE_APP_PORT, CODEGATE_APP_PROXY_PORT, CODEGATE_APP_HOST, CODEGATE_APP_LOG_LEVEL)
1314

1415
# Provider URLs
1516
provider_urls:
@@ -26,6 +27,22 @@ provider_urls:
2627
# --openai-url
2728
# --anthropic-url
2829

30+
# Certificate configuration
31+
certs_dir: "./certs" # Directory for certificate files
32+
ca_cert: "ca.crt" # CA certificate file name
33+
ca_key: "ca.key" # CA key file name
34+
server_cert: "server.crt" # Server certificate file name
35+
server_key: "server.key" # Server key file name
36+
37+
# Note: Certificate configuration can be overridden by:
38+
# 1. CLI arguments (--certs-dir, --ca-cert, --ca-key, --server-cert, --server-key)
39+
# 2. Environment variables:
40+
# CODEGATE_CERTS_DIR
41+
# CODEGATE_CA_CERT
42+
# CODEGATE_CA_KEY
43+
# CODEGATE_SERVER_CERT
44+
# CODEGATE_SERVER_KEY
45+
2946
# Embedding model configuration
3047

3148
####

docs/configuration.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The configuration system in Codegate is managed through the `Config` class in `c
1212
## Default Configuration Values
1313

1414
- Port: 8989
15+
- Proxy Port: 8990
1516
- Host: "localhost"
1617
- Log Level: "INFO"
1718
- Log Format: "JSON"
@@ -21,6 +22,12 @@ The configuration system in Codegate is managed through the `Config` class in `c
2122
- OpenAI: "https://api.openai.com/v1"
2223
- Anthropic: "https://api.anthropic.com/v1"
2324
- Ollama: "http://localhost:11434"
25+
- Certificate Configuration:
26+
- Certs Directory: "./certs"
27+
- CA Certificate: "ca.crt"
28+
- CA Key: "ca.key"
29+
- Server Certificate: "server.crt"
30+
- Server Key: "server.key"
2431

2532
## Configuration Methods
2633

@@ -35,6 +42,7 @@ config = Config.from_file("config.yaml")
3542
Example config.yaml:
3643
```yaml
3744
port: 8989
45+
proxy_port: 8990
3846
host: localhost
3947
log_level: INFO
4048
log_format: JSON
@@ -43,13 +51,19 @@ provider_urls:
4351
openai: "https://api.openai.com/v1"
4452
anthropic: "https://api.anthropic.com/v1"
4553
ollama: "http://localhost:11434"
54+
certs_dir: "./certs"
55+
ca_cert: "ca.crt"
56+
ca_key: "ca.key"
57+
server_cert: "server.crt"
58+
server_key: "server.key"
4659
```
4760
4861
### From Environment Variables
4962
5063
Environment variables are automatically loaded with these mappings:
5164
5265
- `CODEGATE_APP_PORT`: Server port
66+
- `CODEGATE_APP_PROXY_PORT`: Server proxy port
5367
- `CODEGATE_APP_HOST`: Server host
5468
- `CODEGATE_APP_LOG_LEVEL`: Logging level
5569
- `CODEGATE_LOG_FORMAT`: Log format
@@ -58,13 +72,41 @@ Environment variables are automatically loaded with these mappings:
5872
- `CODEGATE_PROVIDER_OPENAI_URL`: OpenAI provider URL
5973
- `CODEGATE_PROVIDER_ANTHROPIC_URL`: Anthropic provider URL
6074
- `CODEGATE_PROVIDER_OLLAMA_URL`: Ollama provider URL
75+
- `CODEGATE_CERTS_DIR`: Directory for certificate files
76+
- `CODEGATE_CA_CERT`: CA certificate file name
77+
- `CODEGATE_CA_KEY`: CA key file name
78+
- `CODEGATE_SERVER_CERT`: Server certificate file name
79+
- `CODEGATE_SERVER_KEY`: Server key file name
6180

6281
```python
6382
config = Config.from_env()
6483
```
6584

6685
## Configuration Options
6786

87+
### Network Settings
88+
89+
Network settings can be configured in several ways:
90+
91+
1. In Configuration File:
92+
```yaml
93+
port: 8989 # Port to listen on (1-65535)
94+
proxy_port: 8990 # Proxy port to listen on (1-65535)
95+
host: "localhost" # Host to bind to
96+
```
97+
98+
2. Via Environment Variables:
99+
```bash
100+
export CODEGATE_APP_PORT=8989
101+
export CODEGATE_APP_PROXY_PORT=8990
102+
export CODEGATE_APP_HOST=localhost
103+
```
104+
105+
3. Via CLI Flags:
106+
```bash
107+
codegate serve --port 8989 --proxy-port 8990 --host localhost
108+
```
109+
68110
### Provider URLs
69111

70112
Provider URLs can be configured in several ways:
@@ -95,6 +137,33 @@ Note:
95137
- For the vLLM provider, the /v1 path is automatically appended to the base URL if not present.
96138
- For the Ollama provider, the /api path is automatically appended to the base URL if not present.
97139

140+
### Certificate Configuration
141+
142+
Certificate files can be configured in several ways:
143+
144+
1. In Configuration File:
145+
```yaml
146+
certs_dir: "./certs"
147+
ca_cert: "ca.crt"
148+
ca_key: "ca.key"
149+
server_cert: "server.crt"
150+
server_key: "server.key"
151+
```
152+
153+
2. Via Environment Variables:
154+
```bash
155+
export CODEGATE_CERTS_DIR=./certs
156+
export CODEGATE_CA_CERT=ca.crt
157+
export CODEGATE_CA_KEY=ca.key
158+
export CODEGATE_SERVER_CERT=server.crt
159+
export CODEGATE_SERVER_KEY=server.key
160+
```
161+
162+
3. Via CLI Flags:
163+
```bash
164+
codegate serve --certs-dir ./certs --ca-cert ca.crt --ca-key ca.key --server-cert server.crt --server-key server.key
165+
```
166+
98167
### Log Levels
99168

100169
Available log levels (case-insensitive):
@@ -160,6 +229,7 @@ prompt = config.prompts.prompt_name
160229
The configuration system uses a custom `ConfigurationError` exception for handling configuration-related errors, such as:
161230

162231
- Invalid port numbers (must be between 1 and 65535)
232+
- Invalid proxy port numbers (must be between 1 and 65535)
163233
- Invalid log levels
164234
- Invalid log formats
165235
- YAML parsing errors

0 commit comments

Comments
 (0)