1+ import * as fs from 'fs'
12import * as path from 'path'
23import type { Auth , DRecord } from '@keeper-security/keeperapi'
3- import { generateUid } from '@keeper-security/keeperapi'
4+ import {
5+ fileAddMessage ,
6+ generateEncryptionKey ,
7+ generateUid ,
8+ normal64Bytes ,
9+ platform ,
10+ Records ,
11+ } from '@keeper-security/keeperapi'
412import type { InMemoryStorage } from '../../storage/InMemoryStorage'
513import { VaultObjectKind } from '../../folders/folderHelpers'
614import { getRecordType } from '../../records/RecordUtils'
@@ -36,7 +44,57 @@ export async function addRotationScript(
3644 const dataFields = recordData . fields
3745 const fileName = path . basename ( expandedPath )
3846
47+ const recordKey = await storage . getKeyBytes ( record . uid )
48+ if ( ! recordKey ) {
49+ throw new KeeperSdkError (
50+ `Unable to retrieve encryption key for record "${ record . uid } "` ,
51+ ResultCodes . PAM_CONFIG_CREATE_FAILED
52+ )
53+ }
54+
3955 const fileUid = generateUid ( )
56+ const fileKey = generateEncryptionKey ( )
57+ const scriptData = new Uint8Array ( fs . readFileSync ( expandedPath ) )
58+ const encryptedScript = await platform . aesGcmEncrypt ( scriptData , fileKey )
59+ const fileMetadata = platform . stringToBytes (
60+ JSON . stringify ( {
61+ title : fileName ,
62+ name : fileName ,
63+ type : 'application/octet-stream' ,
64+ size : scriptData . length ,
65+ } )
66+ )
67+
68+ const filesAddResponse = await auth . executeRest (
69+ fileAddMessage ( {
70+ clientTime : Date . now ( ) ,
71+ files : [
72+ {
73+ recordUid : normal64Bytes ( fileUid ) ,
74+ recordKey : await platform . aesGcmEncrypt ( fileKey , auth . dataKey ! ) ,
75+ data : await platform . aesGcmEncrypt ( fileMetadata , fileKey ) ,
76+ fileSize : encryptedScript . length ,
77+ isScript : true ,
78+ } ,
79+ ] ,
80+ } )
81+ )
82+ const fileStatus = filesAddResponse . files ?. [ 0 ]
83+ if ( ! fileStatus || fileStatus . status !== Records . FileAddResult . FA_SUCCESS || ! fileStatus . url ) {
84+ throw new KeeperSdkError ( 'Failed to obtain script file upload URL' , ResultCodes . PAM_CONFIG_CREATE_FAILED )
85+ }
86+
87+ let uploadParameters : { [ key : string ] : string }
88+ try {
89+ uploadParameters = JSON . parse ( fileStatus . parameters || '{}' )
90+ } catch {
91+ throw new KeeperSdkError ( 'Invalid script file upload parameters' , ResultCodes . PAM_CONFIG_CREATE_FAILED )
92+ }
93+ const uploadResponse = await platform . fileUpload ( fileStatus . url , uploadParameters , encryptedScript )
94+ if ( fileStatus . successStatusCode && uploadResponse ?. statusCode !== fileStatus . successStatusCode ) {
95+ throw new KeeperSdkError ( 'Failed to upload script file' , ResultCodes . PAM_CONFIG_CREATE_FAILED )
96+ }
97+
4098 const scriptValue : RotationScriptValue = {
4199 fileRef : fileUid ,
42100 recordRef : [ ] ,
@@ -54,17 +112,30 @@ export async function addRotationScript(
54112 }
55113 }
56114
57- const newScriptField = {
58- type : SCRIPT_FIELD_TYPE ,
59- label : SCRIPT_FIELD_LABEL ,
60- value : [ scriptValue ] ,
115+ const scriptField = dataFields . find (
116+ ( field ) => field . type === SCRIPT_FIELD_TYPE && Array . isArray ( field . value )
117+ )
118+ if ( scriptField ) {
119+ scriptField . label = SCRIPT_FIELD_LABEL
120+ scriptField . required = false
121+ scriptField . value . push ( scriptValue )
122+ } else {
123+ dataFields . push ( {
124+ type : SCRIPT_FIELD_TYPE ,
125+ label : SCRIPT_FIELD_LABEL ,
126+ value : [ scriptValue ] ,
127+ required : false ,
128+ } )
61129 }
62-
63- dataFields . push ( newScriptField )
64130 recordData . fields = dataFields
65131 record . data = recordData
66132
67- await updatePamRecordFields ( auth , record , recordType , dataFields , currentRevision , storage )
133+ await updatePamRecordFields ( auth , record , recordType , dataFields , currentRevision , storage , [
134+ {
135+ recordUid : normal64Bytes ( fileUid ) ,
136+ recordKey : await platform . aesGcmEncrypt ( fileKey , recordKey ) ,
137+ } ,
138+ ] )
68139
69140 return {
70141 success : true ,
0 commit comments