-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconfig.example
227 lines (196 loc) · 9.15 KB
/
config.example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// This file is executed by Serial Bridge in an independent Javascript context.
// It's expected to declare a global object or function named 'config', described below.
config = {
// Optional. Configuration for the web frontend. If undefined, the web server is not started.
web: {
port: 80, // Default 80.
// Optional. Specifies the SSL certificate to use with HTTPS connections. If undefined, the webserver only speaks HTTP.
ssl: {
key: 'key.pem',
cert: 'cert.pem',
passphrase: 'secret', // If undefined, the private key must be unencrypted.
},
},
// Optional.
users: {
// A function that attempts to identify a user given their hostname. See the "Users" section below for more information.
identify: functionName,
// A flag indicating if the identify function will attempt to specify user avatars. This affects the help text the user is shown on the homepage.
avatarSupport: true,
},
// Optional. Shows a notice to users at the top of the web homepage.
notice: 'Notice here.',
// Optional.
portsFind: {
// Enable the port finding tool, used to figure out which ports correspond to which nodes.
// Giving users access to every serial port on the system has security implications, so this is disabled by default.
enabled: false,
// Each pattern set is a list of regular expressions to try and match against serial data, and which node that data will appear on.
// Users can specify their own patterns interactively; predefined sets are just to save time if the same type of device will be enrolled multiple times.
patterns: {
nameOfSet: [
{ pattern: 'This is node A\r\n', name: 'A' },
{ pattern: 'This is node B\r\n', name: 'B' },
],
},
},
// Optional. Enable reloading the configuration file to update devices without restarting the server.
configReloadable: false,
// An array of devices to connect to.
devices: [
{
name: 'Device name',
description: 'A longer description of the device.', // Optional.
category: 'Shiny devices', // Optional. Devices in the same category are grouped on the home page.
tags: [ // Optional. No effect, just displayed on the home page and optionally the device page.
'tag 1',
'tag 2',
{ name: 'tag 3', description: "Tooltip description", color: 'green' },
{ name: 'tag 4', showOnDevicePage: false },
],
// Individual ports on the device.
nodes: [
{
name: 'Node name',
comPort: 'COM<n> or /dev/pty<n>',
baudRate: 115200,
byteSize: 8, // 5, 6, 7, 8. Default 8.
parity: 'none', // even, odd, none. Default none.
stop: 1, // 1 or 2. Default 1.
tcpPort: 10000,
eol: 'crlf', // cr, lf, crlf. Default crlf. Controls what line ending is sent when a user presses Enter while writing to a node.
// Optional. An array of links to show in a node's titlebar that provide quick access to that node.
// If undefined, no links will be shown.
webLinks: [
'telnet', // Open the node's TCP port in the system's default telnet client.
'raw', // Open the node's TCP port in Putty's "raw" mode. This is Putty-specific and requires extra setup explained on the homepage.
'ssh', // Connect to the node over SSH. This is Putty-specific and requires extra setup explained on the homepage. It also requires a separate 'ssh' configuration block
],
// Optional unless 'ssh' is in webLinks.
ssh: {
host: 'hostname',
// The username and password are optional.
username: 'username',
password: 'password',
},
},
],
// Optional. The name of the Jenkins resource lock that corresponds to this device. Must also set 'jenkinsUrl' on the config root.
jenkinsLock: 'lock name',
}
],
// Optional. An array of remote Serial Bridge servers to read devices from.
remotes: [
{
name: 'Remote name',
url: 'http://example.com/',
deviceRewriter: device => device, // Optional. Function to make changes to incoming devices, e.g. to set a category or add a tag
}
],
// Optional. An array of commands the user can run from a menu on the device page.
commands: [
{
// Label to display in the menu item.
label: 'Command name',
// Icon to display in the menu item. See the "Commands" section below for more information.
icon: 'fas fa-smile',
// Exactly one of 'fn' or 'submenu' must be provided:
// Function to execute when the user clicks this command. See the "Commands" section below for more information.
fn: functionName,
// Array of commands to display beneath this submenu.
// Note that these can also be submenus, nested indefinitely.
submenu: [
{
label: 'Sub-command',
// etc.
},
],
},
],
// Optional. The path to the Jenkins installation that manages device locks.
jenkinsUrl: 'http://...',
// Optional. List of hostnames/IP addresses to block from connecting.
blacklist: [
'google.com',
'8.8.8.8',
],
};
// That's the end of the configuration block; what follows is some extra information/examples:
////////////////////////////////////////////////////////////////////////////////
// USERS:
// config.users.identify is a function that will be passed a single object containing the key 'host',
// a string that will be the user's IP address or (if available) DNS name.
// The function should set the following additional keys on that object, if available:
//
// * displayName: The user's real name.
// * email: The user's e-mail address.
// * avatar: The URL to the user's avatar.
//
// This function can be asynchronous if needed.
// The 'lookupUser' function below is an example identify function that finds a user in Active Directory.
// It uses Gravatar for the avatar provider, but this part is separate and optional.
const ActiveDirectory = require('activedirectory');
const crypto = require('crypto');
const { promisify } = require('util');
const ad = new ActiveDirectory({
url: "ldap://example.com:389",
baseDN: "dc=example,dc=com",
username: "cn=username,dc=example,dc=com",
password: "password",
});
const adLookup = promisify((username, cb) => ad.findUser(username, cb));
async function lookupUser(user) {
// At this point user.host is the only key guaranteed to be set.
// user.displayName and user.email might also be set if the user provided them manually.
if(!user.displayName) {
// Figure out the username based on the hostname. Here we assume the hostname convention is "<username>-desktop":
const match = user.host.match(/^(.+)-desktop$/);
if(!match) {
return;
}
const username = match[1];
// Set the displayName to the username for now in case this is the best we can do.
user.displayName = username;
// Try to find the user in Active Directory
const adUser = await adLookup(username);
if(!adUser) {
return;
}
// Update the displayName to the user's real name, and set the e-mail.
user.displayName = adUser.displayName;
if(adUser.mail) {
user.email = adUser.mail;
}
}
// If we have the user's e-mail (either it was passed in or we just got it from AD), set their avatar to a Gravatar URL.
if(user.email) {
const hash = crypto.createHash('md5').update(user.email.toLowerCase()).digest('hex');
user.avatar = `https://www.gravatar.com/avatar/${hash}`;
}
}
////////////////////////////////////////////////////////////////////////////////
// COMMANDS:
// When setting a command's icon, look it up on FontAwesome: https://fontawesome.com/icons?m=free .
// Set the string to the icon's full class. For example,
// https://fontawesome.com/icons/smile?style=solid is 'fas fa-smile'.
// A command's function is allowed to be asynchronous, and takes a single object argument
// containing functions to interact with the device. These functions are:
//
// getDevice() -- Returns an object containing information about the current device. This object is the same one returned by the /api/devices route, so you can open that URL in a browser for more information.
// send(nodeName: string, message: Buffer | string) -- Send the specified data to the specified node.
// sendln(nodeName: string, message: string) -- Send the specified data to the specified node, and append '\r\n'.
// recvAsync(nodeName: string, handler: (data: Buffer) => void, bufferLines: boolean = false) -- Pass incoming data from the specified node to the handler. If bufferLines is true, one complete line at a time is passed to the handler. Returns a function that can be called to stop receiving data.
// drawTermLine(label: string, caps?: 'start' | 'end') -- Draw a colored line in every terminal to delineate an event. 'caps' indicate how the end of the line should look:
// 'start': ┌─── Label ───┐
// undefined: ──── Label ────
// 'end': └─── Label ───┘
// showModal(title: string, rows: { key: string; value: string }[]) -- Show a modal dialog on the web interface. This interface is likely to change.
// This sample command sends data to the node named 'power'
const command = {
label: 'Power On',
icon: 'fas fa-plug',
async fn(api) {
api.drawTermLine('Power on');
api.send('power', 'set power = true')
},
}