feat(vpn): allow target profiles to grant non-vpnOnly routes by live client source IP

This commit is contained in:
2026-05-21 23:44:01 +00:00
parent 27d077feed
commit 8188b4712c
15 changed files with 667 additions and 15 deletions
+4
View File
@@ -1569,6 +1569,7 @@ export const createTargetProfileAction = targetProfilesStatePart.createAction<{
domains?: string[];
targets?: Array<{ ip: string; port: number }>;
routeRefs?: string[];
allowRoutesByClientSourceIp?: boolean;
}>(async (statePartArg, dataArg, actionContext): Promise<ITargetProfilesState> => {
const context = getActionContext();
try {
@@ -1582,6 +1583,7 @@ export const createTargetProfileAction = targetProfilesStatePart.createAction<{
domains: dataArg.domains,
targets: dataArg.targets,
routeRefs: dataArg.routeRefs,
allowRoutesByClientSourceIp: dataArg.allowRoutesByClientSourceIp,
});
if (!response.success) {
return {
@@ -1605,6 +1607,7 @@ export const updateTargetProfileAction = targetProfilesStatePart.createAction<{
domains?: string[];
targets?: Array<{ ip: string; port: number }>;
routeRefs?: string[];
allowRoutesByClientSourceIp?: boolean;
}>(async (statePartArg, dataArg, actionContext): Promise<ITargetProfilesState> => {
const context = getActionContext();
try {
@@ -1619,6 +1622,7 @@ export const updateTargetProfileAction = targetProfilesStatePart.createAction<{
domains: dataArg.domains,
targets: dataArg.targets,
routeRefs: dataArg.routeRefs,
allowRoutesByClientSourceIp: dataArg.allowRoutesByClientSourceIp,
});
if (!response.success) {
return {
@@ -97,6 +97,7 @@ export class OpsViewTargetProfiles extends DeesElement {
'Route Refs': profile.routeRefs?.length
? html`${profile.routeRefs.map(r => html`<span class="tagBadge">${this.formatRouteRef(r)}</span>`)}`
: '-',
'Client Source IP Routes': profile.allowRoutesByClientSourceIp ? 'Yes' : 'No',
Created: new Date(profile.createdAt).toLocaleDateString(),
})}
.dataActions=${[
@@ -223,6 +224,7 @@ export class OpsViewTargetProfiles extends DeesElement {
<dees-input-list .key=${'domains'} .label=${'Domains'} .placeholder=${'e.g. *.example.com'} .allowFreeform=${true}></dees-input-list>
<dees-input-list .key=${'targets'} .label=${'Targets'} .description=${'Format: ip:port, e.g. 10.0.0.1:443'} .placeholder=${'e.g. 10.0.0.1:443'} .allowFreeform=${true}></dees-input-list>
<dees-input-list .key=${'routeRefs'} .label=${'Route Refs'} .placeholder=${'Type to search routes...'} .candidates=${routeCandidates} .allowFreeform=${true}></dees-input-list>
<dees-input-checkbox .key=${'allowRoutesByClientSourceIp'} .label=${'Allow routes by VPN client source IP'} .description=${'Also grant access to non-VPN-only routes that would allow the client\'s real connecting IP'} .value=${false}></dees-input-checkbox>
</dees-form>
`,
menuOptions: [
@@ -258,6 +260,7 @@ export class OpsViewTargetProfiles extends DeesElement {
domains: domains.length > 0 ? domains : undefined,
targets: targets.length > 0 ? targets : undefined,
routeRefs: routeRefs.length > 0 ? routeRefs : undefined,
allowRoutesByClientSourceIp: data.allowRoutesByClientSourceIp === true,
});
modalArg.destroy();
},
@@ -284,6 +287,7 @@ export class OpsViewTargetProfiles extends DeesElement {
<dees-input-list .key=${'domains'} .label=${'Domains'} .placeholder=${'e.g. *.example.com'} .allowFreeform=${true} .value=${currentDomains}></dees-input-list>
<dees-input-list .key=${'targets'} .label=${'Targets'} .description=${'Format: ip:port, e.g. 10.0.0.1:443'} .placeholder=${'e.g. 10.0.0.1:443'} .allowFreeform=${true} .value=${currentTargets}></dees-input-list>
<dees-input-list .key=${'routeRefs'} .label=${'Route Refs'} .placeholder=${'Type to search routes...'} .candidates=${routeCandidates} .allowFreeform=${true} .value=${currentRouteRefs}></dees-input-list>
<dees-input-checkbox .key=${'allowRoutesByClientSourceIp'} .label=${'Allow routes by VPN client source IP'} .description=${'Also grant access to non-VPN-only routes that would allow the client\'s real connecting IP'} .value=${profile.allowRoutesByClientSourceIp === true}></dees-input-checkbox>
</dees-form>
`,
menuOptions: [
@@ -319,6 +323,7 @@ export class OpsViewTargetProfiles extends DeesElement {
domains,
targets,
routeRefs,
allowRoutesByClientSourceIp: data.allowRoutesByClientSourceIp === true,
});
modalArg.destroy();
},
@@ -389,6 +394,10 @@ export class OpsViewTargetProfiles extends DeesElement {
: '-'}
</div>
</div>
<div>
<div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};">Client Source IP Routes</div>
<div style="font-size: 14px; margin-top: 4px;">${profile.allowRoutesByClientSourceIp ? 'Enabled' : 'Disabled'}</div>
</div>
<div>
<div style="font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};">Created</div>
<div style="font-size: 14px; margin-top: 4px;">${new Date(profile.createdAt).toLocaleString()} by ${profile.createdBy}</div>
+2
View File
@@ -339,6 +339,7 @@ export class OpsViewVpn extends DeesElement {
'Status': statusHtml,
'Routing': routingHtml,
'VPN IP': client.assignedIp || '-',
'Source IP': conn?.sourceIp || '-',
'Target Profiles': this.renderTargetProfileBadges(client.targetProfileIds),
'Description': client.description || '-',
'Created': new Date(client.createdAt).toLocaleDateString(),
@@ -487,6 +488,7 @@ export class OpsViewVpn extends DeesElement {
${conn ? html`
<div class="infoItem"><span class="infoLabel">Connected Since</span><span class="infoValue">${new Date(conn.connectedSince).toLocaleString()}</span></div>
<div class="infoItem"><span class="infoLabel">Transport</span><span class="infoValue">${conn.transport}</span></div>
<div class="infoItem"><span class="infoLabel">Source IP</span><span class="infoValue">${conn.sourceIp || '-'}</span></div>
` : ''}
<div class="infoItem"><span class="infoLabel">Description</span><span class="infoValue">${client.description || '-'}</span></div>
<div class="infoItem"><span class="infoLabel">Target Profiles</span><span class="infoValue">${this.resolveProfileIdsToLabels(client.targetProfileIds)?.join(', ') || '-'}</span></div>