Compare commits

..
14 changed files with 3409 additions and 2340 deletions

No files matched your search

+2 -1
View File
@@ -43,6 +43,7 @@ fi
export AUTH_AUTHORITY=${AUTH_AUTHORITY:-https://$AUTH0_DOMAIN}
export AUTH_CLIENT_ID=${AUTH_CLIENT_ID:-$AUTH0_CLIENT_ID}
export AUTH_CLIENT_SECRET=${AUTH_CLIENT_SECRET}
export AUTH_AUDIENCE=${AUTH_AUDIENCE:-$AUTH0_AUDIENCE}
export AUTH_REDIRECT_URI=${AUTH_REDIRECT_URI}
export AUTH_SILENT_REDIRECT_URI=${AUTH_SILENT_REDIRECT_URI}
@@ -57,7 +58,7 @@ export NETBIRD_TOKEN_SOURCE=${NETBIRD_TOKEN_SOURCE:-accessToken}
echo "NetBird latest version: ${NETBIRD_LATEST_VERSION}"
# replace ENVs in the config
ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_HOTJAR_TRACK_ID \$\$AUTH_REDIRECT_URI \$\$AUTH_SILENT_REDIRECT_URI \$\$NETBIRD_TOKEN_SOURCE"
ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_CLIENT_SECRET \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_HOTJAR_TRACK_ID \$\$AUTH_REDIRECT_URI \$\$AUTH_SILENT_REDIRECT_URI \$\$NETBIRD_TOKEN_SOURCE"
MAIN_JS=$(find /usr/share/nginx/html/static/js/main.*js)
OIDC_TRUSTED_DOMAINS="/usr/share/nginx/html/OidcTrustedDomains.js"
+2 -2
View File
@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="29.435" height="7.636" viewBox="0 0 29.435 7.636">
<path id="direct_bi" d="M3.64,8.158-.178,4.34,3.64.522,4.3,1.17l-2.7,2.7h25.89l-2.7-2.7.656-.648L29.257,4.34,27.213,6.384,25.439,8.158,24.783,7.5l2.7-2.693H1.595L4.3,7.5Z" transform="translate(0.178 -0.522)" fill="#1e429f"/>
<svg width="39" height="6" viewBox="0 0 39 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.451731 2.66267C0.315048 2.79935 0.315048 3.02096 0.451731 3.15764L2.67912 5.38503C2.8158 5.52171 3.03741 5.52171 3.17409 5.38503C3.31078 5.24835 3.31078 5.02674 3.17409 4.89006L1.19419 2.91016L3.17409 0.930257C3.31078 0.793574 3.31078 0.571966 3.17409 0.435282C3.03741 0.298599 2.8158 0.298599 2.67912 0.435282L0.451731 2.66267ZM38.3807 3.15764C38.5174 3.02096 38.5174 2.79935 38.3807 2.66267L36.1533 0.435282C36.0166 0.298599 35.795 0.298599 35.6583 0.435282C35.5216 0.571966 35.5216 0.793574 35.6583 0.930257L37.6382 2.91016L35.6583 4.89006C35.5216 5.02674 35.5216 5.24835 35.6583 5.38503C35.795 5.52171 36.0166 5.52171 36.1533 5.38503L38.3807 3.15764ZM0.699219 3.26016H38.1332V2.56016H0.699219V3.26016Z" fill="#03543F"/>
</svg>

Before

Width:  |  Height:  |  Size: 332 B

After

Width:  |  Height:  |  Size: 837 B

+2 -2
View File
@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="29.497" height="7.636" viewBox="0 0 29.497 7.636">
<path id="direct_out" d="M26.589,8l-.656-.656,2.7-2.693H.91V3.713H28.635l-2.7-2.7.656-.648,3.818,3.818Z" transform="translate(-0.91 -0.364)" fill="#03543f"/>
<svg width="39" height="6" viewBox="0 0 39 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M38.3807 3.15764C38.5174 3.02096 38.5174 2.79935 38.3807 2.66267L36.1533 0.435282C36.0166 0.298599 35.795 0.298599 35.6583 0.435282C35.5216 0.571966 35.5216 0.793574 35.6583 0.930257L37.6382 2.91016L35.6583 4.89006C35.5216 5.02674 35.5216 5.24835 35.6583 5.38503C35.795 5.52171 36.0166 5.52171 36.1533 5.38503L38.3807 3.15764ZM0.699219 3.26016H38.1332V2.56016H0.699219V3.26016Z" fill="#1E429F"/>
</svg>

Before

Width:  |  Height:  |  Size: 265 B

After

Width:  |  Height:  |  Size: 506 B

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+4 -3
View File
@@ -357,7 +357,7 @@ const UserEdit = () => {
<Input
disabled={user.id}
value={formUser.email}
style={{ color: "#5a5c5a" }}
style={{ color: "#8c8c8c"}}
autoComplete="off"
/>
</Form.Item>
@@ -371,10 +371,11 @@ const UserEdit = () => {
>
<Select
style={{ width: "100%" }}
disabled={user.is_current}
>
<Option value="admin">admin</Option>
<Option value="user">user</Option>
<Option value="admin"><Text type={"secondary"}>admin</Text></Option>
<Option value="user"><Text type={"secondary"}>user</Text></Option>
</Select>
</Form.Item>
</Col>
+1
View File
@@ -2,6 +2,7 @@
"auth0Auth": "$USE_AUTH0",
"authAuthority": "$AUTH_AUTHORITY",
"authClientId": "$AUTH_CLIENT_ID",
"authClientSecret": "$AUTH_CLIENT_SECRET",
"authScopesSupported": "$AUTH_SUPPORTED_SCOPES",
"authAudience": "$AUTH_AUDIENCE",
+1
View File
@@ -30,6 +30,7 @@ export function getConfig() {
auth0Auth: configJson.auth0Auth == "true", //due to substitution we can't use boolean in the config
authority: configJson.authAuthority,
clientId: configJson.authClientId,
clientSecret: configJson.authClientSecret,
scopesSupported: configJson.authScopesSupported,
apiOrigin: configJson.apiOrigin,
grpcApiOrigin: configJson.grpcApiOrigin,
+18 -1
View File
@@ -5,7 +5,7 @@ body {
background-color: #f0f2f5;
}
.ant-layout-header {
background: #fff;
padding: 0;
@@ -163,4 +163,21 @@ td.non-highlighted-table-column {
.CustomPopupCollapse .ant-collapse-header {
padding-left: 0 !important;
padding-top: 0 !important;
}
.system-info-panel .ant-collapse-header {
padding: 0 !important;
}
.system-info-panel .ant-collapse-content-box {
padding-left: 0 !important;
padding-right: 0 !important;
}
.peers-form .ant-layout-header {
line-height: 25px;
height: auto;
min-height: auto;
padding-bottom: 15px;
cursor: pointer;
}
+2 -1
View File
@@ -34,7 +34,8 @@ const providerConfig = {
// service_worker_relative_url:'/OidcServiceWorker.js',
service_worker_only: false,
authority_configuration: config.auth0Auth ? auth0AuthorityConfig : undefined,
...(config.audience ? {extras: {audience: config.audience}} : null)
...(config.audience ? {extras: {audience: config.audience}} : null),
...(config.clientSecret ? {token_request_extras: {client_secret: config.clientSecret}} : null)
};
const root = ReactDOM.createRoot(
+194 -138
View File
@@ -1,167 +1,223 @@
import { all, call, put, select, takeLatest } from 'redux-saga/effects';
import { ApiError, ApiResponse, CreateResponse, DeleteResponse } from '../../services/api-client/types';
import { Policy, PolicyRule } from './types'
import service from './service';
import serviceGroup from '../group/service';
import actions from './actions';
import { actions as groupActions } from '../group';
import { all, call, put, select, takeLatest } from "redux-saga/effects";
import {
ApiError,
ApiResponse,
CreateResponse,
DeleteResponse,
} from "../../services/api-client/types";
import { Policy, PolicyRule } from "./types";
import service from "./service";
import serviceGroup from "../group/service";
import actions from "./actions";
import { actions as groupActions } from "../group";
import { Group } from "../group/types";
export function* getPolicies(action: ReturnType<typeof actions.getPolicies.request>): Generator {
try {
export function* getPolicies(
action: ReturnType<typeof actions.getPolicies.request>
): Generator {
try {
yield put(
actions.setDeletedPolicy({
loading: false,
success: false,
failure: false,
error: null,
data: null,
} as DeleteResponse<string | null>)
);
yield put(actions.setDeletedPolicy({
loading: false,
success: false,
failure: false,
error: null,
data: null
} as DeleteResponse<string | null>))
const effect = yield call(service.getPolicies, action.payload);
const response = effect as ApiResponse<Policy[]>;
const effect = yield call(service.getPolicies, action.payload);
const response = effect as ApiResponse<Policy[]>;
yield put(actions.getPolicies.success(response.body));
} catch (err) {
yield put(actions.getPolicies.failure(err as ApiError));
}
yield put(actions.getPolicies.success(response.body));
} catch (err) {
yield put(actions.getPolicies.failure(err as ApiError));
}
}
export function* setCreatedPolicy(action: ReturnType<typeof actions.setSavedPolicy>): Generator {
yield put(actions.setSavedPolicy(action.payload))
export function* setCreatedPolicy(
action: ReturnType<typeof actions.setSavedPolicy>
): Generator {
yield put(actions.setSavedPolicy(action.payload));
}
function getNewGroupIds(dataString: string[], responses: Group[]): string[] {
return responses.filter(r => dataString.includes(r.name)).map(r => r.id || '')
return responses
.filter((r) => dataString.includes(r.name))
.map((r) => r.id || "");
}
export function* savePolicy(action: ReturnType<typeof actions.savePolicy.request>): Generator {
try {
yield put(actions.setSavedPolicy({
loading: true,
success: false,
failure: false,
error: null,
data: null
} as CreateResponse<Policy | null>))
export function* savePolicy(
action: ReturnType<typeof actions.savePolicy.request>
): Generator {
try {
yield put(
actions.setSavedPolicy({
loading: true,
success: false,
failure: false,
error: null,
data: null,
} as CreateResponse<Policy | null>)
);
const policyToSave = action.payload.payload
const responsesGroup = yield all(policyToSave.groupsToSave.map(g => call(serviceGroup.createGroup, {
getAccessTokenSilently: action.payload.getAccessTokenSilently,
payload: { name: g }
const policyToSave = action.payload.payload;
const groupsToSave = policyToSave.groupsToSave
? policyToSave.groupsToSave
: [];
const responsesGroup = yield all(
groupsToSave.map((g) =>
call(serviceGroup.createGroup, {
getAccessTokenSilently: action.payload.getAccessTokenSilently,
payload: { name: g },
})
))
)
);
const resGroups = (responsesGroup as ApiResponse<Policy>[]).filter(r => r.statusCode === 200).map(r => (r.body as Group))
const resGroups = (responsesGroup as ApiResponse<Policy>[])
.filter((r) => r.statusCode === 200)
.map((r) => r.body as Group);
const currentGroups = [...(yield select(state => state.group.data)) as Policy[]]
const newGroups = [...currentGroups, ...resGroups]
yield put(groupActions.getGroups.success(newGroups));
const currentGroups = [
...((yield select((state) => state.group.data)) as Policy[]),
];
const newGroups = [...currentGroups, ...resGroups];
yield put(groupActions.getGroups.success(newGroups));
const newSources = getNewGroupIds(policyToSave.sourcesNoId, resGroups)
const newDestinations = getNewGroupIds(policyToSave.destinationsNoId, resGroups)
const newSources = getNewGroupIds(
policyToSave.sourcesNoId ? policyToSave.sourcesNoId : [],
resGroups
);
const newDestinations = getNewGroupIds(
policyToSave.destinationsNoId ? policyToSave.destinationsNoId : [],
resGroups
);
const payloadToSave = {
getAccessTokenSilently: action.payload.getAccessTokenSilently,
payload: {
name: policyToSave.name,
description: policyToSave.description,
enabled: policyToSave.enabled,
query: policyToSave.query
} as Policy
}
if (policyToSave.rules.length > 0) {
payloadToSave.payload.rules = []
}
policyToSave.rules.forEach((r) => {
payloadToSave.payload.rules.push({
name: r.name,
description: r.description,
enabled: r.enabled,
sources: [...r.sources as string[], ...newSources],
destinations: [...r.destinations as string[], ...newDestinations],
bidirectional: r.bidirectional,
protocol: r.protocol,
ports: r.ports,
action: r.action
} as PolicyRule)
})
let effect
if (!policyToSave.id) {
effect = yield call(service.createPolicy, payloadToSave);
} else {
payloadToSave.payload.id = policyToSave.id
effect = yield call(service.editPolicy, payloadToSave);
}
const response = effect as ApiResponse<Policy>;
yield put(actions.savePolicy.success({
loading: false,
success: true,
failure: false,
error: null,
data: response.body
} as CreateResponse<Policy | null>));
yield put(groupActions.getGroups.request({ getAccessTokenSilently: action.payload.getAccessTokenSilently, payload: null }));
yield put(actions.getPolicies.request({ getAccessTokenSilently: action.payload.getAccessTokenSilently, payload: null }));
} catch (err) {
yield put(actions.savePolicy.failure({
loading: false,
success: false,
failure: true,
error: err as ApiError,
data: null
} as CreateResponse<Policy | null>));
const payloadToSave = {
getAccessTokenSilently: action.payload.getAccessTokenSilently,
payload: {
name: policyToSave.name,
description: policyToSave.description,
enabled: policyToSave.enabled,
query: policyToSave.query,
} as Policy,
};
if (policyToSave.rules.length > 0) {
payloadToSave.payload.rules = [];
}
policyToSave.rules.forEach((r) => {
payloadToSave.payload.rules.push({
name: r.name,
description: r.description,
enabled: r.enabled,
sources: [...(r.sources as string[]), ...newSources],
destinations: [...(r.destinations as string[]), ...newDestinations],
bidirectional: r.bidirectional,
protocol: r.protocol,
ports: r.ports,
action: r.action,
} as PolicyRule);
});
let effect;
if (!policyToSave.id) {
effect = yield call(service.createPolicy, payloadToSave);
} else {
payloadToSave.payload.id = policyToSave.id;
effect = yield call(service.editPolicy, payloadToSave);
}
const response = effect as ApiResponse<Policy>;
yield put(
actions.savePolicy.success({
loading: false,
success: true,
failure: false,
error: null,
data: response.body,
} as CreateResponse<Policy | null>)
);
yield put(
groupActions.getGroups.request({
getAccessTokenSilently: action.payload.getAccessTokenSilently,
payload: null,
})
);
yield put(
actions.getPolicies.request({
getAccessTokenSilently: action.payload.getAccessTokenSilently,
payload: null,
})
);
} catch (err) {
yield put(
actions.savePolicy.failure({
loading: false,
success: false,
failure: true,
error: err as ApiError,
data: null,
} as CreateResponse<Policy | null>)
);
}
}
export function* setDeletePolicy(action: ReturnType<typeof actions.setDeletedPolicy>): Generator {
yield put(actions.setDeletedPolicy(action.payload))
export function* setDeletePolicy(
action: ReturnType<typeof actions.setDeletedPolicy>
): Generator {
yield put(actions.setDeletedPolicy(action.payload));
}
export function* deletePolicy(action: ReturnType<typeof actions.deletePolicy.request>): Generator {
try {
yield call(actions.setDeletedPolicy, {
loading: true,
success: false,
failure: false,
error: null,
data: null
} as DeleteResponse<string | null>)
export function* deletePolicy(
action: ReturnType<typeof actions.deletePolicy.request>
): Generator {
try {
yield call(actions.setDeletedPolicy, {
loading: true,
success: false,
failure: false,
error: null,
data: null,
} as DeleteResponse<string | null>);
const effect = yield call(service.deletedPolicy, action.payload);
const response = effect as ApiResponse<any>;
const effect = yield call(service.deletedPolicy, action.payload);
const response = effect as ApiResponse<any>;
yield put(actions.deletePolicy.success({
loading: false,
success: true,
failure: false,
error: null,
data: response.body
} as DeleteResponse<string | null>));
yield put(
actions.deletePolicy.success({
loading: false,
success: true,
failure: false,
error: null,
data: response.body,
} as DeleteResponse<string | null>)
);
const policies = (yield select(state => state.policy.data)) as Policy[]
yield put(actions.getPolicies.success(policies.filter((p: Policy) => p.id !== action.payload.payload)))
} catch (err) {
yield put(actions.deletePolicy.failure({
loading: false,
success: false,
failure: false,
error: err as ApiError,
data: null
} as DeleteResponse<string | null>));
}
const policies = (yield select((state) => state.policy.data)) as Policy[];
yield put(
actions.getPolicies.success(
policies.filter((p: Policy) => p.id !== action.payload.payload)
)
);
} catch (err) {
yield put(
actions.deletePolicy.failure({
loading: false,
success: false,
failure: false,
error: err as ApiError,
data: null,
} as DeleteResponse<string | null>)
);
}
}
export default function* sagas(): Generator {
yield all([
takeLatest(actions.getPolicies.request, getPolicies),
takeLatest(actions.savePolicy.request, savePolicy),
takeLatest(actions.deletePolicy.request, deletePolicy)
]);
yield all([
takeLatest(actions.getPolicies.request, getPolicies),
takeLatest(actions.savePolicy.request, savePolicy),
takeLatest(actions.deletePolicy.request, deletePolicy),
]);
}
+3 -3
View File
@@ -23,7 +23,7 @@ export interface Policy {
};
export interface PolicyToSave extends Policy {
sourcesNoId: string[],
destinationsNoId: string[],
groupsToSave: string[]
sourcesNoId?: string[],
destinationsNoId?: string[],
groupsToSave?: string[]
};
File diff suppressed because it is too large. Load diff
+909 -633
View File
File diff suppressed because it is too large. Load diff