mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Website: (config builder) Add Wifi settings for Windows. (#31235)
Changes:
- Updated the configuration profile builder to support Windows settings
that have a templated setting target (e.g.,
`./Device/Vendor/MSFT/WiFi/Profile/{SSID}/WlanXml`)
- Updated the configuration profile builder to include Wi-fi settings
for Windows devices.
This commit is contained in:
parent
2ec413776e
commit
fa0b595a10
3 changed files with 206 additions and 6 deletions
|
|
@ -2508,6 +2508,176 @@ parasails.registerPage('configuration-builder', {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
subcategoryName: 'WiFi',
|
||||
subcategorySlug: 'windows-wifi',
|
||||
description: 'Settings related to wireless networks on Windows devices.',
|
||||
learnMoreLinkUrl: 'https://learn.microsoft.com/en-us/windows/client-management/mdm/wifi-csp',
|
||||
payloads: [
|
||||
{
|
||||
name: 'Add WiFi network (device scope)',
|
||||
uniqueSlug: 'windows-wifi-add-network',
|
||||
tooltip: 'This policy lets you add a Wi-Fi network on a windows device.',
|
||||
category: 'Wi-Fi',
|
||||
supportedAccessTypes: ['add', 'replace'],
|
||||
formInput: {
|
||||
type: 'multifield',
|
||||
inputs: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'Network SSID',
|
||||
slug: 'ssid',
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'Network password',
|
||||
slug: 'password',
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
label: 'Encryption type',
|
||||
slug: 'networkEncryptionType',
|
||||
options: [
|
||||
// { // TODO: these values are hidden because they require a different keyType value. https://learn.microsoft.com/en-us/windows/win32/nativewifi/wlan-profileschema-sharedkey-security-element#keymaterial
|
||||
// name: 'Open',
|
||||
// value: 'open'
|
||||
// },
|
||||
// {
|
||||
// name: 'Shared',
|
||||
// value: 'shared',
|
||||
// },
|
||||
// {
|
||||
// name: 'WPA Enterprise',
|
||||
// value: 'WPA',
|
||||
// },
|
||||
{
|
||||
name: 'WPA Personal',
|
||||
value: 'WPAPSK',
|
||||
},
|
||||
// {
|
||||
// name: 'WPA2 Enterprise',
|
||||
// value: 'WPA2',
|
||||
// },
|
||||
{
|
||||
name: 'WPA2 Personal',
|
||||
value: 'WPA2PSK',
|
||||
},
|
||||
{
|
||||
name: 'WPA3 Personal',
|
||||
value: `WPA3SAE`,
|
||||
},
|
||||
// {
|
||||
// name: 'WPA3 Enterprise 192-bit mode authentication.',
|
||||
// value: 'WPA3ENT192',
|
||||
// },
|
||||
// {
|
||||
// name: 'WPA3 Enterprise',
|
||||
// value: 'WPA2PSK',
|
||||
// },
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'booleanWithLabel',
|
||||
label: 'Automatically connect to network',
|
||||
slug: 'connectionMode',
|
||||
},
|
||||
]
|
||||
},
|
||||
formOutput: {
|
||||
settingFormat: 'chr',
|
||||
settingTargetTemplate: `./Device/Vendor/MSFT/WiFi/Profile/<%= ssid %>/WlanXml`,
|
||||
outputTemplate: `<![CDATA[<?xml version="1.0"?><WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1"><name><%= ssid %></name><SSIDConfig><SSID><name><%= ssid %></name></SSID></SSIDConfig><connectionType>ESS</connectionType><connectionMode><%= connectionMode %></connectionMode><MSM><security><authEncryption><authentication><%= networkEncryptionType %></authentication><encryption>AES</encryption><useOneX>false</useOneX><transitionMode xmlns="http://www.microsoft.com/networking/WLAN/profile/v4">true</transitionMode></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial><%= password %></keyMaterial></sharedKey></security></MSM></WLANProfile>]]>`,
|
||||
valuesToTransform: {
|
||||
'connectionMode': {
|
||||
true: 'auto',
|
||||
false: 'manual',
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Add WiFi network (user scope)',
|
||||
uniqueSlug: 'windows-wifi-add-network-user-scope',
|
||||
tooltip: 'This policy lets you add a Wi-Fi network on a windows device.',
|
||||
category: 'Wi-Fi',
|
||||
supportedAccessTypes: ['add', 'replace'],
|
||||
formInput: {
|
||||
type: 'multifield',
|
||||
inputs: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'Network SSID',
|
||||
slug: 'ssid',
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'Network password',
|
||||
slug: 'password',
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
label: 'Encryption type',
|
||||
slug: 'networkEncryptionType',
|
||||
options: [
|
||||
// { // TODO: these values are hidden because they require a different keyType value. https://learn.microsoft.com/en-us/windows/win32/nativewifi/wlan-profileschema-sharedkey-security-element#keymaterial
|
||||
// name: 'Open',
|
||||
// value: 'open'
|
||||
// },
|
||||
// {
|
||||
// name: 'Shared',
|
||||
// value: 'shared',
|
||||
// },
|
||||
// {
|
||||
// name: 'WPA Enterprise',
|
||||
// value: 'WPA',
|
||||
// },
|
||||
{
|
||||
name: 'WPA Personal',
|
||||
value: 'WPAPSK',
|
||||
},
|
||||
// {
|
||||
// name: 'WPA2 Enterprise',
|
||||
// value: 'WPA2',
|
||||
// },
|
||||
{
|
||||
name: 'WPA2 Personal',
|
||||
value: 'WPA2PSK',
|
||||
},
|
||||
{
|
||||
name: 'WPA3 Personal',
|
||||
value: `WPA3SAE`,
|
||||
},
|
||||
// {
|
||||
// name: 'WPA3 Enterprise 192-bit mode authentication.',
|
||||
// value: 'WPA3ENT192',
|
||||
// },
|
||||
// {
|
||||
// name: 'WPA3 Enterprise',
|
||||
// value: 'WPA2PSK',
|
||||
// },
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'booleanWithLabel',
|
||||
label: 'Automatically connect to network',
|
||||
slug: 'connectionMode',
|
||||
},
|
||||
]
|
||||
},
|
||||
formOutput: {
|
||||
settingFormat: 'chr',
|
||||
settingTargetTemplate: `./User/Vendor/MSFT/WiFi/Profile/<%= ssid %>/WlanXml`,
|
||||
outputTemplate: `<![CDATA[<?xml version="1.0"?><WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1"><name><%= ssid %></name><SSIDConfig><SSID><name><%= ssid %></name></SSID></SSIDConfig><connectionType>ESS</connectionType><connectionMode><%= connectionMode %></connectionMode><MSM><security><authEncryption><authentication><%= networkEncryptionType %></authentication><encryption>AES</encryption><useOneX>false</useOneX><transitionMode xmlns="http://www.microsoft.com/networking/WLAN/profile/v4">true</transitionMode></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial><%= password %></keyMaterial></sharedKey></security></MSM></WLANProfile>]]>`,
|
||||
valuesToTransform: {
|
||||
'connectionMode': {
|
||||
true: 'auto',
|
||||
false: 'manual',
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
|
|
@ -2578,6 +2748,23 @@ parasails.registerPage('configuration-builder', {
|
|||
// Get the selected access type for this payload
|
||||
let accessType = this.configurationBuilderFormData[payload.uniqueSlug+'-access-type'];
|
||||
let value;
|
||||
// If a payload uses a settingTargetTemplate, build the settting target value and add it to the payload.
|
||||
if(payloadToAdd.formOutput.settingTargetTemplate) {
|
||||
let templateToUseForSettingTarget = _.template(payloadToAdd.formOutput.settingTargetTemplate);
|
||||
let formDataForThisPayloadToBuildTheSettingTarget = {};
|
||||
if(payload.formInput.type === 'multifield') {
|
||||
for(let input of payload.formInput.inputs) {
|
||||
if(payload.formOutput.valuesToTransform && payload.formOutput.valuesToTransform[input.slug]){
|
||||
formDataForThisPayloadToBuildTheSettingTarget[input.slug] = encodeURIComponent(payload.formOutput.valuesToTransform[input.slug][this.configurationBuilderFormData[payload.uniqueSlug+'-'+input.slug]]);
|
||||
} else {
|
||||
formDataForThisPayloadToBuildTheSettingTarget[input.slug] = encodeURIComponent(this.configurationBuilderFormData[payload.uniqueSlug+'-'+input.slug]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
formDataForThisPayloadToBuildTheSettingTarget[payloadToAdd.uniqueSlug] = encodeURIComponent(this.configurationBuilderFormData[payload.uniqueSlug+'-value']);
|
||||
}
|
||||
payloadToAdd.formOutput.settingTarget = _.trim(templateToUseForSettingTarget(formDataForThisPayloadToBuildTheSettingTarget));
|
||||
}
|
||||
if(payload.formInput.type === 'multifield') {
|
||||
// If the payload's formInput type is multifield, we'll need to combine the values for this payload.
|
||||
// build a dictionary of formData where each key is the input's slug.
|
||||
|
|
|
|||
|
|
@ -605,6 +605,11 @@
|
|||
|
||||
[purpose='option-value'] {
|
||||
margin-bottom: 32px;
|
||||
[purpose='nested-label'] {
|
||||
font-size: 14px;
|
||||
margin-bottom: 4px;
|
||||
|
||||
}
|
||||
input {
|
||||
display: flex;
|
||||
width: 260px;
|
||||
|
|
@ -698,6 +703,9 @@
|
|||
|
||||
}
|
||||
}
|
||||
[purpose='select-option'] {
|
||||
max-width: 50%;
|
||||
}
|
||||
}
|
||||
[purpose='name-and-access-type'] {
|
||||
margin-bottom: 32px;
|
||||
|
|
|
|||
17
website/views/pages/configuration-builder.ejs
vendored
17
website/views/pages/configuration-builder.ejs
vendored
|
|
@ -198,6 +198,7 @@
|
|||
{{ configurationBuilderFormData[option.uniqueSlug+'-value'] ? 'Yes' : 'No' }}
|
||||
</label>
|
||||
</div>
|
||||
<%// Select input %>
|
||||
<div purpose="option-value" v-else-if="['select'].includes(option.formInput.type)">
|
||||
<select :class="[formErrors[option.uniqueSlug+'-value'] ? 'is-invalid' : '']" purpose="access-type-select" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-value']" class="form-control" style="width: 300px;" @input="clickAutoSelectWhenSet(formInput)">
|
||||
<option selected value="undefined" >Select an option</option>
|
||||
|
|
@ -205,6 +206,7 @@
|
|||
</select>
|
||||
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-value']">Please select an option</div>
|
||||
</div>
|
||||
<%// Multiple inputs %>
|
||||
<div purpose="option-value" class="w-100" v-else-if="['multifield'].includes(option.formInput.type)">
|
||||
<div purpose="multifield-option" v-for="input in option.formInput.inputs">
|
||||
<% // Number input %>
|
||||
|
|
@ -218,8 +220,11 @@
|
|||
</div>
|
||||
<% // Text input %>
|
||||
<div purpose="option-value" v-if="['text'].includes(input.type)">
|
||||
<input :class="[formErrors[option.uniqueSlug+'-'+input.slug] ? 'is-invalid' : '']" class="form-control" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" :type="input.type" placeholder="Please enter a value" >
|
||||
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-'+input.slug]">Please enter a value</div>
|
||||
<label>
|
||||
<span purpose="nested-label">{{input.name}}</span>
|
||||
<input :class="[formErrors[option.uniqueSlug+'-'+input.slug] ? 'is-invalid' : '']" class="form-control" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" :type="input.type" placeholder="Please enter a value" >
|
||||
<div class="invalid-feedback" v-if="formErrors[option.uniqueSlug+'-'+input.slug]">Please enter a value</div>
|
||||
</label>
|
||||
</div>
|
||||
<% // Radio input %>
|
||||
<div purpose="option-value" v-else-if="['radio'].includes(input.type)" :class="[formErrors[option.uniqueSlug+'-'+input.slug] ? 'is-invalid' : '']">
|
||||
|
|
@ -238,7 +243,7 @@
|
|||
{{ configurationBuilderFormData[option.uniqueSlug+'-'+input.slug] ? 'Yes' : 'No' }}
|
||||
</label>
|
||||
</div>
|
||||
<%// Checkbox input %>
|
||||
<%// Checkbox (with label) input %>
|
||||
<div purpose="option-value" v-else-if="['booleanWithLabel'].includes(input.type)">
|
||||
<div class="d-flex flex-row justify-content-between">
|
||||
<p>{{input.label}}</p>
|
||||
|
|
@ -247,13 +252,13 @@
|
|||
<span purpose="custom-switch" :class="[configurationBuilderFormData[option.uniqueSlug+'-'+input.slug] ? 'checked' : '']"><span purpose="custom-switch-status"></span></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<%// select input %>
|
||||
<div purpose="option-value" v-else-if="['select'].includes(input.type)">
|
||||
<div class="d-flex flex-row justify-content-between">
|
||||
<p>{{input.label}}</p>
|
||||
<div class="d-flex flex-column">
|
||||
<select :class="[formErrors[option.uniqueSlug+'-'+input.slug] ? 'is-invalid' : '']" purpose="access-type-select" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" class="form-control" style="width: 120px;">
|
||||
<div class="d-flex flex-column" purpose="select-option">
|
||||
<select :class="[formErrors[option.uniqueSlug+'-'+input.slug] ? 'is-invalid' : '']" purpose="access-type-select" v-model.trim="configurationBuilderFormData[option.uniqueSlug+'-'+input.slug]" class="form-control">
|
||||
<option :value="undefined">Select an option</option>
|
||||
<option :value="formInput.value" style="text-transform: uppercase;" v-for="formInput in input.options">{{formInput.name}}</option>
|
||||
</select>
|
||||
|
|
|
|||
Loading…
Reference in a new issue