From 8e2a7882e794efd6db2c9b943bf1c1ceae0386b4 Mon Sep 17 00:00:00 2001 From: checktheroads Date: Mon, 10 May 2021 14:12:36 -0700 Subject: [PATCH] #5278: Remove secrets javascript from netbox core --- netbox/project-static/dist/netbox.js | Bin 546729 -> 542285 bytes netbox/project-static/dist/netbox.js.map | Bin 1326964 -> 1315079 bytes netbox/project-static/src/netbox.ts | 2 - netbox/project-static/src/secrets.ts | 208 ----------------------- 4 files changed, 210 deletions(-) delete mode 100644 netbox/project-static/src/secrets.ts diff --git a/netbox/project-static/dist/netbox.js b/netbox/project-static/dist/netbox.js index c7d68128a9c3b529be3d53aed30c3252e0edef5d..6fc632bf274a92aab4b2b7fa30f98bbfa342ab6b 100644 GIT binary patch delta 266 zcmZ3vUh!;?VnYjK3sVbo3rh=Y3)>dCfMH*#^ zMGDEb20A&m(V2Rgd6^|n`S~TqB}It^K;sSvbGSs6f`wfYOHzYVb5fH_@{4rxAu1sj z>lA}|&M-T4Qo#I>#H5^5=ls01%=B36WSbnloYcJZk__u)ZEekJ4WNb5$RTcJ delta 2510 zcma)8OK%)S5Y{H1N2JJk*_Is#JRYOXbUZt|Nr=GS42d5J5|5C?i3Bpnnw{yjhfJn- zdwSM!ti_R72}ME>i$e=IapVwz5R#EVB7cAbKOvkr1i^_Mp?V(cO(KDP@peyFbya=! zebv8wJpT1J<99lR&YsTRPG3jr$lohlQ%Zzgidn=PdzJO#Lb|ZMYRjP-wkdALKE;M! zBZNhaIt?9}jQ?0xE&kht^4>No$X5#mm*0O;9phi_k+1WgAITDIlpj!&0w63+?X0?O}E>F8!0;brl;5!c{^ zj;em$2;(3aw{2W3X1^%f5TOzqTg@2L^#vSYml0~{4Bui7#m+>p57YU-gVb-Ow-qqo zQspBDqE)gMTD8bZ!{dJ)mIqE@yJAv%k(ka>6`!S6fWsBGTE&x-X*{k?7x7Xx3(_qX zUH))hIaX^M6*IJ)hW{#NvrdGOp_gG*&QK_?;1E-X;S!CU62wswh0&44R&i+5J<#X7D9zAKh_c%)lR zr&u(I)pCLu+pg(kzbI$)<^&wmJ@4%g*F{0k}_yyANTpv)tHl%)(l4V>9$ z9!+fdA*6Q=fU&bZaNBO@d1=0ZA%XWF%i8H$%oqu+I1Gq;qm-6sG5uHaJ^Q$Bxg>NQ z1{V79B^`;bX+D-mPG*L?HY17IYnho#8tc2cEl)FqH1#w{-L`E8mE@PtC?orI5kR)Z zAH~wKQDo*V`-}~5PRmF5Ke4p0-|RJ{!q@PzuB9mIleZE6M=Xs#X+;vN0kl)sz{psV z5bKQS2!KE5TMw^Ddd`7H0oG{PdQ(u+Ajk}O`GhjW%N0fGe*zSpJ9njGMi$<#C?ovJ zN#)4?L`eWD;4?|C9Zu0(?jlD4v=;F_UU;AkZt6PlnnHsAO^}=@y8}2xz83jdXO*wS)o~X!^SLO#lF85x4M9sWiIz zG+>}Gd79AZ2J6XAKau?b+=9hv7X!CJ1XeJcVT}4fF_4nx2|{%Rex+Or}9RmY9k z_N>rA$nr>tt9=NP=AYk|#x{F2A`d{#yousA_csAyR?H+p1n8n<_= zs7W>Gc|bbpooaHiAI&uUuIfT1=%lT`8+Ka~4&QQdLr68Wc-}U{n-?8Fz@Em4b`?WC za0_b-S*yJct!7e`wOSho5f(`@3x+d@_ch`~43dmu*98mR)O!rUn~VJx_F(%R5^Fb| zbuA=oT1r#s=48NI`cT(B)IDzyE#`+zMH`$DqaH_WIV+o(4?4g9lJW}wprRb&1E%s^ z{{)O=x}3>J@^ykg|F_gX6y;L`$exM5uDAJ56&U^FEopMtgGLlcr_TyV%wBZOz>Ilm zN}1r_T~O!vz>KPY1P_w!tts_owH)p|KCE)8&XLfP-t8;&yle1uPjxAv(5aO5Qt|2z}s95xH+d5`yj4q{_7=ql&fLi c;X=SWbL#Dbd3w_sY53byN^yI1UOlzvU(I<#g#Z8m diff --git a/netbox/project-static/dist/netbox.js.map b/netbox/project-static/dist/netbox.js.map index 33fdbf58e51c85ab85976339f86047d9ab92a059..d8acd3fc1c3a838c5651a681ecd347e9fd1de2a8 100644 GIT binary patch delta 202 zcmezJFQ9!a_k3LGMya5r+<`V zm*b9d*Ku`pbky;8OrI_#&#upC+U_OK4#XTl%n8I?K+FxqJV49~#C$-^55xl7z2pT? fPio(EQ4olQwr{#9yeDh>3>%RHjN7y9M7S6MD1Acx delta 8637 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'textarea#new_pubkey'); - const privateElem = element.querySelector('textarea#new_privkey'); - - /** - * Handle Generate Private Key Pair Modal opening. - */ - function handleOpen() { - // When the modal opens, set the `readonly` attribute on the textarea elements. - for (const elem of [publicElem, privateElem]) { - if (elem !== null) { - elem.setAttribute('readonly', ''); - } - } - // Fetch the key pair from the API. - apiGetBase('/api/secrets/generate-rsa-key-pair').then(data => { - if (!hasError(data)) { - // If key pair generation was successful, set the textarea elements' value to the generated - // values. - const { private_key: priv, public_key: pub } = data; - if (publicElem !== null && privateElem !== null) { - publicElem.value = pub; - privateElem.value = priv; - } - } else { - // Otherwise, show an error. - const toast = createToast('danger', 'Error', data.error); - toast.show(); - } - }); - } - /** - * Set the public key form field's value to the generated public key. - */ - function handleAccept() { - const publicKeyField = document.getElementById('id_public_key') as HTMLTextAreaElement; - if (publicElem !== null) { - publicKeyField.value = publicElem.value; - publicKeyField.innerText = publicElem.value; - } - } - element.addEventListener('shown.bs.modal', handleOpen); - accept.addEventListener('click', handleAccept); -} - -/** - * Toggle copy/lock/unlock button visibility based on the action occurring. - * @param id Secret ID. - * @param action Lock or Unlock, so we know which buttons to display. - */ -function toggleSecretButtons(id: string, action: 'lock' | 'unlock') { - const unlockButton = document.querySelector(`button.unlock-secret[secret-id='${id}']`); - const lockButton = document.querySelector(`button.lock-secret[secret-id='${id}']`); - const copyButton = document.querySelector(`button.copy-secret[secret-id='${id}']`); - - // If we're unlocking, hide the unlock button. Otherwise, show it. - if (unlockButton !== null) { - if (action === 'unlock') unlockButton.classList.add('d-none'); - if (action === 'lock') unlockButton.classList.remove('d-none'); - } - // If we're unlocking, show the lock button. Otherwise, hide it. - if (lockButton !== null) { - if (action === 'unlock') lockButton.classList.remove('d-none'); - if (action === 'lock') lockButton.classList.add('d-none'); - } - // If we're unlocking, show the copy button. Otherwise, hide it. - if (copyButton !== null) { - if (action === 'unlock') copyButton.classList.remove('d-none'); - if (action === 'lock') copyButton.classList.add('d-none'); - } -} - -/** - * Initialize Lock & Unlock button event listeners & callbacks. - */ -function initLockUnlock() { - const privateKeyModalElem = document.getElementById('privkey_modal'); - if (privateKeyModalElem === null) { - return; - } - const privateKeyModal = new Modal(privateKeyModalElem); - - /** - * Unlock a secret, or prompt the user for their private key, if a session key is not available. - * - * @param id Secret ID - */ - function unlock(id: string | null) { - const target = document.getElementById(`secret_${id}`); - if (typeof id === 'string' && id !== '') { - apiGetBase(`/api/secrets/secrets/${id}`).then(data => { - if (!hasError(data)) { - const { plaintext } = data; - // `plaintext` is the plain text value of the secret. If it is null, it has not been - // decrypted, likely due to a mission session key. - - if (target !== null && plaintext !== null) { - // If `plaintext` is not null, we have the decrypted value. Set the target element's - // inner text to the decrypted value and toggle copy/lock button visibility. - target.innerText = plaintext; - toggleSecretButtons(id, 'unlock'); - } else { - // Otherwise, we do _not_ have the decrypted value and need to prompt the user for - // their private RSA key, in order to get a session key. The session key is then sent - // as a cookie in future requests. - privateKeyModal.show(); - } - } else { - if (data.error.toLowerCase().includes('invalid session key')) { - // If, for some reason, a request was made but resulted in an API error that complains - // of a missing session key, prompt the user for their session key. - privateKeyModal.show(); - } else { - // If we received an API error but it doesn't contain 'invalid session key', show the - // user an error message. - const toast = createToast('danger', 'Error', data.error); - toast.show(); - } - } - }); - } - } - /** - * Lock a secret and toggle visibility of the unlock button. - * @param id Secret ID - */ - function lock(id: string | null) { - if (typeof id === 'string' && id !== '') { - const target = document.getElementById(`secret_${id}`); - if (target !== null) { - // Obscure the inner text of the secret element. - target.innerText = '********'; - } - // Toggle visibility of the copy/lock/unlock buttons. - toggleSecretButtons(id, 'lock'); - } - } - - for (const element of getElements('button.unlock-secret')) { - element.addEventListener('click', () => unlock(element.getAttribute('secret-id'))); - } - for (const element of getElements('button.lock-secret')) { - element.addEventListener('click', () => lock(element.getAttribute('secret-id'))); - } -} - -/** - * Request a session key from the API. - * @param privateKey RSA Private Key (valid JSON string) - */ -function requestSessionKey(privateKey: string) { - apiPostForm('/api/secrets/get-session-key/', { private_key: privateKey }).then(res => { - if (!hasError(res)) { - // If the response received was not an error, show the user a success message. - const toast = createToast('success', 'Session Key Received', 'You may now unlock secrets.'); - toast.show(); - } else { - // Otherwise, show the user an error message. - let message = res.error; - if (isApiError(res)) { - // If the error received was a standard API error containing a Python exception message, - // append it to the error. - message += `\n${res.exception}`; - } - const toast = createToast('danger', 'Failed to Retrieve Session Key', message); - toast.show(); - } - }); -} - -/** - * Initialize Request Session Key Elements. - */ -function initGetSessionKey() { - for (const element of getElements('#request_session_key')) { - /** - * Send the user's input private key to the API to get a session key, which will be stored as - * a cookie for future requests. - */ - function handleClick() { - for (const pk of getElements('#user_privkey')) { - requestSessionKey(pk.value); - // Clear the private key form field value. - pk.value = ''; - } - } - element.addEventListener('click', handleClick); - } -} - -export function initSecrets() { - for (const func of [initGenerateKeyPair, initLockUnlock, initGetSessionKey]) { - func(); - } -}