Compare commits

...

5 Commits

Author SHA1 Message Date
Owen Schwartz
03288d2a60 Merge pull request #2667 from LaurenceJJones/feature/newt-ipv6-format-endpoint
fix(newt): Format ipv6 targets for go
2026-03-18 15:34:36 -07:00
miloschwartz
1169b68619 fix more info content on member page 2026-03-18 12:18:18 -07:00
Laurence
d3bfd67738 fix(newt): Format ipv6 targets for go
We added support https://github.com/fosrl/newt/releases/tag/1.10.3 for ipv6 targets from newt -> application, but we need to ensure that we handle if user provides a none bracketed ipv6 string
2026-03-18 13:26:38 +00:00
miloschwartz
d44292cf33 pass access token params to badger 2026-03-17 16:57:31 -07:00
miloschwartz
2c2be50b19 change route name 2026-03-16 20:02:57 -07:00
6 changed files with 45 additions and 39 deletions

View File

@@ -286,14 +286,12 @@ export class TraefikConfigManager {
// Check non-wildcard certs for expiry (within 45 days to match
// the server-side renewal window in certificate-service)
for (const domain of domainsNeedingCerts) {
const localState =
this.lastLocalCertificateState.get(domain);
const localState = this.lastLocalCertificateState.get(domain);
if (localState?.expiresAt) {
const nowInSeconds = Math.floor(Date.now() / 1000);
const secondsUntilExpiry =
localState.expiresAt - nowInSeconds;
const daysUntilExpiry =
secondsUntilExpiry / (60 * 60 * 24);
const daysUntilExpiry = secondsUntilExpiry / (60 * 60 * 24);
if (daysUntilExpiry < 45) {
logger.info(
`Fetching certificates due to upcoming expiry for ${domain} (${Math.round(daysUntilExpiry)} days remaining)`
@@ -306,18 +304,11 @@ export class TraefikConfigManager {
// Also check wildcard certificates for expiry. These are not
// included in domainsNeedingCerts since their subdomains are
// filtered out, so we must check them separately.
for (const [certDomain, state] of this
.lastLocalCertificateState) {
if (
state.exists &&
state.wildcard &&
state.expiresAt
) {
for (const [certDomain, state] of this.lastLocalCertificateState) {
if (state.exists && state.wildcard && state.expiresAt) {
const nowInSeconds = Math.floor(Date.now() / 1000);
const secondsUntilExpiry =
state.expiresAt - nowInSeconds;
const daysUntilExpiry =
secondsUntilExpiry / (60 * 60 * 24);
const secondsUntilExpiry = state.expiresAt - nowInSeconds;
const daysUntilExpiry = secondsUntilExpiry / (60 * 60 * 24);
if (daysUntilExpiry < 45) {
logger.info(
`Fetching certificates due to upcoming expiry for wildcard cert ${certDomain} (${Math.round(daysUntilExpiry)} days remaining)`
@@ -405,14 +396,8 @@ export class TraefikConfigManager {
// their subdomains were filtered out above.
for (const [certDomain, state] of this
.lastLocalCertificateState) {
if (
state.exists &&
state.wildcard &&
state.expiresAt
) {
const nowInSeconds = Math.floor(
Date.now() / 1000
);
if (state.exists && state.wildcard && state.expiresAt) {
const nowInSeconds = Math.floor(Date.now() / 1000);
const secondsUntilExpiry =
state.expiresAt - nowInSeconds;
const daysUntilExpiry =
@@ -572,11 +557,18 @@ export class TraefikConfigManager {
config.getRawConfig().server
.session_cookie_name,
// deprecated
accessTokenQueryParam:
config.getRawConfig().server
.resource_access_token_param,
accessTokenIdHeader:
config.getRawConfig().server
.resource_access_token_headers.id,
accessTokenHeader:
config.getRawConfig().server
.resource_access_token_headers.token,
resourceSessionRequestParam:
config.getRawConfig().server
.resource_session_request_param

View File

@@ -310,7 +310,7 @@ authenticated.post(
);
authenticated.post(
"/client/:clientId/resources",
"/client/:clientId/site-resources",
verifyLimits,
verifyApiKeyHasAction(ActionsEnum.setResourceUsers),
logActionAudit(ActionsEnum.setResourceUsers),

View File

@@ -14,7 +14,11 @@ import logger from "@server/logger";
import { initPeerAddHandshake, updatePeer } from "../olm/peers";
import { eq, and } from "drizzle-orm";
import config from "@server/lib/config";
import { generateSubnetProxyTargets, SubnetProxyTarget } from "@server/lib/ip";
import {
formatEndpoint,
generateSubnetProxyTargets,
SubnetProxyTarget
} from "@server/lib/ip";
export async function buildClientConfigurationForNewtClient(
site: Site,
@@ -219,8 +223,8 @@ export async function buildTargetConfigurationForNewtClient(siteId: number) {
return acc;
}
// Format target into string
const formattedTarget = `${target.internalPort}:${target.ip}:${target.port}`;
// Format target into string (handles IPv6 bracketing)
const formattedTarget = `${target.internalPort}:${formatEndpoint(target.ip, target.port)}`;
// Add to the appropriate protocol array
if (target.protocol === "tcp") {

View File

@@ -35,9 +35,9 @@ const batchAddClientToSiteResourcesBodySchema = z
registry.registerPath({
method: "post",
path: "/client/{clientId}/resources",
path: "/client/{clientId}/site-resources",
description: "Add a machine client to multiple site resources at once.",
tags: [OpenAPITags.PrivateResource, OpenAPITags.Client],
tags: [OpenAPITags.Client],
request: {
params: batchAddClientToSiteResourcesParamsSchema,
body: {

View File

@@ -39,11 +39,18 @@ export async function traefikConfigProvider(
userSessionCookieName:
config.getRawConfig().server.session_cookie_name,
// deprecated
accessTokenQueryParam:
config.getRawConfig().server
.resource_access_token_param,
accessTokenIdHeader:
config.getRawConfig().server
.resource_access_token_headers.id,
accessTokenHeader:
config.getRawConfig().server
.resource_access_token_headers.token,
resourceSessionRequestParam:
config.getRawConfig().server
.resource_session_request_param

View File

@@ -129,6 +129,11 @@ const ResourceInfo = ({ resource }: { resource: Resource }) => {
resource.pincode ||
resource.whitelist;
const hasAnyInfo =
Boolean(resource.siteName) || Boolean(hasAuthMethods) || !resource.enabled;
if (!hasAnyInfo) return null;
const infoContent = (
<div className="flex flex-col gap-3">
{/* Site Information */}
@@ -828,6 +833,12 @@ export default function MemberResourcesPortal({
</span>
</div>
)}
<div>
<span className="font-medium">Destination:</span>
<span className="ml-2 text-muted-foreground">
{siteResource.destination}
</span>
</div>
{siteResource.alias && (
<div>
<span className="font-medium">Alias:</span>
@@ -836,14 +847,6 @@ export default function MemberResourcesPortal({
</span>
</div>
)}
{siteResource.aliasAddress && (
<div>
<span className="font-medium">Alias Address:</span>
<span className="ml-2 text-muted-foreground">
{siteResource.aliasAddress}
</span>
</div>
)}
<div>
<span className="font-medium">Status:</span>
<span className={`ml-2 ${siteResource.enabled ? 'text-green-600' : 'text-red-600'}`}>