chore(release): SFTP host verification support (known_hosts or hostpub fingerprint)
This commit is contained in:
		
					parent
					
						
							
								4516f9f2a9
							
						
					
				
			
			
				commit
				
					
						a3d0c380ee
					
				
			
		
					 2 changed files with 36 additions and 10 deletions
				
			
		| 
						 | 
					@ -14,3 +14,8 @@ FTP_USER=your-ftp-username
 | 
				
			||||||
FTP_PASS=your-ftp-password
 | 
					FTP_PASS=your-ftp-password
 | 
				
			||||||
# Remote directory to upload signed artifacts (e.g., /addons/archive-org-link-grabber/)
 | 
					# Remote directory to upload signed artifacts (e.g., /addons/archive-org-link-grabber/)
 | 
				
			||||||
FTP_REMOTE_DIR=/path/on/server
 | 
					FTP_REMOTE_DIR=/path/on/server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SFTP host verification (SFTP only; choose one)
 | 
				
			||||||
 | 
					# SFTP_KNOWN_HOSTS=/home/you/.ssh/known_hosts
 | 
				
			||||||
 | 
					# SFTP_HOST_PUBKEY_SHA256=base64sha256fingerprint
 | 
				
			||||||
 | 
					# SFTP_HOST_PUBKEY_MD5=aa:bb:cc:dd:...
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,14 @@
 | 
				
			||||||
 *   FTP_USER=username (required)
 | 
					 *   FTP_USER=username (required)
 | 
				
			||||||
 *   FTP_PASS=password (required)
 | 
					 *   FTP_PASS=password (required)
 | 
				
			||||||
 *   FTP_REMOTE_DIR=/remote/path (required)
 | 
					 *   FTP_REMOTE_DIR=/remote/path (required)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SFTP notes:
 | 
				
			||||||
 | 
					 *   - SFTP requires host verification. Provide one of:
 | 
				
			||||||
 | 
					 *       SFTP_KNOWN_HOSTS=/path/to/known_hosts
 | 
				
			||||||
 | 
					 *       SFTP_HOST_PUBKEY_SHA256=base64_sha256_fingerprint
 | 
				
			||||||
 | 
					 *       SFTP_HOST_PUBKEY_MD5=aa:bb:cc:... (legacy)
 | 
				
			||||||
 | 
					 *     If not provided and no default known_hosts is found, curl will fail with
 | 
				
			||||||
 | 
					 *     "Couldn't find a known_hosts file".
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const fs = require('fs');
 | 
					const fs = require('fs');
 | 
				
			||||||
const path = require('path');
 | 
					const path = require('path');
 | 
				
			||||||
| 
						 | 
					@ -91,6 +99,11 @@ const user = process.env.FTP_USER;
 | 
				
			||||||
const pass = process.env.FTP_PASS;
 | 
					const pass = process.env.FTP_PASS;
 | 
				
			||||||
let remoteDir = process.env.FTP_REMOTE_DIR || '/';
 | 
					let remoteDir = process.env.FTP_REMOTE_DIR || '/';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SFTP host verification options (optional)
 | 
				
			||||||
 | 
					const sftpKnownHosts = process.env.SFTP_KNOWN_HOSTS || process.env.FTP_SSH_KNOWN_HOSTS;
 | 
				
			||||||
 | 
					const sftpHostPubSha256 = process.env.SFTP_HOST_PUBKEY_SHA256 || process.env.FTP_SSH_HOST_PUBKEY_SHA256;
 | 
				
			||||||
 | 
					const sftpHostPubMd5 = process.env.SFTP_HOST_PUBKEY_MD5 || process.env.FTP_SSH_HOST_PUBKEY_MD5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!host || !user || !pass || !remoteDir) {
 | 
					if (!host || !user || !pass || !remoteDir) {
 | 
				
			||||||
  console.error('Missing FTP config. Required: FTP_HOST, FTP_USER, FTP_PASS, FTP_REMOTE_DIR');
 | 
					  console.error('Missing FTP config. Required: FTP_HOST, FTP_USER, FTP_PASS, FTP_REMOTE_DIR');
 | 
				
			||||||
  process.exit(1);
 | 
					  process.exit(1);
 | 
				
			||||||
| 
						 | 
					@ -100,9 +113,23 @@ if (!host || !user || !pass || !remoteDir) {
 | 
				
			||||||
if (!remoteDir.startsWith('/')) remoteDir = '/' + remoteDir;
 | 
					if (!remoteDir.startsWith('/')) remoteDir = '/' + remoteDir;
 | 
				
			||||||
if (remoteDir.endsWith('/')) remoteDir = remoteDir.slice(0, -1);
 | 
					if (remoteDir.endsWith('/')) remoteDir = remoteDir.slice(0, -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Construct base URL for FTP upload target
 | 
					// Construct base URL for FTP/SFTP upload target
 | 
				
			||||||
const baseUrl = `${protocol}://${host}${port ? `:${port}` : ''}${remoteDir}`;
 | 
					const baseUrl = `${protocol}://${host}${port ? `:${port}` : ''}${remoteDir}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Prepare common curl flags
 | 
				
			||||||
 | 
					const curlBase = ['curl', '--fail', '--ftp-create-dirs'];
 | 
				
			||||||
 | 
					if (protocol === 'sftp') {
 | 
				
			||||||
 | 
					  if (sftpKnownHosts) {
 | 
				
			||||||
 | 
					    curlBase.push('--knownhosts', JSON.stringify(sftpKnownHosts));
 | 
				
			||||||
 | 
					  } else if (sftpHostPubSha256) {
 | 
				
			||||||
 | 
					    curlBase.push('--hostpubsha256', JSON.stringify(sftpHostPubSha256));
 | 
				
			||||||
 | 
					  } else if (sftpHostPubMd5) {
 | 
				
			||||||
 | 
					    curlBase.push('--hostpubmd5', JSON.stringify(sftpHostPubMd5));
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    console.warn('SFTP: no known_hosts or host public key provided; relying on default known_hosts.');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Prepare or update self-hosted updates.json before upload
 | 
					// Prepare or update self-hosted updates.json before upload
 | 
				
			||||||
function ensureUpdatesJson() {
 | 
					function ensureUpdatesJson() {
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
| 
						 | 
					@ -164,9 +191,7 @@ for (const file of files) {
 | 
				
			||||||
  const url = `${baseUrl}/${encodeURIComponent(file)}`;
 | 
					  const url = `${baseUrl}/${encodeURIComponent(file)}`;
 | 
				
			||||||
  // --ftp-create-dirs ensures remote dirs are created; --fail fails on server errors.
 | 
					  // --ftp-create-dirs ensures remote dirs are created; --fail fails on server errors.
 | 
				
			||||||
  const cmd = [
 | 
					  const cmd = [
 | 
				
			||||||
    'curl',
 | 
					    ...curlBase,
 | 
				
			||||||
    '--fail',
 | 
					 | 
				
			||||||
    '--ftp-create-dirs',
 | 
					 | 
				
			||||||
    `--user`, `${user}:${pass}`,
 | 
					    `--user`, `${user}:${pass}`,
 | 
				
			||||||
    '--upload-file', JSON.stringify(localPath),
 | 
					    '--upload-file', JSON.stringify(localPath),
 | 
				
			||||||
    JSON.stringify(url),
 | 
					    JSON.stringify(url),
 | 
				
			||||||
| 
						 | 
					@ -181,9 +206,7 @@ try {
 | 
				
			||||||
  const latestUrl = `${baseUrl}/${latestAlias}`;
 | 
					  const latestUrl = `${baseUrl}/${latestAlias}`;
 | 
				
			||||||
  console.log(`Uploading latest alias ${latestAlias} -> ${chosenXpi}`);
 | 
					  console.log(`Uploading latest alias ${latestAlias} -> ${chosenXpi}`);
 | 
				
			||||||
  const latestCmd = [
 | 
					  const latestCmd = [
 | 
				
			||||||
    'curl',
 | 
					    ...curlBase,
 | 
				
			||||||
    '--fail',
 | 
					 | 
				
			||||||
    '--ftp-create-dirs',
 | 
					 | 
				
			||||||
    `--user`, `${user}:${pass}`,
 | 
					    `--user`, `${user}:${pass}`,
 | 
				
			||||||
    '--upload-file', JSON.stringify(localLatestSrc),
 | 
					    '--upload-file', JSON.stringify(localLatestSrc),
 | 
				
			||||||
    JSON.stringify(latestUrl),
 | 
					    JSON.stringify(latestUrl),
 | 
				
			||||||
| 
						 | 
					@ -199,9 +222,7 @@ if (fs.existsSync(updatesPath)) {
 | 
				
			||||||
  const updatesUrl = `${baseUrl}/updates.json`;
 | 
					  const updatesUrl = `${baseUrl}/updates.json`;
 | 
				
			||||||
  console.log(`Uploading updates.json to ${updatesUrl}`);
 | 
					  console.log(`Uploading updates.json to ${updatesUrl}`);
 | 
				
			||||||
  const cmd = [
 | 
					  const cmd = [
 | 
				
			||||||
    'curl',
 | 
					    ...curlBase,
 | 
				
			||||||
    '--fail',
 | 
					 | 
				
			||||||
    '--ftp-create-dirs',
 | 
					 | 
				
			||||||
    `--user`, `${user}:${pass}`,
 | 
					    `--user`, `${user}:${pass}`,
 | 
				
			||||||
    '--upload-file', JSON.stringify(updatesPath),
 | 
					    '--upload-file', JSON.stringify(updatesPath),
 | 
				
			||||||
    JSON.stringify(updatesUrl),
 | 
					    JSON.stringify(updatesUrl),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue