@@ -1819,13 +1819,14 @@ module.exports = options
18191819const fs = __nccwpck_require__ ( 7147 )
18201820const path = __nccwpck_require__ ( 1017 )
18211821const os = __nccwpck_require__ ( 2037 )
1822+ const crypto = __nccwpck_require__ ( 6113 )
18221823const packageJson = __nccwpck_require__ ( 9968 )
18231824
18241825const version = packageJson . version
18251826
18261827const LINE = / (?: ^ | ^ ) \s * (?: e x p o r t \s + ) ? ( [ \w . - ] + ) (?: \s * = \s * ?| : \s + ?) ( \s * ' (?: \\ ' | [ ^ ' ] ) * ' | \s * " (?: \\ " | [ ^ " ] ) * " | \s * ` (?: \\ ` | [ ^ ` ] ) * ` | [ ^ # \r \n ] + ) ? \s * (?: # .* ) ? (?: $ | $ ) / mg
18271828
1828- // Parser src into an Object
1829+ // Parse src into an Object
18291830function parse ( src ) {
18301831 const obj = { }
18311832
@@ -1864,20 +1865,130 @@ function parse (src) {
18641865 return obj
18651866}
18661867
1868+ function _parseVault ( options ) {
1869+ const vaultPath = _vaultPath ( options )
1870+
1871+ // Parse .env.vault
1872+ const result = DotenvModule . configDotenv ( { path : vaultPath } )
1873+ if ( ! result . parsed ) {
1874+ throw new Error ( `MISSING_DATA: Cannot parse ${ vaultPath } for an unknown reason` )
1875+ }
1876+
1877+ // handle scenario for comma separated keys - for use with key rotation
1878+ // example: DOTENV_KEY="dotenv://:[email protected] /vault/.env.vault?environment=prod,dotenv://:[email protected] /vault/.env.vault?environment=prod" 1879+ const keys = _dotenvKey ( ) . split ( ',' )
1880+ const length = keys . length
1881+
1882+ let decrypted
1883+ for ( let i = 0 ; i < length ; i ++ ) {
1884+ try {
1885+ // Get full key
1886+ const key = keys [ i ] . trim ( )
1887+
1888+ // Get instructions for decrypt
1889+ const attrs = _instructions ( result , key )
1890+
1891+ // Decrypt
1892+ decrypted = DotenvModule . decrypt ( attrs . ciphertext , attrs . key )
1893+
1894+ break
1895+ } catch ( error ) {
1896+ // last key
1897+ if ( i + 1 >= length ) {
1898+ throw error
1899+ }
1900+ // try next key
1901+ }
1902+ }
1903+
1904+ // Parse decrypted .env string
1905+ return DotenvModule . parse ( decrypted )
1906+ }
1907+
18671908function _log ( message ) {
1909+ console . log ( `[dotenv@${ version } ][INFO] ${ message } ` )
1910+ }
1911+
1912+ function _warn ( message ) {
1913+ console . log ( `[dotenv@${ version } ][WARN] ${ message } ` )
1914+ }
1915+
1916+ function _debug ( message ) {
18681917 console . log ( `[dotenv@${ version } ][DEBUG] ${ message } ` )
18691918}
18701919
1920+ function _dotenvKey ( ) {
1921+ if ( process . env . DOTENV_KEY && process . env . DOTENV_KEY . length > 0 ) {
1922+ return process . env . DOTENV_KEY
1923+ }
1924+
1925+ return ''
1926+ }
1927+
1928+ function _instructions ( result , dotenvKey ) {
1929+ // Parse DOTENV_KEY. Format is a URI
1930+ let uri
1931+ try {
1932+ uri = new URL ( dotenvKey )
1933+ } catch ( error ) {
1934+ if ( error . code === 'ERR_INVALID_URL' ) {
1935+ throw new Error ( 'INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:[email protected] /vault/.env.vault?environment=development' ) 1936+ }
1937+
1938+ throw error
1939+ }
1940+
1941+ // Get decrypt key
1942+ const key = uri . password
1943+ if ( ! key ) {
1944+ throw new Error ( 'INVALID_DOTENV_KEY: Missing key part' )
1945+ }
1946+
1947+ // Get environment
1948+ const environment = uri . searchParams . get ( 'environment' )
1949+ if ( ! environment ) {
1950+ throw new Error ( 'INVALID_DOTENV_KEY: Missing environment part' )
1951+ }
1952+
1953+ // Get ciphertext payload
1954+ const environmentKey = `DOTENV_VAULT_${ environment . toUpperCase ( ) } `
1955+ const ciphertext = result . parsed [ environmentKey ] // DOTENV_VAULT_PRODUCTION
1956+ if ( ! ciphertext ) {
1957+ throw new Error ( `NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${ environmentKey } in your .env.vault file.` )
1958+ }
1959+
1960+ return { ciphertext, key }
1961+ }
1962+
1963+ function _vaultPath ( options ) {
1964+ let dotenvPath = path . resolve ( process . cwd ( ) , '.env' )
1965+
1966+ if ( options && options . path && options . path . length > 0 ) {
1967+ dotenvPath = options . path
1968+ }
1969+
1970+ // Locate .env.vault
1971+ return dotenvPath . endsWith ( '.vault' ) ? dotenvPath : `${ dotenvPath } .vault`
1972+ }
1973+
18711974function _resolveHome ( envPath ) {
18721975 return envPath [ 0 ] === '~' ? path . join ( os . homedir ( ) , envPath . slice ( 1 ) ) : envPath
18731976}
18741977
1875- // Populates process.env from .env file
1876- function config ( options ) {
1978+ function _configVault ( options ) {
1979+ _log ( 'Loading env from encrypted .env.vault' )
1980+
1981+ const parsed = DotenvModule . _parseVault ( options )
1982+
1983+ DotenvModule . populate ( process . env , parsed , options )
1984+
1985+ return { parsed }
1986+ }
1987+
1988+ function configDotenv ( options ) {
18771989 let dotenvPath = path . resolve ( process . cwd ( ) , '.env' )
18781990 let encoding = 'utf8'
18791991 const debug = Boolean ( options && options . debug )
1880- const override = Boolean ( options && options . override )
18811992
18821993 if ( options ) {
18831994 if ( options . path != null ) {
@@ -1892,41 +2003,115 @@ function config (options) {
18922003 // Specifying an encoding returns a string instead of a buffer
18932004 const parsed = DotenvModule . parse ( fs . readFileSync ( dotenvPath , { encoding } ) )
18942005
1895- Object . keys ( parsed ) . forEach ( function ( key ) {
1896- if ( ! Object . prototype . hasOwnProperty . call ( process . env , key ) ) {
1897- process . env [ key ] = parsed [ key ]
1898- } else {
1899- if ( override === true ) {
1900- process . env [ key ] = parsed [ key ]
1901- }
1902-
1903- if ( debug ) {
1904- if ( override === true ) {
1905- _log ( `"${ key } " is already defined in \`process.env\` and WAS overwritten` )
1906- } else {
1907- _log ( `"${ key } " is already defined in \`process.env\` and was NOT overwritten` )
1908- }
1909- }
1910- }
1911- } )
2006+ DotenvModule . populate ( process . env , parsed , options )
19122007
19132008 return { parsed }
19142009 } catch ( e ) {
19152010 if ( debug ) {
1916- _log ( `Failed to load ${ dotenvPath } ${ e . message } ` )
2011+ _debug ( `Failed to load ${ dotenvPath } ${ e . message } ` )
19172012 }
19182013
19192014 return { error : e }
19202015 }
19212016}
19222017
2018+ // Populates process.env from .env file
2019+ function config ( options ) {
2020+ const vaultPath = _vaultPath ( options )
2021+
2022+ // fallback to original dotenv if DOTENV_KEY is not set
2023+ if ( _dotenvKey ( ) . length === 0 ) {
2024+ return DotenvModule . configDotenv ( options )
2025+ }
2026+
2027+ // dotenvKey exists but .env.vault file does not exist
2028+ if ( ! fs . existsSync ( vaultPath ) ) {
2029+ _warn ( `You set DOTENV_KEY but you are missing a .env.vault file at ${ vaultPath } . Did you forget to build it?` )
2030+
2031+ return DotenvModule . configDotenv ( options )
2032+ }
2033+
2034+ return DotenvModule . _configVault ( options )
2035+ }
2036+
2037+ function decrypt ( encrypted , keyStr ) {
2038+ const key = Buffer . from ( keyStr . slice ( - 64 ) , 'hex' )
2039+ let ciphertext = Buffer . from ( encrypted , 'base64' )
2040+
2041+ const nonce = ciphertext . slice ( 0 , 12 )
2042+ const authTag = ciphertext . slice ( - 16 )
2043+ ciphertext = ciphertext . slice ( 12 , - 16 )
2044+
2045+ try {
2046+ const aesgcm = crypto . createDecipheriv ( 'aes-256-gcm' , key , nonce )
2047+ aesgcm . setAuthTag ( authTag )
2048+ return `${ aesgcm . update ( ciphertext ) } ${ aesgcm . final ( ) } `
2049+ } catch ( error ) {
2050+ const isRange = error instanceof RangeError
2051+ const invalidKeyLength = error . message === 'Invalid key length'
2052+ const decryptionFailed = error . message === 'Unsupported state or unable to authenticate data'
2053+
2054+ if ( isRange || invalidKeyLength ) {
2055+ const msg = 'INVALID_DOTENV_KEY: It must be 64 characters long (or more)'
2056+ throw new Error ( msg )
2057+ } else if ( decryptionFailed ) {
2058+ const msg = 'DECRYPTION_FAILED: Please check your DOTENV_KEY'
2059+ throw new Error ( msg )
2060+ } else {
2061+ console . error ( 'Error: ' , error . code )
2062+ console . error ( 'Error: ' , error . message )
2063+ throw error
2064+ }
2065+ }
2066+ }
2067+
2068+ // Populate process.env with parsed values
2069+ function populate ( processEnv , parsed , options = { } ) {
2070+ const debug = Boolean ( options && options . debug )
2071+ const override = Boolean ( options && options . override )
2072+
2073+ if ( typeof parsed !== 'object' ) {
2074+ throw new Error ( 'OBJECT_REQUIRED: Please check the processEnv argument being passed to populate' )
2075+ }
2076+
2077+ // Set process.env
2078+ for ( const key of Object . keys ( parsed ) ) {
2079+ if ( Object . prototype . hasOwnProperty . call ( processEnv , key ) ) {
2080+ if ( override === true ) {
2081+ processEnv [ key ] = parsed [ key ]
2082+ }
2083+
2084+ if ( debug ) {
2085+ if ( override === true ) {
2086+ _debug ( `"${ key } " is already defined and WAS overwritten` )
2087+ } else {
2088+ _debug ( `"${ key } " is already defined and was NOT overwritten` )
2089+ }
2090+ }
2091+ } else {
2092+ processEnv [ key ] = parsed [ key ]
2093+ }
2094+ }
2095+ }
2096+
19232097const DotenvModule = {
2098+ configDotenv,
2099+ _configVault,
2100+ _parseVault,
19242101 config,
1925- parse
2102+ decrypt,
2103+ parse,
2104+ populate
19262105}
19272106
2107+ module . exports . configDotenv = DotenvModule . configDotenv
2108+ module . exports . _configVault = DotenvModule . _configVault
2109+ module . exports . _parseVault = DotenvModule . _parseVault
19282110module . exports . config = DotenvModule . config
2111+ module . exports . decrypt = DotenvModule . decrypt
19292112module . exports . parse = DotenvModule . parse
2113+ module . exports . populate = DotenvModule . populate
2114+
19302115module . exports = DotenvModule
19312116
19322117
@@ -7753,7 +7938,7 @@ return new B(c,{type:"multipart/form-data; boundary="+b})}
77537938/***/ 9968 :
77547939/***/ ( ( module ) => {
77557940
7756- module . exports = JSON . parse ( '{"name":"dotenv","version":"16.0.3","description":"Loads environment variables from .env file","main":"lib/main.js","types":"lib/main.d.ts","exports":{".":{"require":"./lib/main.js","types":"./lib/main.d.ts","default":"./lib/main.js"},"./config":"./config.js","./config.js":"./config.js","./lib/env-options":"./lib/env-options.js","./lib/env-options.js":"./lib/env-options.js","./lib/cli-options":"./lib/cli-options.js","./lib/cli-options.js":"./lib/cli-options.js","./package.json":"./package.json"},"scripts":{"dts-check":"tsc --project tests/types/tsconfig.json","lint":"standard","lint-readme":"standard-markdown","pretest":"npm run lint && npm run dts-check","test":"tap tests/*.js --100 -Rspec","prerelease":"npm test","release":"standard-version"},"repository":{"type":"git","url":"git://github.com/motdotla/dotenv.git"},"keywords":["dotenv","env",".env","environment","variables","config","settings"],"readmeFilename":"README.md","license":"BSD-2-Clause","devDependencies":{"@types/node":"^17.0.9","decache":"^4.6.1","dtslint":"^3.7.0","sinon":"^12.0.1","standard":"^16.0.4","standard-markdown":"^7.1.0","standard-version":"^9.3.2","tap":"^15.1.6","tar":"^6.1.11","typescript":"^4.5.4"},"engines":{"node":">=12"}}' ) ;
7941+ module . exports = JSON . parse ( '{"name":"dotenv","version":"16.1.4","description":"Loads environment variables from .env file","main":"lib/main.js","types":"lib/main.d.ts","exports":{".":{"types":"./lib/main.d.ts","require":"./lib/main.js","default":"./lib/main.js"},"./config":"./config.js","./config.js":"./config.js","./lib/env-options":"./lib/env-options.js","./lib/env-options.js":"./lib/env-options.js","./lib/cli-options":"./lib/cli-options.js","./lib/cli-options.js":"./lib/cli-options.js","./package.json":"./package.json"},"scripts":{"dts-check":"tsc --project tests/types/tsconfig.json","lint":"standard","lint-readme":"standard-markdown","pretest":"npm run lint && npm run dts-check","test":"tap tests/*.js --100 -Rspec","prerelease":"npm test","release":"standard-version"},"repository":{"type":"git","url":"git://github.com/motdotla/dotenv.git"},"funding":"https://github.com/motdotla/dotenv?sponsor=1","keywords":["dotenv","env",".env","environment","variables","config","settings"],"readmeFilename":"README.md","license":"BSD-2-Clause","devDependencies":{"@definitelytyped/dtslint":"^0.0.133","@types/node":"^18.11.3","decache":"^4.6.1","sinon":"^14.0.1","standard":"^17.0.0","standard-markdown":"^7.1.0","standard-version":"^9.5.0","tap":"^16.3.0","tar":"^6.1.11","typescript":"^4.8.4"},"engines":{"node":">=12"},"browser":{"fs":false}}' ) ;
77577942
77587943/***/ } )
77597944
@@ -10104,6 +10289,11 @@ const run = async () => {
1010410289 res = await fetch ( `https://api.render.com/v1/services/${ serviceId } /deploys?limit=20` , { method : 'GET' , ...options } ) ;
1010510290 data = await res . json ( ) ;
1010610291
10292+ if ( ! data ) {
10293+ core . setFailed ( `This operation did not succeed. Please check if the serviceId and apiKey inputs were correclty set` ) ;
10294+ return ;
10295+ }
10296+
1010710297 if ( res . status !== 200 ) {
1010810298 core . setFailed ( `This operation did not succeed. Reason: ${ data . message } ` ) ;
1010910299 return ;
0 commit comments