mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-04 17:56:38 +00:00
Get the headers into the traefik config
This commit is contained in:
@@ -31,6 +31,8 @@ def convert_and_send(file_path, url, headers):
|
|||||||
|
|
||||||
# convert the parsed YAML to a JSON string
|
# convert the parsed YAML to a JSON string
|
||||||
json_payload = json.dumps(parsed_yaml)
|
json_payload = json.dumps(parsed_yaml)
|
||||||
|
print("Converted JSON payload:")
|
||||||
|
print(json_payload)
|
||||||
|
|
||||||
# Encode the JSON string to Base64
|
# Encode the JSON string to Base64
|
||||||
encoded_json = base64.b64encode(json_payload.encode('utf-8')).decode('utf-8')
|
encoded_json = base64.b64encode(json_payload.encode('utf-8')).decode('utf-8')
|
||||||
|
|||||||
@@ -5,16 +5,19 @@ resources:
|
|||||||
full-domain: level1.test3.example.com
|
full-domain: level1.test3.example.com
|
||||||
host-header: example.com
|
host-header: example.com
|
||||||
tls-server-name: example.com
|
tls-server-name: example.com
|
||||||
auth:
|
# auth:
|
||||||
pincode: 123456
|
# pincode: 123456
|
||||||
password: sadfasdfadsf
|
# password: sadfasdfadsf
|
||||||
sso-enabled: true
|
# sso-enabled: true
|
||||||
sso-roles:
|
# sso-roles:
|
||||||
- Member
|
# - Member
|
||||||
sso-users:
|
# sso-users:
|
||||||
- owen@fossorial.io
|
# - owen@fossorial.io
|
||||||
whitelist-users:
|
# whitelist-users:
|
||||||
- owen@fossorial.io
|
# - owen@fossorial.io
|
||||||
|
headers:
|
||||||
|
- X-Example-Header: example-value
|
||||||
|
- X-Another-Header: another-value
|
||||||
targets:
|
targets:
|
||||||
- site: lively-yosemite-toad
|
- site: lively-yosemite-toad
|
||||||
hostname: localhost
|
hostname: localhost
|
||||||
@@ -24,15 +27,11 @@ resources:
|
|||||||
hostname: localhost
|
hostname: localhost
|
||||||
method: http
|
method: http
|
||||||
port: 8001
|
port: 8001
|
||||||
- site: glossy-plains-viscacha-rat
|
|
||||||
hostname: localhost
|
|
||||||
method: http
|
|
||||||
port: 8001
|
|
||||||
resource-nice-id2:
|
resource-nice-id2:
|
||||||
name: this is other resource
|
name: this is other resource
|
||||||
protocol: tcp
|
protocol: tcp
|
||||||
proxy-port: 3000
|
proxy-port: 3000
|
||||||
targets:
|
targets:
|
||||||
- site: glossy-plains-viscacha-rat
|
- site: lively-yosemite-toad
|
||||||
hostname: localhost
|
hostname: localhost
|
||||||
port: 3000
|
port: 3000
|
||||||
@@ -96,6 +96,7 @@ export const resources = pgTable("resources", {
|
|||||||
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
|
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
|
||||||
onDelete: "cascade"
|
onDelete: "cascade"
|
||||||
}),
|
}),
|
||||||
|
headers: text("headers"), // comma-separated list of headers to add to the request
|
||||||
});
|
});
|
||||||
|
|
||||||
export const targets = pgTable("targets", {
|
export const targets = pgTable("targets", {
|
||||||
|
|||||||
@@ -107,7 +107,8 @@ export const resources = sqliteTable("resources", {
|
|||||||
enableProxy: integer("enableProxy", { mode: "boolean" }).default(true),
|
enableProxy: integer("enableProxy", { mode: "boolean" }).default(true),
|
||||||
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
|
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
|
||||||
onDelete: "cascade"
|
onDelete: "cascade"
|
||||||
})
|
}),
|
||||||
|
headers: text("headers"), // comma-separated list of headers to add to the request
|
||||||
});
|
});
|
||||||
|
|
||||||
export const targets = sqliteTable("targets", {
|
export const targets = sqliteTable("targets", {
|
||||||
|
|||||||
@@ -120,6 +120,17 @@ export async function updateResources(
|
|||||||
const http = resourceData.protocol == "http";
|
const http = resourceData.protocol == "http";
|
||||||
const protocol =
|
const protocol =
|
||||||
resourceData.protocol == "http" ? "tcp" : resourceData.protocol;
|
resourceData.protocol == "http" ? "tcp" : resourceData.protocol;
|
||||||
|
const resourceEnabled = resourceData.enabled == undefined || resourceData.enabled == null ? true : resourceData.enabled;
|
||||||
|
let headers = "";
|
||||||
|
for (const headerObj of resourceData.headers || []) {
|
||||||
|
for (const [key, value] of Object.entries(headerObj)) {
|
||||||
|
headers += `${key}: ${value},`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if there are headers, remove the trailing comma
|
||||||
|
if (headers.endsWith(",")) {
|
||||||
|
headers = headers.slice(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
if (existingResource) {
|
if (existingResource) {
|
||||||
let domain;
|
let domain;
|
||||||
@@ -152,7 +163,7 @@ export async function updateResources(
|
|||||||
fullDomain: http ? resourceData["full-domain"] : null,
|
fullDomain: http ? resourceData["full-domain"] : null,
|
||||||
subdomain: domain ? domain.subdomain : null,
|
subdomain: domain ? domain.subdomain : null,
|
||||||
domainId: domain ? domain.domainId : null,
|
domainId: domain ? domain.domainId : null,
|
||||||
enabled: resourceData.enabled ? true : false,
|
enabled: resourceEnabled,
|
||||||
sso: resourceData.auth?.["sso-enabled"] || false,
|
sso: resourceData.auth?.["sso-enabled"] || false,
|
||||||
ssl: resourceData.ssl ? true : false,
|
ssl: resourceData.ssl ? true : false,
|
||||||
setHostHeader: resourceData["host-header"] || null,
|
setHostHeader: resourceData["host-header"] || null,
|
||||||
@@ -161,7 +172,8 @@ export async function updateResources(
|
|||||||
"whitelist-users"
|
"whitelist-users"
|
||||||
]
|
]
|
||||||
? resourceData.auth["whitelist-users"].length > 0
|
? resourceData.auth["whitelist-users"].length > 0
|
||||||
: false
|
: false,
|
||||||
|
headers: headers || null,
|
||||||
})
|
})
|
||||||
.where(
|
.where(
|
||||||
eq(resources.resourceId, existingResource.resourceId)
|
eq(resources.resourceId, existingResource.resourceId)
|
||||||
@@ -379,11 +391,12 @@ export async function updateResources(
|
|||||||
fullDomain: http ? resourceData["full-domain"] : null,
|
fullDomain: http ? resourceData["full-domain"] : null,
|
||||||
subdomain: domain ? domain.subdomain : null,
|
subdomain: domain ? domain.subdomain : null,
|
||||||
domainId: domain ? domain.domainId : null,
|
domainId: domain ? domain.domainId : null,
|
||||||
enabled: resourceData.enabled ? true : false,
|
enabled: resourceEnabled,
|
||||||
sso: resourceData.auth?.["sso-enabled"] || false,
|
sso: resourceData.auth?.["sso-enabled"] || false,
|
||||||
setHostHeader: resourceData["host-header"] || null,
|
setHostHeader: resourceData["host-header"] || null,
|
||||||
tlsServerName: resourceData["tls-server-name"] || null,
|
tlsServerName: resourceData["tls-server-name"] || null,
|
||||||
ssl: resourceData.ssl ? true : false
|
ssl: resourceData.ssl ? true : false,
|
||||||
|
headers: headers || null
|
||||||
})
|
})
|
||||||
.returning();
|
.returning();
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ export const ResourceSchema = z
|
|||||||
targets: z.array(TargetSchema.nullable()).optional().default([]),
|
targets: z.array(TargetSchema.nullable()).optional().default([]),
|
||||||
auth: AuthSchema.optional(),
|
auth: AuthSchema.optional(),
|
||||||
"host-header": z.string().optional(),
|
"host-header": z.string().optional(),
|
||||||
"tls-server-name": z.string().optional()
|
"tls-server-name": z.string().optional(),
|
||||||
|
headers: z.array(z.record(z.string(), z.string())).optional().default([]),
|
||||||
})
|
})
|
||||||
.refine(
|
.refine(
|
||||||
(resource) => {
|
(resource) => {
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ export async function traefikConfigProvider(
|
|||||||
config.getRawConfig().traefik.site_types
|
config.getRawConfig().traefik.site_types
|
||||||
);
|
);
|
||||||
|
|
||||||
if (traefikConfig?.http?.middlewares) { // BECAUSE SOMETIMES THE CONFIG CAN BE EMPTY IF THERE IS NOTHING
|
if (traefikConfig?.http?.middlewares) {
|
||||||
|
// BECAUSE SOMETIMES THE CONFIG CAN BE EMPTY IF THERE IS NOTHING
|
||||||
traefikConfig.http.middlewares[badgerMiddlewareName] = {
|
traefikConfig.http.middlewares[badgerMiddlewareName] = {
|
||||||
plugin: {
|
plugin: {
|
||||||
[badgerMiddlewareName]: {
|
[badgerMiddlewareName]: {
|
||||||
@@ -124,6 +125,7 @@ export async function getTraefikConfig(
|
|||||||
tlsServerName: resources.tlsServerName,
|
tlsServerName: resources.tlsServerName,
|
||||||
setHostHeader: resources.setHostHeader,
|
setHostHeader: resources.setHostHeader,
|
||||||
enableProxy: resources.enableProxy,
|
enableProxy: resources.enableProxy,
|
||||||
|
headers: resources.headers,
|
||||||
// Target fields
|
// Target fields
|
||||||
targetId: targets.targetId,
|
targetId: targets.targetId,
|
||||||
targetEnabled: targets.enabled,
|
targetEnabled: targets.enabled,
|
||||||
@@ -152,7 +154,7 @@ export async function getTraefikConfig(
|
|||||||
inArray(sites.type, siteTypes),
|
inArray(sites.type, siteTypes),
|
||||||
config.getRawConfig().traefik.allow_raw_resources
|
config.getRawConfig().traefik.allow_raw_resources
|
||||||
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
|
? isNotNull(resources.http) // ignore the http check if allow_raw_resources is true
|
||||||
: eq(resources.http, true),
|
: eq(resources.http, true)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -177,7 +179,8 @@ export async function getTraefikConfig(
|
|||||||
tlsServerName: row.tlsServerName,
|
tlsServerName: row.tlsServerName,
|
||||||
setHostHeader: row.setHostHeader,
|
setHostHeader: row.setHostHeader,
|
||||||
enableProxy: row.enableProxy,
|
enableProxy: row.enableProxy,
|
||||||
targets: []
|
targets: [],
|
||||||
|
headers: row.headers
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,13 +299,52 @@ export async function getTraefikConfig(
|
|||||||
const additionalMiddlewares =
|
const additionalMiddlewares =
|
||||||
config.getRawConfig().traefik.additional_middlewares || [];
|
config.getRawConfig().traefik.additional_middlewares || [];
|
||||||
|
|
||||||
|
let routerMiddlewares = [
|
||||||
|
badgerMiddlewareName,
|
||||||
|
...additionalMiddlewares
|
||||||
|
];
|
||||||
|
|
||||||
|
if (resource.headers && resource.headers.length > 0) {
|
||||||
|
const headersMiddlewareName = `${resource.resourceId}-headers-middleware`;
|
||||||
|
// if there are headers, parse them into an object
|
||||||
|
let headersObj: { [key: string]: string } = {};
|
||||||
|
const headersArr = resource.headers.split(",");
|
||||||
|
for (const header of headersArr) {
|
||||||
|
const [key, value] = header
|
||||||
|
.split(":")
|
||||||
|
.map((s: string) => s.trim());
|
||||||
|
if (key && value) {
|
||||||
|
headersObj[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resource.setHostHeader) {
|
||||||
|
headersObj["Host"] = resource.setHostHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the object is not empty
|
||||||
|
if (Object.keys(headersObj).length > 0) {
|
||||||
|
// Add the headers middleware
|
||||||
|
if (!config_output.http.middlewares) {
|
||||||
|
config_output.http.middlewares = {};
|
||||||
|
}
|
||||||
|
config_output.http.middlewares[headersMiddlewareName] = {
|
||||||
|
headers: {
|
||||||
|
customRequestHeaders: headersObj
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
routerMiddlewares.push(headersMiddlewareName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
config_output.http.routers![routerName] = {
|
config_output.http.routers![routerName] = {
|
||||||
entryPoints: [
|
entryPoints: [
|
||||||
resource.ssl
|
resource.ssl
|
||||||
? config.getRawConfig().traefik.https_entrypoint
|
? config.getRawConfig().traefik.https_entrypoint
|
||||||
: config.getRawConfig().traefik.http_entrypoint
|
: config.getRawConfig().traefik.http_entrypoint
|
||||||
],
|
],
|
||||||
middlewares: [badgerMiddlewareName, ...additionalMiddlewares],
|
middlewares: routerMiddlewares,
|
||||||
service: serviceName,
|
service: serviceName,
|
||||||
rule: `Host(\`${fullDomain}\`)`,
|
rule: `Host(\`${fullDomain}\`)`,
|
||||||
priority: 100,
|
priority: 100,
|
||||||
@@ -413,27 +455,6 @@ export async function getTraefikConfig(
|
|||||||
serviceName
|
serviceName
|
||||||
].loadBalancer.serversTransport = transportName;
|
].loadBalancer.serversTransport = transportName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the host header middleware
|
|
||||||
if (resource.setHostHeader) {
|
|
||||||
if (!config_output.http.middlewares) {
|
|
||||||
config_output.http.middlewares = {};
|
|
||||||
}
|
|
||||||
config_output.http.middlewares[hostHeaderMiddlewareName] = {
|
|
||||||
headers: {
|
|
||||||
customRequestHeaders: {
|
|
||||||
Host: resource.setHostHeader
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (!config_output.http.routers![routerName].middlewares) {
|
|
||||||
config_output.http.routers![routerName].middlewares = [];
|
|
||||||
}
|
|
||||||
config_output.http.routers![routerName].middlewares = [
|
|
||||||
...config_output.http.routers![routerName].middlewares,
|
|
||||||
hostHeaderMiddlewareName
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Non-HTTP (TCP/UDP) configuration
|
// Non-HTTP (TCP/UDP) configuration
|
||||||
if (!resource.enableProxy) {
|
if (!resource.enableProxy) {
|
||||||
|
|||||||
Reference in New Issue
Block a user