mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-28 11:43:03 +00:00
Compare commits
4 Commits
316b7e5653
...
5f19918ca0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f19918ca0 | ||
|
|
2959ad0e70 | ||
|
|
a76eec7bb7 | ||
|
|
068b2a0dcd |
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -4,13 +4,13 @@
|
|||||||
},
|
},
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"[jsonc]": {
|
"[jsonc]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "vscode.json-language-features"
|
||||||
},
|
},
|
||||||
"[javascript]": {
|
"[javascript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||||
},
|
},
|
||||||
"[typescriptreact]": {
|
"[typescriptreact]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ Download the Pangolin client for your platform:
|
|||||||
- [Mac](https://pangolin.net/downloads/mac)
|
- [Mac](https://pangolin.net/downloads/mac)
|
||||||
- [Windows](https://pangolin.net/downloads/windows)
|
- [Windows](https://pangolin.net/downloads/windows)
|
||||||
- [Linux](https://pangolin.net/downloads/linux)
|
- [Linux](https://pangolin.net/downloads/linux)
|
||||||
|
- [iOS](https://pangolin.net/downloads/ios)
|
||||||
|
- [Android](https://pangolin.net/downloads/android)
|
||||||
|
|
||||||
## Get Started
|
## Get Started
|
||||||
|
|
||||||
|
|||||||
72
blueprint.py
72
blueprint.py
@@ -1,72 +0,0 @@
|
|||||||
import requests
|
|
||||||
import yaml
|
|
||||||
import json
|
|
||||||
import base64
|
|
||||||
|
|
||||||
# The file path for the YAML file to be read
|
|
||||||
# You can change this to the path of your YAML file
|
|
||||||
YAML_FILE_PATH = 'blueprint.yaml'
|
|
||||||
|
|
||||||
# The API endpoint and headers from the curl request
|
|
||||||
API_URL = 'http://api.pangolin.net/v1/org/test/blueprint'
|
|
||||||
HEADERS = {
|
|
||||||
'accept': '*/*',
|
|
||||||
'Authorization': 'Bearer <your_token_here>',
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
|
|
||||||
def convert_and_send(file_path, url, headers):
|
|
||||||
"""
|
|
||||||
Reads a YAML file, converts its content to a JSON payload,
|
|
||||||
and sends it via a PUT request to a specified URL.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# Read the YAML file content
|
|
||||||
with open(file_path, 'r') as file:
|
|
||||||
yaml_content = file.read()
|
|
||||||
|
|
||||||
# Parse the YAML string to a Python dictionary
|
|
||||||
# This will be used to ensure the YAML is valid before sending
|
|
||||||
parsed_yaml = yaml.safe_load(yaml_content)
|
|
||||||
|
|
||||||
# convert the parsed YAML to a JSON string
|
|
||||||
json_payload = json.dumps(parsed_yaml)
|
|
||||||
print("Converted JSON payload:")
|
|
||||||
print(json_payload)
|
|
||||||
|
|
||||||
# Encode the JSON string to Base64
|
|
||||||
encoded_json = base64.b64encode(json_payload.encode('utf-8')).decode('utf-8')
|
|
||||||
|
|
||||||
# Create the final payload with the base64 encoded data
|
|
||||||
final_payload = {
|
|
||||||
"blueprint": encoded_json
|
|
||||||
}
|
|
||||||
|
|
||||||
print("Sending the following Base64 encoded JSON payload:")
|
|
||||||
print(final_payload)
|
|
||||||
print("-" * 20)
|
|
||||||
|
|
||||||
# Make the PUT request with the base64 encoded payload
|
|
||||||
response = requests.put(url, headers=headers, json=final_payload)
|
|
||||||
|
|
||||||
# Print the API response for debugging
|
|
||||||
print(f"API Response Status Code: {response.status_code}")
|
|
||||||
print("API Response Content:")
|
|
||||||
print(response.text)
|
|
||||||
|
|
||||||
# Raise an exception for bad status codes (4xx or 5xx)
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
except FileNotFoundError:
|
|
||||||
print(f"Error: The file '{file_path}' was not found.")
|
|
||||||
except yaml.YAMLError as e:
|
|
||||||
print(f"Error parsing YAML file: {e}")
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
print(f"An error occurred during the API request: {e}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"An unexpected error occurred: {e}")
|
|
||||||
|
|
||||||
# Run the function
|
|
||||||
if __name__ == "__main__":
|
|
||||||
convert_and_send(YAML_FILE_PATH, API_URL, HEADERS)
|
|
||||||
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
client-resources:
|
|
||||||
client-resource-nice-id-uno:
|
|
||||||
name: this is my resource
|
|
||||||
protocol: tcp
|
|
||||||
proxy-port: 3001
|
|
||||||
hostname: localhost
|
|
||||||
internal-port: 3000
|
|
||||||
site: lively-yosemite-toad
|
|
||||||
client-resource-nice-id-duce:
|
|
||||||
name: this is my resource
|
|
||||||
protocol: udp
|
|
||||||
proxy-port: 3000
|
|
||||||
hostname: localhost
|
|
||||||
internal-port: 3000
|
|
||||||
site: lively-yosemite-toad
|
|
||||||
|
|
||||||
proxy-resources:
|
|
||||||
resource-nice-id-uno:
|
|
||||||
name: this is my resource
|
|
||||||
protocol: http
|
|
||||||
full-domain: duce.test.example.com
|
|
||||||
host-header: example.com
|
|
||||||
tls-server-name: example.com
|
|
||||||
# auth:
|
|
||||||
# pincode: 123456
|
|
||||||
# password: sadfasdfadsf
|
|
||||||
# sso-enabled: true
|
|
||||||
# sso-roles:
|
|
||||||
# - Member
|
|
||||||
# sso-users:
|
|
||||||
# - owen@pangolin.net
|
|
||||||
# whitelist-users:
|
|
||||||
# - owen@pangolin.net
|
|
||||||
# auto-login-idp: 1
|
|
||||||
headers:
|
|
||||||
- name: X-Example-Header
|
|
||||||
value: example-value
|
|
||||||
- name: X-Another-Header
|
|
||||||
value: another-value
|
|
||||||
rules:
|
|
||||||
- action: allow
|
|
||||||
match: ip
|
|
||||||
value: 1.1.1.1
|
|
||||||
- action: deny
|
|
||||||
match: cidr
|
|
||||||
value: 2.2.2.2/32
|
|
||||||
- action: pass
|
|
||||||
match: path
|
|
||||||
value: /admin
|
|
||||||
targets:
|
|
||||||
- site: lively-yosemite-toad
|
|
||||||
path: /path
|
|
||||||
pathMatchType: prefix
|
|
||||||
hostname: localhost
|
|
||||||
method: http
|
|
||||||
port: 8000
|
|
||||||
- site: slim-alpine-chipmunk
|
|
||||||
hostname: localhost
|
|
||||||
path: /yoman
|
|
||||||
pathMatchType: exact
|
|
||||||
method: http
|
|
||||||
port: 8001
|
|
||||||
resource-nice-id-duce:
|
|
||||||
name: this is other resource
|
|
||||||
protocol: tcp
|
|
||||||
proxy-port: 3000
|
|
||||||
targets:
|
|
||||||
- site: lively-yosemite-toad
|
|
||||||
hostname: localhost
|
|
||||||
port: 3000
|
|
||||||
@@ -31,7 +31,7 @@ import { pickPort } from "@server/routers/target/helpers";
|
|||||||
import { resourcePassword } from "@server/db";
|
import { resourcePassword } from "@server/db";
|
||||||
import { hashPassword } from "@server/auth/password";
|
import { hashPassword } from "@server/auth/password";
|
||||||
import { isValidCIDR, isValidIP, isValidUrlGlobPattern } from "../validators";
|
import { isValidCIDR, isValidIP, isValidUrlGlobPattern } from "../validators";
|
||||||
import { isLicensedOrSubscribed } from "../isLicencedOrSubscribed";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
|
|
||||||
export type ProxyResourcesResults = {
|
export type ProxyResourcesResults = {
|
||||||
@@ -213,11 +213,7 @@ export async function updateProxyResources(
|
|||||||
// Update existing resource
|
// Update existing resource
|
||||||
|
|
||||||
const isLicensed = await isLicensedOrSubscribed(orgId);
|
const isLicensed = await isLicensedOrSubscribed(orgId);
|
||||||
if (build == "enterprise" && !isLicensed) {
|
if (!isLicensed) {
|
||||||
logger.warn(
|
|
||||||
"Server is not licensed! Clearing set maintenance screen values"
|
|
||||||
);
|
|
||||||
// null the maintenance mode fields if not licensed
|
|
||||||
resourceData.maintenance = undefined;
|
resourceData.maintenance = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -653,11 +649,7 @@ export async function updateProxyResources(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isLicensed = await isLicensedOrSubscribed(orgId);
|
const isLicensed = await isLicensedOrSubscribed(orgId);
|
||||||
if (build == "enterprise" && !isLicensed) {
|
if (!isLicensed) {
|
||||||
logger.warn(
|
|
||||||
"Server is not licensed! Clearing set maintenance screen values"
|
|
||||||
);
|
|
||||||
// null the maintenance mode fields if not licensed
|
|
||||||
resourceData.maintenance = undefined;
|
resourceData.maintenance = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
} from "@server/db";
|
} from "@server/db";
|
||||||
import { getUniqueClientName } from "@server/db/names";
|
import { getUniqueClientName } from "@server/db/names";
|
||||||
import { getNextAvailableClientSubnet } from "@server/lib/ip";
|
import { getNextAvailableClientSubnet } from "@server/lib/ip";
|
||||||
import { isLicensedOrSubscribed } from "@server/lib/isLicencedOrSubscribed";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
import { sendTerminateClient } from "@server/routers/client/terminate";
|
import { sendTerminateClient } from "@server/routers/client/terminate";
|
||||||
import { and, eq, notInArray, type InferInsertModel } from "drizzle-orm";
|
import { and, eq, notInArray, type InferInsertModel } from "drizzle-orm";
|
||||||
|
|||||||
@@ -1,17 +1,3 @@
|
|||||||
import { build } from "@server/build";
|
|
||||||
import license from "#dynamic/license/license";
|
|
||||||
import { getOrgTierData } from "#dynamic/lib/billing";
|
|
||||||
import { TierId } from "@server/lib/billing/tiers";
|
|
||||||
|
|
||||||
export async function isLicensedOrSubscribed(orgId: string): Promise<boolean> {
|
export async function isLicensedOrSubscribed(orgId: string): Promise<boolean> {
|
||||||
if (build === "enterprise") {
|
return false;
|
||||||
return await license.isUnlocked();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (build === "saas") {
|
|
||||||
const { tier } = await getOrgTierData(orgId);
|
|
||||||
return tier === TierId.STANDARD;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
30
server/private/lib/isLicencedOrSubscribed.ts
Normal file
30
server/private/lib/isLicencedOrSubscribed.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of a proprietary work.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 Fossorial, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is licensed under the Fossorial Commercial License.
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
* Unauthorized use, copying, modification, or distribution is strictly prohibited.
|
||||||
|
*
|
||||||
|
* This file is not licensed under the AGPLv3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { build } from "@server/build";
|
||||||
|
import license from "#private/license/license";
|
||||||
|
import { getOrgTierData } from "#private/lib/billing";
|
||||||
|
import { TierId } from "@server/lib/billing/tiers";
|
||||||
|
|
||||||
|
export async function isLicensedOrSubscribed(orgId: string): Promise<boolean> {
|
||||||
|
if (build === "enterprise") {
|
||||||
|
return await license.isUnlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (build === "saas") {
|
||||||
|
const { tier } = await getOrgTierData(orgId);
|
||||||
|
return tier === TierId.STANDARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -26,7 +26,8 @@ const applyBlueprintSchema = z
|
|||||||
message: `Invalid YAML: ${error instanceof Error ? error.message : "Unknown error"}`
|
message: `Invalid YAML: ${error instanceof Error ? error.message : "Unknown error"}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
|
source: z.enum(["API", "UI", "CLI"]).optional()
|
||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ export async function applyYAMLBlueprint(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { blueprint: contents, name } = parsedBody.data;
|
const { blueprint: contents, name, source = "UI" } = parsedBody.data;
|
||||||
|
|
||||||
logger.debug(`Received blueprint:`, contents);
|
logger.debug(`Received blueprint:`, contents);
|
||||||
|
|
||||||
@@ -107,7 +108,7 @@ export async function applyYAMLBlueprint(
|
|||||||
blueprint = await applyBlueprint({
|
blueprint = await applyBlueprint({
|
||||||
orgId,
|
orgId,
|
||||||
name,
|
name,
|
||||||
source: "UI",
|
source,
|
||||||
configData: parsedConfig
|
configData: parsedConfig
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Blueprint } from "@server/db";
|
import type { Blueprint } from "@server/db";
|
||||||
|
|
||||||
export type BlueprintSource = "API" | "UI" | "NEWT";
|
export type BlueprintSource = "API" | "UI" | "NEWT" | "CLI";
|
||||||
|
|
||||||
export type BlueprintData = Omit<Blueprint, "source"> & {
|
export type BlueprintData = Omit<Blueprint, "source"> & {
|
||||||
source: BlueprintSource;
|
source: BlueprintSource;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { fromError } from "zod-validation-error";
|
|||||||
import { OpenAPITags, registry } from "@server/openApi";
|
import { OpenAPITags, registry } from "@server/openApi";
|
||||||
import { getUserDeviceName } from "@server/db/names";
|
import { getUserDeviceName } from "@server/db/names";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { isLicensedOrSubscribed } from "@server/lib/isLicencedOrSubscribed";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
|
|
||||||
const getClientSchema = z.strictObject({
|
const getClientSchema = z.strictObject({
|
||||||
clientId: z
|
clientId: z
|
||||||
@@ -78,58 +78,108 @@ function getPlatformPostureData(
|
|||||||
|
|
||||||
// Windows: Hard drive encryption, Firewall, Auto updates, TPM availability, Windows Antivirus status
|
// Windows: Hard drive encryption, Firewall, Auto updates, TPM availability, Windows Antivirus status
|
||||||
if (normalizedPlatform === "windows") {
|
if (normalizedPlatform === "windows") {
|
||||||
if (fingerprint.diskEncrypted !== null && fingerprint.diskEncrypted !== undefined) {
|
if (
|
||||||
|
fingerprint.diskEncrypted !== null &&
|
||||||
|
fingerprint.diskEncrypted !== undefined
|
||||||
|
) {
|
||||||
posture.diskEncrypted = fingerprint.diskEncrypted;
|
posture.diskEncrypted = fingerprint.diskEncrypted;
|
||||||
}
|
}
|
||||||
if (fingerprint.firewallEnabled !== null && fingerprint.firewallEnabled !== undefined) {
|
if (
|
||||||
|
fingerprint.firewallEnabled !== null &&
|
||||||
|
fingerprint.firewallEnabled !== undefined
|
||||||
|
) {
|
||||||
posture.firewallEnabled = fingerprint.firewallEnabled;
|
posture.firewallEnabled = fingerprint.firewallEnabled;
|
||||||
}
|
}
|
||||||
if (fingerprint.tpmAvailable !== null && fingerprint.tpmAvailable !== undefined) {
|
if (
|
||||||
|
fingerprint.tpmAvailable !== null &&
|
||||||
|
fingerprint.tpmAvailable !== undefined
|
||||||
|
) {
|
||||||
posture.tpmAvailable = fingerprint.tpmAvailable;
|
posture.tpmAvailable = fingerprint.tpmAvailable;
|
||||||
}
|
}
|
||||||
if (fingerprint.windowsAntivirusEnabled !== null && fingerprint.windowsAntivirusEnabled !== undefined) {
|
if (
|
||||||
posture.windowsAntivirusEnabled = fingerprint.windowsAntivirusEnabled;
|
fingerprint.windowsAntivirusEnabled !== null &&
|
||||||
|
fingerprint.windowsAntivirusEnabled !== undefined
|
||||||
|
) {
|
||||||
|
posture.windowsAntivirusEnabled =
|
||||||
|
fingerprint.windowsAntivirusEnabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// macOS: Hard drive encryption, Biometric configuration, Firewall, System Integrity Protection (SIP), Gatekeeper, Firewall stealth mode
|
// macOS: Hard drive encryption, Biometric configuration, Firewall, System Integrity Protection (SIP), Gatekeeper, Firewall stealth mode
|
||||||
else if (normalizedPlatform === "macos") {
|
else if (normalizedPlatform === "macos") {
|
||||||
if (fingerprint.diskEncrypted !== null && fingerprint.diskEncrypted !== undefined) {
|
if (
|
||||||
|
fingerprint.diskEncrypted !== null &&
|
||||||
|
fingerprint.diskEncrypted !== undefined
|
||||||
|
) {
|
||||||
posture.diskEncrypted = fingerprint.diskEncrypted;
|
posture.diskEncrypted = fingerprint.diskEncrypted;
|
||||||
}
|
}
|
||||||
if (fingerprint.biometricsEnabled !== null && fingerprint.biometricsEnabled !== undefined) {
|
if (
|
||||||
|
fingerprint.biometricsEnabled !== null &&
|
||||||
|
fingerprint.biometricsEnabled !== undefined
|
||||||
|
) {
|
||||||
posture.biometricsEnabled = fingerprint.biometricsEnabled;
|
posture.biometricsEnabled = fingerprint.biometricsEnabled;
|
||||||
}
|
}
|
||||||
if (fingerprint.firewallEnabled !== null && fingerprint.firewallEnabled !== undefined) {
|
if (
|
||||||
|
fingerprint.firewallEnabled !== null &&
|
||||||
|
fingerprint.firewallEnabled !== undefined
|
||||||
|
) {
|
||||||
posture.firewallEnabled = fingerprint.firewallEnabled;
|
posture.firewallEnabled = fingerprint.firewallEnabled;
|
||||||
}
|
}
|
||||||
if (fingerprint.macosSipEnabled !== null && fingerprint.macosSipEnabled !== undefined) {
|
if (
|
||||||
|
fingerprint.macosSipEnabled !== null &&
|
||||||
|
fingerprint.macosSipEnabled !== undefined
|
||||||
|
) {
|
||||||
posture.macosSipEnabled = fingerprint.macosSipEnabled;
|
posture.macosSipEnabled = fingerprint.macosSipEnabled;
|
||||||
}
|
}
|
||||||
if (fingerprint.macosGatekeeperEnabled !== null && fingerprint.macosGatekeeperEnabled !== undefined) {
|
if (
|
||||||
|
fingerprint.macosGatekeeperEnabled !== null &&
|
||||||
|
fingerprint.macosGatekeeperEnabled !== undefined
|
||||||
|
) {
|
||||||
posture.macosGatekeeperEnabled = fingerprint.macosGatekeeperEnabled;
|
posture.macosGatekeeperEnabled = fingerprint.macosGatekeeperEnabled;
|
||||||
}
|
}
|
||||||
if (fingerprint.macosFirewallStealthMode !== null && fingerprint.macosFirewallStealthMode !== undefined) {
|
if (
|
||||||
posture.macosFirewallStealthMode = fingerprint.macosFirewallStealthMode;
|
fingerprint.macosFirewallStealthMode !== null &&
|
||||||
|
fingerprint.macosFirewallStealthMode !== undefined
|
||||||
|
) {
|
||||||
|
posture.macosFirewallStealthMode =
|
||||||
|
fingerprint.macosFirewallStealthMode;
|
||||||
}
|
}
|
||||||
if (fingerprint.autoUpdatesEnabled !== null && fingerprint.autoUpdatesEnabled !== undefined) {
|
if (
|
||||||
|
fingerprint.autoUpdatesEnabled !== null &&
|
||||||
|
fingerprint.autoUpdatesEnabled !== undefined
|
||||||
|
) {
|
||||||
posture.autoUpdatesEnabled = fingerprint.autoUpdatesEnabled;
|
posture.autoUpdatesEnabled = fingerprint.autoUpdatesEnabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Linux: Hard drive encryption, Firewall, AppArmor, SELinux, TPM availability
|
// Linux: Hard drive encryption, Firewall, AppArmor, SELinux, TPM availability
|
||||||
else if (normalizedPlatform === "linux") {
|
else if (normalizedPlatform === "linux") {
|
||||||
if (fingerprint.diskEncrypted !== null && fingerprint.diskEncrypted !== undefined) {
|
if (
|
||||||
|
fingerprint.diskEncrypted !== null &&
|
||||||
|
fingerprint.diskEncrypted !== undefined
|
||||||
|
) {
|
||||||
posture.diskEncrypted = fingerprint.diskEncrypted;
|
posture.diskEncrypted = fingerprint.diskEncrypted;
|
||||||
}
|
}
|
||||||
if (fingerprint.firewallEnabled !== null && fingerprint.firewallEnabled !== undefined) {
|
if (
|
||||||
|
fingerprint.firewallEnabled !== null &&
|
||||||
|
fingerprint.firewallEnabled !== undefined
|
||||||
|
) {
|
||||||
posture.firewallEnabled = fingerprint.firewallEnabled;
|
posture.firewallEnabled = fingerprint.firewallEnabled;
|
||||||
}
|
}
|
||||||
if (fingerprint.linuxAppArmorEnabled !== null && fingerprint.linuxAppArmorEnabled !== undefined) {
|
if (
|
||||||
|
fingerprint.linuxAppArmorEnabled !== null &&
|
||||||
|
fingerprint.linuxAppArmorEnabled !== undefined
|
||||||
|
) {
|
||||||
posture.linuxAppArmorEnabled = fingerprint.linuxAppArmorEnabled;
|
posture.linuxAppArmorEnabled = fingerprint.linuxAppArmorEnabled;
|
||||||
}
|
}
|
||||||
if (fingerprint.linuxSELinuxEnabled !== null && fingerprint.linuxSELinuxEnabled !== undefined) {
|
if (
|
||||||
|
fingerprint.linuxSELinuxEnabled !== null &&
|
||||||
|
fingerprint.linuxSELinuxEnabled !== undefined
|
||||||
|
) {
|
||||||
posture.linuxSELinuxEnabled = fingerprint.linuxSELinuxEnabled;
|
posture.linuxSELinuxEnabled = fingerprint.linuxSELinuxEnabled;
|
||||||
}
|
}
|
||||||
if (fingerprint.tpmAvailable !== null && fingerprint.tpmAvailable !== undefined) {
|
if (
|
||||||
|
fingerprint.tpmAvailable !== null &&
|
||||||
|
fingerprint.tpmAvailable !== undefined
|
||||||
|
) {
|
||||||
posture.tpmAvailable = fingerprint.tpmAvailable;
|
posture.tpmAvailable = fingerprint.tpmAvailable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +189,10 @@ function getPlatformPostureData(
|
|||||||
}
|
}
|
||||||
// Android: Screen lock, Biometric configuration, Hard drive encryption
|
// Android: Screen lock, Biometric configuration, Hard drive encryption
|
||||||
else if (normalizedPlatform === "android") {
|
else if (normalizedPlatform === "android") {
|
||||||
if (fingerprint.diskEncrypted !== null && fingerprint.diskEncrypted !== undefined) {
|
if (
|
||||||
|
fingerprint.diskEncrypted !== null &&
|
||||||
|
fingerprint.diskEncrypted !== undefined
|
||||||
|
) {
|
||||||
posture.diskEncrypted = fingerprint.diskEncrypted;
|
posture.diskEncrypted = fingerprint.diskEncrypted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,7 +306,6 @@ export async function getClient(
|
|||||||
// Build posture data if available (platform-specific)
|
// Build posture data if available (platform-specific)
|
||||||
// Only return posture data if org is licensed/subscribed
|
// Only return posture data if org is licensed/subscribed
|
||||||
let postureData: PostureData | null = null;
|
let postureData: PostureData | null = null;
|
||||||
if (build !== "oss") {
|
|
||||||
const isOrgLicensed = await isLicensedOrSubscribed(
|
const isOrgLicensed = await isLicensedOrSubscribed(
|
||||||
client.clients.orgId
|
client.clients.orgId
|
||||||
);
|
);
|
||||||
@@ -263,7 +315,6 @@ export async function getClient(
|
|||||||
client.currentFingerprint
|
client.currentFingerprint
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const data: GetClientResponse = {
|
const data: GetClientResponse = {
|
||||||
...client.clients,
|
...client.clients,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { build } from "@server/build";
|
|||||||
import { getOrgTierData } from "#dynamic/lib/billing";
|
import { getOrgTierData } from "#dynamic/lib/billing";
|
||||||
import { TierId } from "@server/lib/billing/tiers";
|
import { TierId } from "@server/lib/billing/tiers";
|
||||||
import { cache } from "@server/lib/cache";
|
import { cache } from "@server/lib/cache";
|
||||||
import { isLicensedOrSubscribed } from "@server/lib/isLicencedOrSubscribed";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
|
|
||||||
const updateOrgParamsSchema = z.strictObject({
|
const updateOrgParamsSchema = z.strictObject({
|
||||||
orgId: z.string()
|
orgId: z.string()
|
||||||
@@ -89,7 +89,7 @@ export async function updateOrg(
|
|||||||
const { orgId } = parsedParams.data;
|
const { orgId } = parsedParams.data;
|
||||||
|
|
||||||
const isLicensed = await isLicensedOrSubscribed(orgId);
|
const isLicensed = await isLicensedOrSubscribed(orgId);
|
||||||
if (build == "enterprise" && !isLicensed) {
|
if (!isLicensed) {
|
||||||
parsedBody.data.requireTwoFactor = undefined;
|
parsedBody.data.requireTwoFactor = undefined;
|
||||||
parsedBody.data.maxSessionLengthHours = undefined;
|
parsedBody.data.maxSessionLengthHours = undefined;
|
||||||
parsedBody.data.passwordExpiryDays = undefined;
|
parsedBody.data.passwordExpiryDays = undefined;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { OpenAPITags } from "@server/openApi";
|
|||||||
import { createCertificate } from "#dynamic/routers/certificates/createCertificate";
|
import { createCertificate } from "#dynamic/routers/certificates/createCertificate";
|
||||||
import { validateAndConstructDomain } from "@server/lib/domainUtils";
|
import { validateAndConstructDomain } from "@server/lib/domainUtils";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { isLicensedOrSubscribed } from "@server/lib/isLicencedOrSubscribed";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
|
|
||||||
const updateResourceParamsSchema = z.strictObject({
|
const updateResourceParamsSchema = z.strictObject({
|
||||||
resourceId: z.string().transform(Number).pipe(z.int().positive())
|
resourceId: z.string().transform(Number).pipe(z.int().positive())
|
||||||
@@ -342,11 +342,7 @@ async function updateHttpResource(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isLicensed = await isLicensedOrSubscribed(resource.orgId);
|
const isLicensed = await isLicensedOrSubscribed(resource.orgId);
|
||||||
if (build == "enterprise" && !isLicensed) {
|
if (!isLicensed) {
|
||||||
logger.warn(
|
|
||||||
"Server is not licensed! Clearing set maintenance screen values"
|
|
||||||
);
|
|
||||||
// null the maintenance mode fields if not licensed
|
|
||||||
updateData.maintenanceModeEnabled = undefined;
|
updateData.maintenanceModeEnabled = undefined;
|
||||||
updateData.maintenanceModeType = undefined;
|
updateData.maintenanceModeType = undefined;
|
||||||
updateData.maintenanceTitle = undefined;
|
updateData.maintenanceTitle = undefined;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { ActionsEnum } from "@server/auth/actions";
|
|||||||
import { eq, and } from "drizzle-orm";
|
import { eq, and } from "drizzle-orm";
|
||||||
import { OpenAPITags, registry } from "@server/openApi";
|
import { OpenAPITags, registry } from "@server/openApi";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { isLicensedOrSubscribed } from "@server/lib/isLicencedOrSubscribed";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
|
|
||||||
const createRoleParamsSchema = z.strictObject({
|
const createRoleParamsSchema = z.strictObject({
|
||||||
orgId: z.string()
|
orgId: z.string()
|
||||||
@@ -101,7 +101,7 @@ export async function createRole(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isLicensed = await isLicensedOrSubscribed(orgId);
|
const isLicensed = await isLicensedOrSubscribed(orgId);
|
||||||
if (build === "oss" || !isLicensed) {
|
if (!isLicensed) {
|
||||||
roleData.requireDeviceApproval = undefined;
|
roleData.requireDeviceApproval = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ import HttpCode from "@server/types/HttpCode";
|
|||||||
import createHttpError from "http-errors";
|
import createHttpError from "http-errors";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
import { fromError } from "zod-validation-error";
|
import { fromError } from "zod-validation-error";
|
||||||
import { build } from "@server/build";
|
import { isLicensedOrSubscribed } from "#dynamic/lib/isLicencedOrSubscribed";
|
||||||
import { isLicensedOrSubscribed } from "@server/lib/isLicencedOrSubscribed";
|
|
||||||
import { OpenAPITags, registry } from "@server/openApi";
|
import { OpenAPITags, registry } from "@server/openApi";
|
||||||
|
|
||||||
const updateRoleParamsSchema = z.strictObject({
|
const updateRoleParamsSchema = z.strictObject({
|
||||||
@@ -112,7 +111,7 @@ export async function updateRole(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isLicensed = await isLicensedOrSubscribed(orgId);
|
const isLicensed = await isLicensedOrSubscribed(orgId);
|
||||||
if (build === "oss" || !isLicensed) {
|
if (!isLicensed) {
|
||||||
updateData.requireDeviceApproval = undefined;
|
updateData.requireDeviceApproval = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,15 @@ export default function BlueprintDetailsForm({
|
|||||||
Dashboard
|
Dashboard
|
||||||
</Badge>
|
</Badge>
|
||||||
)}{" "}
|
)}{" "}
|
||||||
|
{blueprint.source === "CLI" && (
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className="inline-flex items-center gap-1 "
|
||||||
|
>
|
||||||
|
<Terminal className="w-3 h-3 flex-none" />
|
||||||
|
CLI
|
||||||
|
</Badge>
|
||||||
|
)}{" "}
|
||||||
</InfoSectionContent>
|
</InfoSectionContent>
|
||||||
</InfoSection>
|
</InfoSection>
|
||||||
<InfoSection>
|
<InfoSection>
|
||||||
|
|||||||
@@ -128,6 +128,19 @@ export default function BlueprintsTable({ blueprints, orgId }: Props) {
|
|||||||
</Badge>
|
</Badge>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
case "CLI": {
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
variant="secondary"
|
||||||
|
className="inline-flex items-center gap-1"
|
||||||
|
>
|
||||||
|
<span className="inline-flex items-center gap-1 ">
|
||||||
|
<Terminal className="w-3 h-3" />
|
||||||
|
CLI
|
||||||
|
</span>
|
||||||
|
</Badge>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user