@chaseconey/let-me-in
Version:
A CLI tool to easily SSH into an ECS container using SSM Session Manager.
191 lines (161 loc) • 4.72 kB
JavaScript
import { spawn } from "child_process";
import chalk from "chalk";
import { homedir } from "os";
import { join } from "path";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
/**
* Get the cache directory path
*/
function getCacheDir() {
const cacheDir = join(homedir(), ".cache", "let-me-in");
if (!existsSync(cacheDir)) {
mkdirSync(cacheDir, { recursive: true });
}
return cacheDir;
}
/**
* Get the cache file path
*/
function getCacheFilePath() {
return join(getCacheDir(), "prerequisites-cache.json");
}
/**
* Check if the cache is valid (not older than 1 week)
*/
function isCacheValid(cacheData) {
const oneWeekInMs = 7 * 24 * 60 * 60 * 1000; // 1 week in milliseconds
const now = Date.now();
return now - cacheData.timestamp < oneWeekInMs;
}
/**
* Load cache from file
*/
function loadCache() {
try {
const cacheFilePath = getCacheFilePath();
if (!existsSync(cacheFilePath)) {
return null;
}
const cacheData = JSON.parse(readFileSync(cacheFilePath, "utf8"));
return isCacheValid(cacheData) ? cacheData : null;
} catch (error) {
// If cache is corrupted, ignore it
return null;
}
}
/**
* Save cache to file
*/
function saveCache() {
try {
const cacheData = {
timestamp: Date.now(),
prerequisitesPassed: true,
};
const cacheFilePath = getCacheFilePath();
writeFileSync(cacheFilePath, JSON.stringify(cacheData, null, 2));
} catch (error) {
// Silently ignore cache save errors
}
}
/**
* Check if AWS CLI is installed and accessible
*/
export async function checkAwsCli() {
return checkCommand("aws", ["--version"]);
}
/**
* Check if Session Manager plugin is installed
*/
export async function checkSessionManagerPlugin() {
return checkCommand("aws", ["ssm", "start-session", "help"]);
}
/**
* Check if a task has enable-execute-command flag set
*/
export function hasExecuteCommandEnabled(task) {
return task.enableExecuteCommand === true;
}
/**
* Generic function to check if a command is available
*/
async function checkCommand(command, args) {
return new Promise((resolve) => {
const child = spawn(command, args, { stdio: "pipe" });
child.on("close", (code) => {
resolve(code === 0);
});
child.on("error", () => {
resolve(false);
});
});
}
/**
* Display error message for missing AWS CLI
*/
export function displayAwsCliError() {
console.error(`${chalk.red("✗ AWS CLI is not installed or not accessible")}
To use this tool, you need to install the AWS CLI:
${chalk.blue("https://aws.amazon.com/cli/")}
Installation options:
• macOS: brew install awscli
• Windows: Download installer from AWS
• Linux: pip install awscli`);
}
/**
* Display error message for missing Session Manager plugin
*/
export function displaySessionManagerPluginError() {
console.error(`${chalk.red("✗ Session Manager plugin is not installed")}
To use this tool, you need to install the Session Manager plugin:
${chalk.blue(
"https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html"
)}
Installation options:
• macOS: Download and install the .pkg file
• Windows: Download and run the .msi installer
• Linux: Download and install the .deb or .rpm package`);
}
/**
* Display error message for task without execute command enabled
*/
export function displayExecuteCommandError(taskName) {
console.error(`${chalk.red(
`✗ Task ${taskName} does not have execute command enabled`
)}
To connect to this task, the ECS service or task definition needs to have
the 'enable-execute-command' flag set to true.
You can enable this by:
• Updating your ECS service with --enable-execute-command flag
• Or updating your task definition and redeploying
AWS CLI example:
${chalk.dim(
"aws ecs update-service --cluster CLUSTER --service SERVICE --enable-execute-command"
)}`);
}
/**
* Run all prerequisite checks
*/
export async function checkPrerequisites() {
// Check if we have a valid cache
const cachedResult = loadCache();
if (cachedResult && cachedResult.prerequisitesPassed) {
return true;
}
console.log(chalk.dim("Checking prerequisites..."));
const awsCliInstalled = await checkAwsCli();
if (!awsCliInstalled) {
displayAwsCliError();
return false;
}
console.log(chalk.green("✓ AWS CLI is installed"));
const sessionManagerInstalled = await checkSessionManagerPlugin();
if (!sessionManagerInstalled) {
displaySessionManagerPluginError();
return false;
}
console.log(chalk.green("✓ Session Manager plugin is installed"));
// Save successful check to cache
saveCache();
return true;
}