MT#60641 Adapt random password generator to the new security standards

In the last version mr12.5 we increased the security standards for the subscriber's password.
Now it is mandatory to have:
 * password length min 12 chars
 * must have at least 3 digits
 * must have at least 3 lowercase letters
 * must have at least 3 uppercase letters
 * must have at least 3 special chars

In this review we adapt the random password generator in the CSC.

Change-Id: I8f257e34f7df8c99ef776ea9262fa18c32aef4da
(cherry picked from commit abf1d52fe7)
(cherry picked from commit 186458d581)
mr12.5.1
Nouhaila Idrissi Zouggari 9 months ago committed by Crescenzo Debora
parent 7a4d31fd4e
commit adec1e280f

@ -3,9 +3,6 @@ import _ from 'lodash'
import { import {
getSubscribers getSubscribers
} from './subscriber' } from './subscriber'
import {
v4
} from 'uuid'
import { import {
getList, getList,
get, get,
@ -14,7 +11,6 @@ import {
httpApi httpApi
} from './common' } from './common'
export const createId = v4
export const PBX_CONFIG_ORDER_BY = 'create_timestamp' export const PBX_CONFIG_ORDER_BY = 'create_timestamp'
export const PBX_CONFIG_ORDER_DIRECTION = 'desc' export const PBX_CONFIG_ORDER_DIRECTION = 'desc'

@ -9,13 +9,13 @@ import {
setPbxExtension, setPbxGroupMemberIds, setPbxExtension, setPbxGroupMemberIds,
setPbxHuntPolicy, setPbxHuntPolicy,
setPbxHuntTimeout, setSubscriberNumbers, setPbxHuntTimeout, setSubscriberNumbers,
setPbxHuntCancelMode setPbxHuntCancelMode,
generateGeneralPassword
} from './subscriber' } from './subscriber'
import { import {
getAllSoundSets, getAllSoundSets,
getPilot, getPilot,
getSoundSet, getSoundSet,
createId,
PBX_CONFIG_ORDER_BY, PBX_CONFIG_ORDER_BY,
PBX_CONFIG_ORDER_DIRECTION, PBX_CONFIG_ORDER_DIRECTION,
setSubscriberSoundSet setSubscriberSoundSet
@ -114,13 +114,14 @@ export function getGroupList (options) {
}) })
} }
export function createGroup (group) { export async function createGroup (group) {
const generatePassword = await generateGeneralPassword()
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let subscriberId let subscriberId
Promise.resolve().then(() => { Promise.resolve().then(() => {
return createSubscriber({ return createSubscriber({
username: createUsername(group.name), username: createUsername(group.name),
password: createId(), password: generatePassword,
is_pbx_group: true, is_pbx_group: true,
display_name: group.name, display_name: group.name,
pbx_extension: group.extension, pbx_extension: group.extension,

@ -20,14 +20,14 @@ import {
setPreferenceAnnouncementToCallee, setPreferenceAnnouncementToCallee,
setPreferenceIgnoreCfWhenHunting, setPreferenceIgnoreCfWhenHunting,
setPreferenceCstaClient, setPreferenceCstaClient,
setPreferenceCstaController setPreferenceCstaController,
generateGeneralPassword
} from './subscriber' } from './subscriber'
import _ from 'lodash' import _ from 'lodash'
import { import {
getAllSoundSets, getAllSoundSets,
getPilot, getPilot,
getSoundSet, getSoundSet,
createId,
PBX_CONFIG_ORDER_BY, PBX_CONFIG_ORDER_BY,
PBX_CONFIG_ORDER_DIRECTION, PBX_CONFIG_ORDER_DIRECTION,
setSubscriberSoundSet, setSubscriberSoundSet,
@ -142,7 +142,8 @@ export function getSeatList (options) {
}) })
} }
export function createSeat (seat) { export async function createSeat (seat) {
const generatePassword = await generateGeneralPassword()
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let subscriberId let subscriberId
Promise.resolve().then(() => { Promise.resolve().then(() => {
@ -150,7 +151,7 @@ export function createSeat (seat) {
username: seat.sipUsername.trim(), username: seat.sipUsername.trim(),
display_name: seat.displayName.trim(), display_name: seat.displayName.trim(),
webusername: seat.webUsername.trim(), webusername: seat.webUsername.trim(),
password: seat.sipPassword ? seat.sipPassword : createId(), password: seat.sipPassword ? seat.sipPassword : generatePassword,
webpassword: seat.webPassword.length > 0 ? seat.webPassword : null, webpassword: seat.webPassword.length > 0 ? seat.webPassword : null,
is_pbx_group: false, is_pbx_group: false,
pbx_extension: seat.extension, pbx_extension: seat.extension,

@ -20,6 +20,13 @@ import {
assignNumbers assignNumbers
} from './user' } from './user'
const minValue = 3
const generateSymbols = '!@#$%^&*()_+~`|}{[]:;?><,./-='
const generateNumbers = '0123456789'
const generateLowercase = 'abcdefghijklmnopqrstuvwxyz'
const generateUppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
const generateLength = 12
export function getPreferences (id) { export function getPreferences (id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
httpApi.get('api/subscriberpreferences/' + id).then((result) => { httpApi.get('api/subscriberpreferences/' + id).then((result) => {
@ -901,3 +908,33 @@ export function setCustomerPreference (customerId, customerValue, fieldName) {
}) })
}) })
} }
export async function generateGeneralPassword () {
const getRandomValues = (buf) => crypto.getRandomValues(buf)
const getRandomInt = (max) => {
const randomBuffer = new Uint32Array(1)
getRandomValues(randomBuffer)
return Math.floor(randomBuffer[0] / (0xFFFFFFFF + 1) * max)
}
const getRandomChar = (charset) => charset[getRandomInt(charset.length)]
const charGroups = [
generateNumbers,
generateLowercase,
generateUppercase,
generateSymbols
]
let password = charGroups.flatMap(group =>
Array.from({ length: minValue }, () => getRandomChar(group))
).join('')
while (password.length < generateLength) {
const allChars = charGroups.join('')
password += getRandomChar(allChars)
}
password = password.split('').sort(() => getRandomInt(2) - 0.5).join('')
return password
}

@ -45,9 +45,10 @@
</template> </template>
</csc-input> </csc-input>
</template> </template>
<script> <script>
import CscInput from 'components/form/CscInput' import CscInput from 'components/form/CscInput'
import PasswordGenerator from 'generate-password' import { mapWaitingActions } from 'vue-wait'
export default { export default {
name: 'CscInputPassword', name: 'CscInputPassword',
components: { CscInput }, components: { CscInput },
@ -55,38 +56,6 @@ export default {
generate: { generate: {
type: Boolean, type: Boolean,
default: false default: false
},
generateLength: {
type: Number,
default: 10
},
generateNumbers: {
type: Boolean,
default: true
},
generateLowercase: {
type: Boolean,
default: true
},
generateUppercase: {
type: Boolean,
default: true
},
generateSymbols: {
type: Boolean,
default: false
},
generateExcludeSimilarCharacters: {
type: Boolean,
default: false
},
generateExclude: {
type: String,
default: ''
},
generateStrict: {
type: Boolean,
default: true
} }
}, },
emits: ['generated', 'update:modelValue'], emits: ['generated', 'update:modelValue'],
@ -97,34 +66,20 @@ export default {
}, },
computed: { computed: {
inputType () { inputType () {
if (this.visible) { return this.visible ? 'text' : 'password'
return 'text'
} else {
return 'password'
}
}, },
visibilityIcon () { visibilityIcon () {
if (!this.visible) { return this.visible ? 'visibility' : 'visibility_off'
return 'visibility_off'
} else {
return 'visibility'
}
} }
}, },
methods: { methods: {
generatePassword () { ...mapWaitingActions('user', {
const pass = PasswordGenerator.generate({ generatePasswordUser: 'generatePasswordUser'
length: this.generateLength, }),
numbers: this.generateNumbers, async generatePassword () {
lowercase: this.generateLowercase, const password = await this.generatePasswordUser()
uppercase: this.generateUppercase, this.$emit('update:modelValue', password)
symbols: this.generateSymbols, this.$emit('generated', password)
excludeSimilarCharacters: this.generateExcludeSimilarCharacters,
exclude: this.generateExclude,
strict: this.generateStrict
})
this.$emit('update:modelValue', pass)
this.$emit('generated', pass)
}, },
toggleVisibility () { toggleVisibility () {
this.visible = !this.visible this.visible = !this.visible

@ -29,7 +29,8 @@ import {
getNcosLevels, getNcosLevels,
getNcosSet, getNcosSet,
getPreferences, getPreferences,
setPreference setPreference,
generateGeneralPassword
} from '../api/subscriber' } from '../api/subscriber'
import { deleteJwt, getJwt, getSubscriberId, setJwt, setSubscriberId } from 'src/auth' import { deleteJwt, getJwt, getSubscriberId, setJwt, setSubscriberId } from 'src/auth'
import QRCode from 'qrcode' import QRCode from 'qrcode'
@ -561,6 +562,11 @@ export default {
} catch (err) { } catch (err) {
commit('setQrCode', null) commit('setQrCode', null)
} }
},
async generatePasswordUser () {
const password = await generateGeneralPassword()
return password
} }
} }
} }

Loading…
Cancel
Save