Skip to content

Commit 62c1b34

Browse files
authored
Merge branch 'main' into kp/py-edge-driver
2 parents 0ab6f30 + b951332 commit 62c1b34

File tree

59 files changed

+2689
-4410
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+2689
-4410
lines changed

.github/workflows/publish.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ jobs:
213213
- edge-test
214214
- edge-tplink-smartplug
215215
- edge-ads
216+
- edge-rtde
216217
permissions:
217218
contents: read
218219
packages: write

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ config.mk
66
*/.npm_install_done
77
.vscode
88
.DS_Store
9-
/edge-ads/node_modules
9+
/edge-ads/node_modules
10+
spirit-schemas/

acs-admin/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Stage 1: Build the application
22
FROM oven/bun:1.2.0 AS builder
3+
ARG tag="(unknown version)"
34

45
# Set working directory
56
WORKDIR /app/acs-admin
@@ -10,6 +11,7 @@ RUN --mount=type=bind,from=lib,dst=/app/lib bun install --production
1011

1112
# Copy the rest of the application code
1213
COPY . .
14+
RUN echo "export const ACS_VERSION = '${tag}';" >src/lib/version.js
1315

1416
# Build the application
1517
RUN --mount=type=bind,from=lib,dst=/app/lib bun run build

acs-admin/src/App.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<img src="/favicon.svg">
1515
</div>
1616
<div class="flex flex-col gap-0.5 leading-none">
17-
<h1 class="font-bold text-base h-4">ACS</h1>
17+
<h1 class="font-bold text-base h-4">ACS {{acs_version}}</h1>
1818
<h2 class="text-gray-500 text-sm">{{s.username}}</h2>
1919
</div>
2020
</div>
@@ -97,6 +97,7 @@ import NewClusterDialog from '@components/EdgeManager/EdgeClusters/NewClusterDia
9797
import NewEdgeDeploymentDialog from '@components/EdgeManager/Nodes/NewEdgeDeploymentDialog.vue'
9898
import NewConnectionDialog from '@components/EdgeManager/Connections/NewConnectionDialog.vue'
9999
import NewDeviceDialog from '@components/EdgeManager/Devices/NewDeviceDialog.vue'
100+
import { ACS_VERSION } from '@/lib/version.js'
100101
101102
export default {
102103
name: 'App',
@@ -105,6 +106,7 @@ export default {
105106
const { escape } = useMagicKeys()
106107
107108
return {
109+
acs_version: ACS_VERSION,
108110
s: useServiceClientStore(),
109111
l: useLayoutStore(),
110112
escape,

acs-admin/src/lib/version.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const ACS_VERSION = "(dev)";

acs-admin/src/pages/EdgeManager/EdgeClusters/hostColumns.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface Host {
1414
control_plane: boolean,
1515
os_version: string,
1616
ready: boolean,
17+
specialised: string,
1718
}
1819

1920
export const hostColumns: ColumnDef<Host>[] = [
@@ -77,6 +78,20 @@ export const hostColumns: ColumnDef<Host>[] = [
7778
return value.includes(row.getValue(id))
7879
},
7980
},
81+
{
82+
accessorKey: 'specialised',
83+
accessorFn: (row) => row.specialised,
84+
header: ({column}) => h(DataTableColumnHeader, {
85+
column,
86+
title: 'Taint'
87+
}),
88+
cell: ({row}) => {
89+
return h('div', {class: 'max-w-[500px] truncate'}, row.getValue('specialised'))
90+
},
91+
filterFn: (row, id, value) => {
92+
return value.includes(row.getValue(id))
93+
},
94+
},
8095
{
8196
accessorKey: 'ready',
8297
accessorFn: (row) => row.ready,

acs-auth/bin/authn.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import AuthZ from "../lib/authz.js";
1616
import { DataFlow } from "../lib/dataflow.js";
1717
import { Loader } from "../lib/loader.js";
1818
import Model from "../lib/model.js";
19+
import { AuthNotify } from "../lib/notify.js";
1920
import Editor from "../lib/editor.js";
2021

2122
import { GIT_VERSION } from "../lib/git-version.js";
@@ -26,6 +27,8 @@ const Version = "2.0.0";
2627
const fplus = new RxClient({ env: process.env });
2728
const debug = fplus.debug;
2829

30+
debug.log("app", "Starting acs-auth revision %s", GIT_VERSION);
31+
2932
const model = await new Model({ debug, }).init();
3033
const data = new DataFlow({
3134
fplus, model,
@@ -73,5 +76,14 @@ const api = await new WebAPI({
7376
},
7477
}).init();
7578

79+
const notify = new AuthNotify({
80+
api, data,
81+
debug: fplus.debug,
82+
});
83+
84+
debug.log("app", "Running data");
7685
data.run();
86+
debug.log("app", "Running notify");
87+
notify.run();
88+
debug.log("app", "Running api");
7789
api.run();

acs-auth/lib/api_v2.js

Lines changed: 22 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -176,44 +176,31 @@ export class APIv2 {
176176
/* XXX The permissions here only handle Kerberos identities. */
177177

178178
async id_list (req, res) {
179-
const tok = await this.data.check_targ(req.auth, Perm.ReadKrb, true);
180-
if (!tok) fail(403);
181-
182-
const ids = await this.data.find_identities(i => tok(i.uuid));
183-
const rv = [...new Set(ids.map(i => i.uuid))];
179+
const idr = await this.data.find_identities(req.auth);
184180

185-
return res.status(200).json(rv);
181+
idr.uniq(i => i.uuid).toExpress(res);
186182
}
187183

188-
async _id_get_all (uuid, res) {
189-
const ids = await this.data.find_identities(i => i.uuid == uuid);
190-
if (!ids.length) fail(404);
184+
async _id_get_all (upn, uuid, res) {
185+
const idr = await this.data.find_identities(upn, { uuid });
191186

192-
const rv = Object.fromEntries(
193-
ids.map(i => [i.kind, i.name])
194-
.concat([["uuid", uuid]]));
195-
return res.status(200).json(rv);
187+
idr.map(ids =>
188+
Object.fromEntries(
189+
ids.map(i => [i.kind, i.name])
190+
.concat([["uuid", uuid]])))
191+
.toExpress(res);
196192
}
197193

198194
async id_get_all (req, res) {
199195
const { uuid } = req.params;
200-
if (!valid_uuid(uuid)) fail(410);
201-
202-
await this.check_acl(req, Perm.ReadKrb, uuid);
203-
204-
return this._id_get_all(uuid, res);
196+
return this._id_get_all(req.auth, uuid, res);
205197
}
206198

207199
async id_get (req, res) {
208200
const { uuid, kind } = req.params;
209-
if (!valid_uuid(uuid)) fail(410);
210-
211-
await this.check_acl(req, Perm.ReadKrb, uuid);
212-
213-
const id = await this.data.find_identities(i => i.uuid == uuid && i.kind == kind);
214-
if (!id.length) fail(404);
215201

216-
return res.status(200).json(id[0].name);
202+
const idr = await this.data.find_identities(req.auth, { uuid, kind });
203+
idr.single().map(id => id.name).toExpress(res);
217204
}
218205

219206
async _id_put (name, req, res) {
@@ -235,52 +222,37 @@ export class APIv2 {
235222
}
236223

237224
async id_kinds (req, res) {
238-
const ids = await this.data.find_identities();
239-
const rv = [...new Set(ids.map(i => i.kind))]
240-
return res.status(200).json(rv);
225+
/* XXX This should not be hardcoded. But it cannot change at
226+
* runtime. */
227+
return res.status(200).json(["kerberos"]);
241228
}
242229

243230
async id_list_kind (req, res) {
244231
const { kind } = req.params;
245232

246-
const tok = await this.data.check_targ(req.auth, Perm.ReadKrb, true);
247-
if (!tok) fail(403);
248-
249-
const ids = await this.data.find_identities(i => i.kind == kind);
250-
if (!ids.length) fail(404);
251-
252-
const rv = ids
253-
.filter(i => tok(i.uuid))
254-
.map(i => i.name);
255-
256-
return res.status(200).json(rv);
233+
const idr = await this.data.find_identities(req.auth, { kind });
234+
idr.uniq(i => i.name).toExpress(res);
257235
}
258236

259237
async id_find (req, res) {
260238
const { kind, name } = req.params;
261239

262-
const tok = await this.data.check_targ(req.auth, Perm.ReadKrb, true);
263-
if (!tok) fail(403);
264-
265-
const ids = await this.data.find_identities(i =>
266-
i.kind == kind && i.name == name && tok(i.uuid));
267-
if (!ids.length) fail(404);
268-
269-
return res.status(200).json(ids[0].uuid);
240+
const idr = await this.data.find_identities(req.auth, { kind, name });
241+
idr.single().map(id => id.uuid).toExpress(res);
270242
}
271243

272244
/* There is no auth check here; any authenticated user can look up
273245
* their own identities. This will only look up based on Kerberos
274246
* auth identity. */
275247

276248
async id_whoami (req, res) {
277-
const uuid = await this.data.whoami(req.auth);
249+
const uuid = await this.data.find_kerberos(req.auth);
278250
if (!uuid) fail(404);
279-
return this._id_get_all(uuid, res);
251+
return this._id_get_all(this.data.root, uuid, res);
280252
}
281253

282254
async id_whoami_uuid (req, res) {
283-
const uuid = await this.data.whoami(req.auth);
255+
const uuid = await this.data.find_kerberos(req.auth);
284256
if (!uuid) fail(404);
285257
return res.status(200).json(uuid);
286258
}

acs-auth/lib/authz.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ import { booleans, valid_krb, valid_uuid } from "./validate.js";
1313

1414
export default class AuthZ {
1515
constructor(opts) {
16-
this.debug = opts.debug;
1716
this.model = opts.model;
1817
this.data = opts.data;
1918

19+
this.log = opts.debug.bound("authz");
20+
2021
this.routes = this.setup_routes();
2122
}
2223

@@ -84,17 +85,24 @@ export default class AuthZ {
8485
if (!valid_uuid(uuid))
8586
return res.status(410).end();
8687

87-
/* This API only ever returns Kerberos identities */
88-
const id = await this.data.find_identities(i =>
89-
i.uuid == uuid && i.kind == "kerberos");
90-
const kerberos = id[0]?.name;
91-
9288
/* The permissions here are odd for historical reasons. If the
9389
* principal turns out to be the client's they can look up
9490
* regardless. */
95-
const tok = await this.data.check_targ(req.auth, Perm.ReadKrb, true);
96-
if (!(kerberos == req.auth || tok?.(uuid)))
97-
return res.status(403).end();
91+
92+
/* This API only ever returns Kerberos identities */
93+
const idr = await this.data.find_identities(
94+
this.data.root, { uuid, kind: "kerberos" });
95+
const kerberos = idr.single().map(id => id.name).get();
96+
this.log("Fetched krb %s", kerberos);
97+
98+
if (kerberos == req.auth) {
99+
this.log("Permitting legacy exception for %s", req.auth);
100+
}
101+
else {
102+
const tok = await this.data.check_targ(req.auth, Perm.ReadKrb, true);
103+
if (!tok?.(uuid))
104+
return res.status(403).end();
105+
}
98106

99107
if (!kerberos) return res.status(404).end();
100108
return res.status(200).json({ uuid, kerberos });

0 commit comments

Comments
 (0)