rds_ssm_connect 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +198 -39
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,16 +1,16 @@
1
- # AWS Environment Selector and Command Executor
1
+ # AWS RDS SSM Connector
2
2
 
3
- This Node.js application allows you to select an AWS environment and execute various AWS commands within that environment. The environments are read from your AWS configuration file, and the application uses the `aws-vault` tool to manage your AWS credentials securely.
3
+ This Node.js application allows you to select an AWS environment and execute various AWS commands within that environment to connect to an RDS database securely. The environments are read from your AWS configuration file, and the application retrieves credentials and other necessary information using AWS Secrets Manager and other AWS services.
4
4
 
5
5
  ## Prerequisites
6
6
 
7
7
  Before running this application, make sure you have the following installed:
8
8
 
9
- - Node.js: You can download it from the [official website](https://nodejs.org/).
10
- - `aws-vault` tool: You can install it following the instructions on the [official GitHub page](https://github.com/99designs/aws-vault).
11
- - AWS CLI: You can install it following the instructions on the [official AWS page](https://aws.amazon.com/cli/).
9
+ - **Node.js**: You can download it from the [official website](https://nodejs.org/).
10
+ - **`aws-vault` tool**: You can install it following the instructions on the [official GitHub page](https://github.com/99designs/aws-vault).
11
+ - **AWS CLI**: You can install it following the instructions on the [official AWS page](https://aws.amazon.com/cli/).
12
12
 
13
- Also, ensure that your AWS configuration file (`~/.aws/config`) is appropriately set up with the environments you want to use.
13
+ Additionally, ensure that your AWS configuration file (`~/.aws/config`) is appropriately set up with the environments you want to use.
14
14
 
15
15
  ## Installation
16
16
 
@@ -20,13 +20,11 @@ You can install this application globally using npm:
20
20
  npm install -g rds_ssm_connect
21
21
  ```
22
22
 
23
- 2. Select the environment you want to use. The application will then execute a series of AWS commands within that environment.
24
-
25
- Given your provided code, here's how to connect to the database:
26
-
27
23
  ## Connecting to the Database
28
24
 
29
- 1. Invoke `rds_ssm_connect` in your terminal:
25
+ 1. **Invoke the Application**:
26
+
27
+ Run the following command in your terminal:
30
28
 
31
29
  ```bash
32
30
  rds_ssm_connect
@@ -34,49 +32,210 @@ Given your provided code, here's how to connect to the database:
34
32
 
35
33
  The application will read your AWS configuration file and prompt you to select an environment.
36
34
 
37
- 2. Select the environment you want to connect to. The application will then execute a series of AWS commands within that environment. It will do the following:
35
+ 2. **Select an Environment**:
36
+
37
+ The application will list the environments found in your AWS configuration file. Select the desired environment for which you want to connect to the RDS instance.
38
+
39
+ 3. **Execution of AWS Commands**:
38
40
 
39
- - Extract the environments from the AWS configuration file
40
- - Get the name of the parameter containing the RDS password
41
- - Get the RDS credentials
42
- - Display the connection credentials and the connection string
43
- - Get the ID of the bastion instance
44
- - Get the endpoint of the RDS cluster
45
- - Start a port forwarding session to the RDS cluster
41
+ After selecting the environment, the application will:
42
+
43
+ - Extract environments from the AWS configuration file.
44
+ - Use AWS Secrets Manager to list and retrieve the secret containing the RDS credentials.
45
+ - Display the connection credentials and connection string.
46
+ - Get the ID of the bastion instance.
47
+ - Get the endpoint of the RDS cluster.
48
+ - Provide a command to start a port forwarding session to the RDS cluster.
46
49
 
47
- 3. After you've selected an environment and the AWS commands have been executed, you will receive the connection information. Here is an example of the output:
50
+ 4. **Receive Connection Information**:
51
+
52
+ After executing the necessary AWS commands, the application will provide the connection information, as shown below:
48
53
 
49
54
  ```
50
- Your connection string is: psql -h localhost -p <port> -U <username> -d oit
55
+ Your connection string is: psql -h localhost -p <port> -U <username> -d <database>
51
56
  Use the password: <password>
52
57
  ```
53
58
 
54
- 4. Use the provided connection string and password to connect to your database via a database administration tool of your choice, such as pgAdmin, DBeaver, or the `psql` command-line interface.
59
+ 5. **Port Forwarding**:
60
+
61
+ Use the provided command to start port forwarding. This step is crucial as it sets up the local port to tunnel to the RDS cluster through the bastion host.
55
62
 
56
- Please note: Make sure the chosen database administration tool is installed and configured on your local machine. The specific instructions for connecting to a database would vary based on the tool used.
63
+ For example:
64
+
65
+ ```
66
+ aws ssm start-session --target <instance-id> --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters "host=<rds-endpoint>,portNumber='5432',localPortNumber='<port>'" --cli-connect-timeout 0
67
+ ```
68
+
69
+ 6. **Connect to Your Database**:
70
+
71
+ Use the provided connection string and password to connect to your database via a database administration tool of your choice, such as pgAdmin, DBeaver, or the `psql` command-line interface.
72
+
73
+ Ensure that the database administration tool is installed and configured on your local machine.
57
74
 
58
75
  ## Requirements
59
76
 
60
77
  This application requires the following Node.js modules:
61
78
 
62
- - `child_process`: For spawning child processes to execute AWS commands.
63
- - `inquirer`: For prompting the user to select an environment.
64
- - `fs`: For reading the AWS configuration file.
65
- - `os`: For getting the user's home directory.
66
- - `path`: For working with file paths.
79
+ - `@aws-sdk/client-ec2`
80
+ - `@aws-sdk/client-rds`
81
+ - `@aws-sdk/client-secrets-manager`
82
+ - `inquirer`
67
83
 
68
- These modules will be installed automatically when you install the application with npm.
84
+ These modules will be automatically installed when you install the application with npm.
69
85
 
70
86
  ## How It Works
71
87
 
72
- The application first reads the AWS configuration file and extracts the environments from it. It then prompts the user to select an environment.
73
-
74
- After the user selects an environment, the application executes a series of AWS commands within that environment using `aws-vault`. These commands include:
75
-
76
- - Describing SSM parameters to get the parameter's name containing the RDS password.
77
- - Getting the value of the RDS password parameter.
78
- - Describing EC2 instances to get the ID of the bastion instance.
79
- - Describing RDS DB clusters to get the endpoint of the RDS cluster.
80
- - Starting an AWS SSM session to forward a local port to the RDS cluster.
88
+ 1. **Reading AWS Configuration**:
89
+
90
+ The application first reads the AWS configuration file (`~/.aws/config`) and extracts the environments configured.
91
+
92
+ 2. **User Prompt**:
93
+
94
+ The user is prompted to select one of the configured environments using `inquirer`.
95
+
96
+ 3. **AWS Commands Execution**:
97
+
98
+ Upon selecting an environment, the application performs the following operations using the AWS SDK and `aws-vault`:
99
+
100
+ - **Listing Secrets**: Uses AWS Secrets Manager to list secrets and identify the one containing the RDS credentials.
101
+ - **Retrieving Secret Value**: Fetches the secret value containing the RDS username and password.
102
+ - **Describing Instances**: Gets the ID of a bastion instance tagged with `Name=*bastion*`.
103
+ - **Describing RDS Clusters**: Retrieves the endpoint of the RDS cluster identified with `-rds-aurora`.
104
+ - **Port Forwarding Command**: Outputs a command to start an AWS SSM session for port forwarding.
105
+
106
+ 4. **Output**:
107
+
108
+ The application displays the connection string and password for the RDS database along with a command to start a port forwarding session to the RDS cluster, allowing secure access from the local machine.
109
+
110
+ ### Code File
111
+
112
+ Here is the `connect.js` file used in the application:
113
+
114
+ ```javascript
115
+ #!/usr/bin/env node
116
+
117
+ import { EC2Client, DescribeInstancesCommand } from "@aws-sdk/client-ec2";
118
+ import { RDSClient, DescribeDBClustersCommand } from "@aws-sdk/client-rds";
119
+ import { SecretsManagerClient, GetSecretValueCommand, ListSecretsCommand } from "@aws-sdk/client-secrets-manager";
120
+ import inquirer from 'inquirer';
121
+ import fs from 'fs';
122
+ import os from 'os';
123
+ import path from 'path';
124
+ import { envPortMapping, REGION, TABLE_NAME } from './envPortMapping.js';
125
+
126
+ // Load AWS config
127
+ const awsConfigPath = path.join(os.homedir(), '.aws', 'config');
128
+ const awsConfig = fs.readFileSync(awsConfigPath, 'utf-8');
129
+ const ENVS = awsConfig
130
+ .split('\n')
131
+ .filter(line => line.startsWith('[') && line.endsWith(']'))
132
+ .map(line => line.slice(1, -1))
133
+ .map(line => line.replace('profile ', ''));
134
+
135
+ // Initialize AWS SDK clients
136
+ const ec2Client = new EC2Client({ region: REGION });
137
+ const rdsClient = new RDSClient({ region: REGION });
138
+ const secretsManagerClient = new SecretsManagerClient({ region: REGION });
139
+
140
+ // Function to list secrets
141
+ async function listSecrets() {
142
+ const command = new ListSecretsCommand({
143
+ Filters: [{ Key: 'name', Values: ['rds!cluster'] }]
144
+ });
145
+ const response = await secretsManagerClient.send(command);
146
+ return response.SecretList.map(secret => secret.Name);
147
+ }
148
+
149
+ // Function to get secret value
150
+ async function getSecretValue(secretName) {
151
+ const command = new GetSecretValueCommand({ SecretId: secretName });
152
+ const response = await secretsManagerClient.send(command);
153
+ return JSON.parse(response.SecretString);
154
+ }
155
+
156
+ // Function to get instance ID
157
+ async function getInstanceId() {
158
+ const command = new DescribeInstancesCommand({
159
+ Filters: [
160
+ { Name: 'tag:Name', Values: ['*bastion*'] },
161
+ { Name: 'instance-state-name', Values: ['running'] }
162
+ ]
163
+ });
164
+ const response = await ec2Client.send(command);
165
+ const instances = response.Reservations.flatMap(reservation => reservation.Instances.map(instance => instance.InstanceId));
166
+ return instances[0];
167
+ }
168
+
169
+ // Function to get RDS endpoint
170
+ async function getRdsEndpoint() {
171
+ const command = new DescribeDBClustersCommand({
172
+ Filters: [{ Name: 'Status', Values: ['available'] }]
173
+ });
174
+ const response = await rdsClient.send(command);
175
+ const clusters = response.DBClusters.filter(cluster => cluster.DBClusterIdentifier.endsWith('-rds-aurora'));
176
+ return clusters[0].Endpoint;
177
+ }
178
+
179
+ async function main() {
180
+ const answers = await inquirer.prompt([
181
+ {
182
+ type: 'list',
183
+ name: 'ENV',
184
+ message: 'Please select the environment:',
185
+ choices: ENVS
186
+ }
187
+ ]);
188
+
189
+ const ENV = answers.ENV;
190
+ console.log(`You selected: ${ENV}`);
191
+
192
+ // Sort all environment suffixes by length, longest first
193
+ const allEnvSuffixes = Object.keys(envPortMapping).sort((a, b) => b.length - a.length);
194
+ const matchedSuffix = allEnvSuffixes.find(suffix => ENV.endsWith(suffix));
195
+ let portNumber = envPortMapping[matchedSuffix] || '5432';
196
+
197
+ if (portNumber === '5432') {
198
+ console.error(`No port number found for environment: ${ENV}. Defaulting to 5432.`);
199
+ }
200
+
201
+ // List secrets and get the first matching secret name
202
+ const secretNames = await listSecrets();
203
+ const SECRET_NAME = secretNames.find(name => name.startsWith('rds!cluster'));
204
+ if (!SECRET_NAME) {
205
+ console.error('No secret found with name starting with rds!cluster.');
206
+ return;
207
+ }
208
+
209
+ // Get secret value
210
+ const CREDENTIALS = await getSecretValue(SECRET_NAME);
211
+ const USERNAME = CREDENTIALS.username;
212
+ const PASSWORD = CREDENTIALS.password;
213
+
214
+ console.log(`Your connection string is: psql -h localhost -p ${portNumber} -U ${USERNAME} -d ${TABLE_NAME}`);
215
+ console.log(`Use the password: ${PASSWORD}`);
216
+
217
+ // Get instance ID
218
+ const INSTANCE_ID = await getInstanceId();
219
+ if (!INSTANCE_ID) {
220
+ console.error('Failed to find a running instance with tag Name=*bastion*.');
221
+ return;
222
+ }
223
+
224
+ // Get RDS endpoint
225
+ const RDS_ENDPOINT = await getRdsEndpoint();
226
+ if (!RDS_ENDPOINT) {
227
+ console.error('Failed to find the RDS endpoint.');
228
+ return;
229
+ }
230
+
231
+ // Start a port forwarding session (this requires AWS CLI tool as the SDK doesn't support starting sessions)
232
+ const portForwardingCommand = `aws ssm start-session --target ${INSTANCE_ID} --document-name AWS-StartPortForwardingSessionToRemoteHost --parameters "host=${RDS_ENDPOINT},portNumber='5432',localPortNumber='${portNumber}'" --cli-connect-timeout 0`;
233
+ console.log(`Run this command to start port forwarding: ${portForwardingCommand}`);
234
+ }
235
+
236
+ main().catch(err => {
237
+ console.error(err);
238
+ });
239
+ ```
81
240
 
82
- The application logs the output of each command and any errors that occur.
241
+ This documentation provides detailed instructions on installation, usage, prerequisites, and how the system works, making it easy for users to understand and use your application effectively.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rds_ssm_connect",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-ec2": "^3.495.0",