Code Monkey home page Code Monkey logo

basti's Introduction

Basti


Basti (from Bastion Host) is a CLI tool for securely accessing your DB instances and other AWS resources in private networks at almost no cost.

💵 No idle costs. 🔑 No SSH keys. 🔒 Fully IAM-driven.

Demo

Table of contents


💡 Why Basti?

With Basti, you can securely connect to RDS, Aurora, Elasticache, or any other AWS resources in private VPC subnets from a local machine or a CI/CD pipeline almost for free!

AWS Session Manager is a fantastic tool! But Basti makes it even better:

  • 🦾 With Session Manager, you need to oversee an EC2 bastion instance for connecting to managed resources such as RDS or Elasticache. Basti handles bastion instance setup, shutdown, and updates for you!

  • 💅 Basti provides a convenient way to store and reuse connection configuration across your team.

  • 📶 Basti improves stability of the Session Manager sessions by automatically restarting failed or expired sessions.

⚙️ How it works

  • 🏰 Basti sets up a so called bastion EC2 instance in the connection target's VPC.

  • 🧑‍💻 The bastion instance is used with AWS Session Manager port forwarding capability to make the target available on your localhost.

  • 💵 Basti takes care of keeping the bastion instance stopped when it's not used to make the solution cost as low as ≈ 0.01 USD per hour of connection plus ≈ 0.80 USD per month of maintaining the instance in a stopped state.

  • 🔒 Security completely relies on AWS Session Manager and IAM policies. The bastion instance is not accessible from the Internet and no SSH keys are used.

💻 Installation

Using homebrew

brew install basti

Using npm

npm install --global basti

Other, NodeJS-independent, installation options are coming soon!

🏄 Basic usage

Basti uses AWS SDK and relies on credentials to be configured in your system. You can use any of the methods supported by AWS SDK to configure credentials.

💡 You can expect Basti to work if you can use AWS CLI in your terminal.

☝️ Initialize connection target

First, initialize your connection target. It could be an RDS instance, an Elasticache cluster or any other target residing in a VPC. The following command will set up all the infrastructure required to start a connection. You only need to do this once.

basti init

You will be prompted for a target to initialize and a public VPC subnet to create the bastion EC2 instance in.

✌️ Connect to the target

Now, you can start the connection. This command will establish a secure port forwarding session and make the target available on your localhost.

basti connect

You will be prompted for the target to connect to as well as the local port to forward the connection to.

🎉 Use the target on localhost

Finally, you can use the target same way as it was running on your localhost and port you specified in the previous step.

psql -h localhost -p 5432

💡 psql, the PostgreSQL client, is used as an example here. Basti can be used to connect to any type of database or other services as long as the communication is done over TCP.

Cleanup (optional)

You can remove all the resources created by Basti in you AWS account.

basti cleanup

The list of resources will be displayed and you will be prompted to confirm the cleanup.

🧶 Reference documentation

Please, refer to the reference documentation for the full description of Basti CLI options and the configuration file.

💠 Custom connection targets

Basti provides first class support for RDS instances, Aurora clusters, and Elasticache clusters. However, you can use Basti to connect to any other target in your AWS VPC (e.g. DocumentDB instance, EC2 instance, etc.).

To connect to a custom target, select the Custom option when prompted for a target to initialize or connect to. You will be prompted for the target's VPC, IP address and port.

🤝 Feel free to open an issue or a pull request if you want to extend the list of natively supported targets

🎛️ Advanced initialization options

The basti init command has a number of advanced options that can be used to customize the bastion instance and other resources created by Basti.

💡 Please, refer to the reference documentation for the full list of options.

Resource tags

You can specify tags to be applied to the bastion instance and other resources created by Basti. This can be done in three ways:

  1. By entering the tags in the advanced options section of the interactive mode.
  2. By passing the --tag option. This option accepts tag name and value separated by an equal sign. For example, --tag Project=my-project This option can be used multiple times to specify multiple tags.
  3. By passing the --tags-file option. This option accepts a path to a JSON file with tags. The option can be used multiple times to specify multiple files.

Example of a tags file:

{
  "Project": "my-project",
  "Environment": "production"
}

Tags with the same name will be overwritten in the order they are specified. Tags specified with the --tag option will always overwrite tags specified in the tags file.

💡 If your tags contain special characters, it might be easier to use interactive mode or the --tags-file command than escaping the characters in the --tag option.

Bastion instance type

You can specify the EC2 instance type to be used for the bastion instance using the --bastion-instance-type option or by entering it in the advanced options section of the interactive mode. The default instance type is t2.micro, but it's subject to change in the future.

🦾 Automatic mode

Using interactive mode is convenient when you're getting used to Basti. However, in Continuous Integration and Continuous Delivery (CI/CD) pipelines, you will probably want to disable interactivity and pass all the options as command line arguments:

basti connect --rds-instance your-instance-id --local-port your-port

Use basti <command> --help to see all the available options for basti connect and other commands.

To continue executing the script after the connection is established, you can use Basti in conjunction with the wait-on utility and the & shell operator:

basti connect --rds-instance your-instance-id --local-port your-port &
wait-on tcp:localhost:your-port

📝 Configuration file

When working with multiple connection targets, it becomes convenient to store their configurations and other Basti settings in a dedicated configuration file. To facilitate this, Basti automatically searches for the configuration file in the current directory and its parent directories. The supported file names are .basti.yaml, .basti.yml, and .basti.json.

You can quickly start a connection defined in the configuration file by passing its name to the basti connect command:

basti connect your-connection
Configuration file example

This example uses YAML format. The same configuration can be written in JSON.

# - Connections are used with the `basti connect <connection>` command
# - Targets' fields are the same as the options for the `basti connect` command
connections:
  database-dev:
    target:
      rdsInstance: my-dev-database
      awsProfile: dev
    localPort: 5432

  database-prod:
    target:
      rdsInstance: my-prod-database
      awsProfile: prod
    localPort: 5432

  # Default AWS profile and region are used if not specified in the target
  redis-cache-dev:
    target:
      elasticacheRedisCluster: my-dev-cache
    localPort: 6379

  # Same target but with different local port
  custom-target-local:
    target: custom-target
    localPort: 4646

# Targets can be extracted and reused in multiple connections
# with different local ports
targets:
  custom-target:
    customTargetVpc: vpc-1234567890
    customTargetHost: 10.0.1.1
    customTargetPort: 4646
    awsProfile: prod
    awsRegion: us-east-1

💡 Please, refer to the reference documentation for the full list of configuration options.

💫 Infrastructure as code (IaC)

Introducing, Basti CDK, an AWS CDK construct library that allows you to integrate Basti with your existing CDK-managed infrastructure.

Feel free to open an issue if you want to see Basti in Terraform or other IaC tools. Contributions are welcome 🤗

🏢 Basti in teams and organizations

Basti was designed with organizational usage patterns in mind. The bastion instance and other infrastructure created by Basti is reused across all the users in your organization.

Minimal IAM permissions

Basti commands require different sets of IAM permissions. basti init needs broad permissions to set up all the infrastructure required to start a connection. basti connect, on the other hand, requires only minimal permissions to start a connection. This means that the AWS account administrator can run the basti init command once and then grant the minimal permissions to the IAM users who need to start connections.

Minimal IAM policy for connection

The following command is optimized for minimal permissions required to start a connection. It doesn't need to retrieve the target information as it's passed as command line arguments.

basti connect --custom-target-vpc your-vpc-id --custom-target-host your-target-host --custom-target-port your-target-port --local-port your-local-port

Minimal policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:DescribeInstances",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "ec2:StartInstances",
      "Resource": "arn:aws:ec2:<your-region>:<your-account-id>:instance/<your-basti-instance-id>"
    },
    {
      "Effect": "Allow",
      "Action": "ec2:CreateTags",
      "Resource": "arn:aws:ec2:<your-region>:<your-account-id>:instance/<your-basti-instance-id>"
    },
    {
      "Effect": "Allow",
      "Action": "ssm:StartSession",
      "Resource": [
        "arn:aws:ssm:*:*:document/AWS-StartPortForwardingSessionToRemoteHost",
        "arn:aws:ec2:<your-region>:<your-account-id>:instance/<your-basti-instance-id>"
      ],
      "Condition": {
          "BoolIfExists": {
              "ssm:SessionDocumentAccessCheck": "true"
          }
      }
    }
  ]
}

Usage audit

Since Basti uses IAM for access control, the connection history, along with the responsible IAM user and all the connection details, can be audited using AWS CloudTrail by filtering on the "StartSession" event. Please, refer to the AWS CloudTrail documentation for more details.

A simple connections history can also be found in the AWS Session Manager history. See AWS Session Manager documentation for more details.

Shared configuration

The Basti configuration file file can be shared across your organization, making it easy for all developers to connect to the project's cloud infrastructure. A recommended practice is to store the configuration file in the root of your project's repository. This ensures that the configuration is readily accessible to all team members, enabling quick and seamless connections to the required cloud resources.

🔐 Security

Security is a top priority for Basti. The following sections describe the security measures taken by Basti.

Network

The bastion EC2 instance reachability from the Internet is completely disabled with AWS Security Groups configuration. No ports are open for inbound traffic. The bastion instance is only accessible through AWS Session Manager.

Basti automatically adjusts the target's Security Group to allow inbound traffic from the bastion instance's Security Group.

Access control

AWS Session Manager, which is used by Basti to establish a port forwarding session, doesn't use SSH keys for access control. Instead, it relies on AWS IAM users and their permissions in your AWS account. This also means that AWS CloudTrail could be used to audit Basti usage.

Software

Basti uses the latest Amazon Linux 2 - Kernel 5.10 AMI available at the initialization time (basti init command) for the bastion instance.

The bastion instance EBS volume is encrypted by default.

The bastion instance is being stopped when it's not used for some short period of time. These shutdowns are also used to update the bastion instance's software packages and OS kernel. By default, the updates happen once a day but not more often than the bastion instance is used.

❤️ Development

First of all, thank you for your interest in contributing to Basti! 🎉

The following section describes how to run your local version of Basti CLI as you make changes to the code. Please, feel free to open an issue if you want to see Basti CDK development guide!

Build

Before proceeding to development, it's recommended to run the full build. This requires Docker to be installed on your machine and may take a couple of minutes.

npm run build

Full Basti build consists of two parts:

  1. Compiling Basti TypeScript code. The code has to be compiled after each change.
    npm run build-src
    
    # Or, if you want to automatically recompile on each change:
    npm run build-src-watch
  2. Building non-NodeJS dependencies (AWS session-manger-plugin). This step is only required after the first checkout or in a rare case when the dependencies are updated.
    npm run build-deps

Run

After the build is complete, you can run Basti:

npm run start -- <command> <options>

Alternatively, you can link-install the local version of Basti in your system and use it as you would usually use Basti:

# Link-install the local version of Basti
npm link

# Run Basti
basti <command> <options>

Test

Before submitting a pull request, please make sure that all the tests and checks pass:

npm run test

License

Usage is provided under the MIT License. See LICENSE for the full details.

basti's People

Contributors

adamaltman avatar ayeone avatar bobveringa avatar bohdanpetryshyn avatar chenrui333 avatar dependabot[bot] avatar dollev36 avatar gustavoadriangimenez avatar motnyk avatar nitrocode avatar ramimac avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

basti's Issues

Default Encryption for ec2 instances volumes

Feature Description

To enhance security, it's important to attach encrypted EBS volumes for EC2 instances.

Use Case

NA

Proposed Solution

Perhaps we could enable the encryption configuration here . We would be pleased to collaborate if you are in agreement

Related Issues/PRs

NA

First-class EC2 support

Summary

Currently, users must use the custom connection target approach to connect to services running on EC2 instances. This involves manually setting up connectivity (at init time) and providing Basti with the target's IP and port (at connect time).

Solution

The first-class EC2 support could be implemented in the following way:

  1. User selects the EC2 instance and a port where the service is running during basti init
  2. The Basti access security group, which allows connection from the bastion instance to the target will have one ingress rule service (one ingress rule will be added per one basti init run)
  3. The per-service ingress rule will have the name of the service in the description (the
    user will be prompted for a name during initialization)
  4. When connecting, the user will be presented not only with the EC2 instances but with services running on those instances based on the ingress rules of the Basti access security group.

This includes:

  1. Detecting EC2 instances in the user's AWS account and presenting them during initialization
  2. EC2 instance initialization (setting up the access security group or reusing the existing one)
  3. Detecting services running on the EC2 instances by the Basti access SG and it's ingress rules
  4. EC2-related resources cleanup in basti cleanup command

basti: Permissions too broad

Bug Description

The bastion is currently provided the s3:GetEncryptionConfiguration permission. This permission is not needed for general SSM operations, and my investigation has not yielded any results where Basti would need this permission.

I didn't give basti this permission in my PoC for the CDK construct, and everything seems to work fine.

The permission is added here:

https://github.com/BohdanPetryshyn/basti/blob/1c960f012d1764143f712fbd3af6b5b1ca6d8191/src/bastion/create-bastion-role.ts#L64

Documentation site

Feature Description

The project requires extended reference documentation but the root README.md file is already pretty bit.

Proposed Solution

We'll set up a full-blown documentation site at https://www.basti.app

Related Issues/PRs

#31

shell completion issue

While packaging for homebrew, I ran into some shell completion issue as below:

~ basti completion zsh
basti <command>

Commands:
  basti init                  Initialize a target to use with Basti                                                                                [aliases: i]
  basti connect [connection]  Start port forwarding session with the selected target                                                               [aliases: c]
  basti cleanup               Remove all resources created by Basti                                                                               [aliases: cl]
  basti completion            Generate completion script for your shell

Options:
  -h, --help     Show help                                                                                                                            [boolean]
  -v, --version  Show version number                                                                                                                  [boolean]

Examples:
  basti init     Initialize a target in interactive mode
  basti connect  Start connection in interactive mode
  basti cleanup  Cleanup Basti resources in interactive mode (requires confirmation)

Did you mean cl?
➜  ~ echo $?
1

Log an issue in here for visibility.

Describe required AWS permissions in README

Tested the tool, very impressed by the smoothness of setup and functionality.
One thing, however, which would have to be figured out, if an org wants to give this functionality to devs: is to what set of permissions to grant. Could you please describe this in documentation?

Add custom tags to instance and related resources

Feature Description

Add possibility to add custom tags that are applied to the instance and related resources.

Use Case

If an organization has a tag policy / SCP combination active that enforces a set of standard tags, basti cannot be used.
Additionally, some organizations have cost allocation tags active which makes it easier to accumulate cost that are induced by basti.
Also, ownership tags are a use case that could come in handy if teams are using basti to access their resources for increased transparency.

Proposed Solution

  • add key-value list of tags, maybe in the basti config or as json for the cli that are applied to the basti instance on creation

Related Issues/PRs

none

Bug report, Feature request and PR templates

Hello!

I hope you're all doing well. I would like to propose the introduction of issue templates, pull request (PR) templates, and feature request templates in the repository. These templates will bring several benefits to the collaborative development process.

  1. Bug report template: By using a standardized bug report template, we can ensure that all bug reports include essential information such as steps to reproduce, expected behavior, and current behavior. This will help us reproduce and resolve issues more efficiently and provide a better experience for our users who encounter bugs.

  2. Feature request template: Implementing a feature request template will provide a structured format for users to communicate their ideas and requirements for new features. This will help us understand the use case, evaluate the feasibility, and prioritize feature requests effectively. It also encourages users to provide additional context and alternative solutions, fostering valuable discussions.

  3. PR template: The addition of a PR template will streamline the pull request process. Contributors can provide clear descriptions of their proposed changes, reference related issues, and verify that they have followed coding style guidelines, added tests (if applicable), and tested their changes locally. This will enhance the quality of the codebase, simplify the review process, and ensure that contributions align with the project's standards.

Having these templates readily available will benefit both contributors and maintainers by providing clear guidelines and reducing ambiguity when submitting and reviewing issues, feature requests, and pull requests.

I am willing to take the responsibility of creating and implementing these templates if it's ok. Please share your thoughts and let me know if you have any suggestions or concerns.
I'll PR / proposal soon.

Monorepo versioning

Context

By the time this issue is created, there're two packages in this monorepo:

  1. Basti CLI (basti)
  2. Basti CDK (basti-cdk)

Suggested versioning strategy

  1. basti and basti-cdk are both versioned independently following semantic versioning.

  2. A new major version is released in two cases

    1. The user interface has changed. For example, a basti-cdk property or a basti CLI option has been renamed.
    2. Basti CLI init command or basti-cdk infrastructure is no longer compatible with the existing versions of the Basti CLI connect command.
  3. Newer versions of Basti CLI must support connecting to any older minor and major version of the infrastructure.

  4. basti connect command checks if the infrastructure was initialized with the satisfying major version of Basti CLI or Basti CDK. If not, the user is asked to update to the latest version of Basti CLI (which must support the newer infrastructure).

Feature request: remember local port

Remember the local port previously used for specific connect target and suggest it on the subsequent connect.

Users will have DB connections saved locally so it's important to use same port.

Improve error messages structure

Feature Description

Improve error messages structure, as it makes it easier to solve a problem for end-user.
For example:

❌ Error checking target state. Unexpected error: The SSO session associated with this profile has expired. To refresh this SSO session run aws sso login with the corresponding profile.

Can be

❌ Error checking target state. 

⚠️ The SSO session associated with this profile has expired. 

To refresh the SSO session, please run the following command with the corresponding profile:

aws sso login --profile <profile_name>

Proposed Solution

Separate error message from suggested fix, when it's possible

Related Issues/PRs

not yet : )

Options to choose writer or reader endpoints on aurora RDS

At the moment, basti presents all the RDS instances irrespective of whether it is for an aurora cluster or nor normal RDS instance.

It would be great to present just the writer / reader endpoints especially where there are many readers in a aurora cluster.

basti: Add option to save logs

Feature Description

The Basti CLI currently only logs to the terminal. This issue proposes a solution that would allow logging to log file.

A logging config option would allow users to specify a file or location (or a default location would be used otherwise) where the Basti CLI would log its activity. This would be beneficial for a number of reasons, including:

  • Troubleshooting problems: If the Basti CLI encounters a problem, the log file could be used to track down the cause of the problem and to identify any errors that may have occurred.
  • Auditing: The log file could be used to audit the activity of the Basti CLI and to ensure that it is being used in a secure and compliant manner.

Proposed Solution

Building on issue #59 it would make sense to create a .config.yml (or json) file in this ~/.basti directory. This would then have a section for logging.

logs:
  save_logs: true
  log_line_limit: 1000
  save_location: ~/.basti/logs/

save_logs would enable or disable logging to a file
log_line_limit is intended to limit the size of the file. This avoids log files that end up GB's in size.
save_location allows the user to configure a save location, but default this is stored in the ~/.basti directory.

The logging itself should always be prefixed with a timestamp. This helps with troubleshooting events in time and allows you to check with AWS logging as well.

Initially, I'd recommend that these settings can just be modified through the config.yml file, but later a command could be added that changes these settings. basti config logs.save_logs true for example.

Related Issues/PRs

#59

Idea: configuration sets

Connection to the same target is repetitive right now and requires someone to carefully pick the target and use correct port.

Would be slick to have some predefined configurations set (which we can distribute to all our users) which will allow doing something like:

basti connect prod-db
basti connect staging-db

Behind the scenes it will pick correct region, target and local port.

The config format may be as simple as that:

{
  "prod-db": { "target": "production-postgres-13", "localPort": 1234, "region": "us-east1" }
   // ...
}

You can store this config in ~/.aws/basti for example.

I know this can be achieved with cli args though so we can just share predefined commands.
So maybe this is an overkill.

First-class Elasticache support

Summary

Currently, users must use the custom connection target approach to connect to Elasticache instances. This involves manually setting up connectivity (at init time) and providing Basti with the target's IP and port (at connect time). Let's implement first-class support for Elasticache, just like for RDS. This includes:

  1. Detecting Elasticache instances in the user's AWS account and presenting them as options in the connect and init commands
  2. Elasticache instance initialization
  3. Elasticache instance connection
  4. Elasticache-related resources cleanup

TODO

  • Redis support
  • Memcached support
  • Documentation

mismatched arch session-manager-plugin got bundled

While packaging for homebrew, I noticed that the wrong arch session-manager-plugin got bundled (below is npm build for a apple arm machine):

Warning: Binaries built for a non-native architecture were installed into basti's prefix.
The offending files are:
  /opt/homebrew/Cellar/basti/1.6.2/libexec/lib/node_modules/basti/node_modules/basti-session-manager-binary-darwin-arm64/session-manager-plugin	(x86_64)

AWS CDK Support

Feature Description

Instead of creating the basti resources with the command basti init there would also be an option of creating the resources through an AWS CDK construct.

An AWS CDK construct for Basti would offer the following benefits:

  • Easier to assign permissions: AWS CDK would allow users to easily assign permissions to Basti bastion hosts. This would make it easier to ensure that Basti bastion hosts only have the permissions that they need.
  • Easier to set up monitoring: AWS CDK would allow users to easily set up alarms and other monitoring for Basti bastion hosts. This would help users to keep Basti bastion hosts secure and healthy.
  • More consistent infrastructure: AWS CDK would allow users to create a consistent infrastructure for their Basti bastion hosts. This would make it easier for users to manage and maintain their Basti bastion hosts.
  • Infrastructure is better documented: AWS CDK is infrastructure-as-code, a construct would mean that Basti resources are also documented, this makes it more transparent to maintain.

Use Case

Currently, users can create Basti bastion hosts using the basti init command. However, this can be difficult to use when all other resources are manged through AWS CDK, as it requires users to manually assign permissions and set up monitoring. An AWS CDK construct would make it easier for these users to create Basti bastion hosts, as it would allow them to use the AWS CDK's built-in permission and monitoring features.

Proposed Solution

The construct should do a lot, but should not be too configurable. The interface should be relatively simple. As targets are most often selected when connecting to the bastion host, the initial version should just set up the bastion host and no more. The interface in python (CDK supports many languages through JSII) would just be a class.

from basti_cdk import BastiHost

host = BastiHost(self, 'bastiHost')

The basti CDK construct can then create its own VPC and any subnets it needs. Maybe the interface can be expanded that these are created.

The construct could also be more limiting and only allow access to a specific database/database cluster.

Related Issues/PRs

No related PRs

Notes

I would be able to help in creating this functionality.

Basti init asks for a connection target

I'm not sure why basti init asks for a connection target but then basti connect asks it again.

If there are some steps needed to init the connection this should support multi-select.

Logs

If they aren't yet, logs should be sent to cloudwatch (this should include system logs and access logs).

Why? An audit trail is vital for security programs, so to use this in a production environment, logging needs to be enabled.

If logs are already enabled, then logs should be mentioned in the README.

basti connect results in error with some node versions while using with npx

Command used:
AWS_PROFILE=support npx basti connect --rds-instance production-postgres-13 --local-port 5434

Output:
TypeError [ERR_PACKAGE_IMPORT_NOT_DEFINED]: Package import specifier "#src/common/debug.js" is not defined in package /Users/antonkozachuk/.npm/_npx/a74823000dc99449/node_modules/basti/dist/package.json imported from /Users/antonkozachuk/.npm/_npx/a74823000dc99449/node_modules/basti/dist/src/cli/run.js at throwImportNotDefined (internal/modules/esm/resolve.js:293:9) at packageImportsResolve (internal/modules/esm/resolve.js:574:3) at moduleResolve (internal/modules/esm/resolve.js:700:21) at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:819:11) at Loader.resolve (internal/modules/esm/loader.js:89:40) at Loader.getModuleJob (internal/modules/esm/loader.js:242:28) at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:73:40) at link (internal/modules/esm/module_job.js:72:36) { code: 'ERR_PACKAGE_IMPORT_NOT_DEFINED' }

Screenshot:
image

basti-cdk: Instance has insufficient permissions

Bug Description

The Basti ec2 instance has insufficient permissions to operate. It requires the ec2:DescribeInstances and ec2:CreateTags permissions to be granted. But they are not. As a result, when starting a basti connection it is only functional for around 1 minute, after which the instance shuts down again as the script it is running has an error.

I have no idea why I did not notice this sooner. It might have something to do with a dependency issue that I removed to fix later, but then never fixed.

The solution is not ideal, as it is not possible (at least not to my knowledge) to restrict the resource scope to the instance alone, as it would create a circular dependency. This means that the scope for the ec2:CreateTags action is wider than it should ideally be. I'll submit a PR that introduces some fixes for this.

Support Node < 14.0.0

Problem

Using basti with Node versions lower than 14.0.0 results in errors connected to Subpath Imports and ESModules usage.

Proposed solution

The build process has to be reconfigured to support older Node versions.

References

Related issue: #21

Document minimal IAM permissions required for connect

Here is the minimal set of permissions that worked for me:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:AuthorizeSecurityGroupEgress",
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:StartInstances",
                "ec2:CreateTags",
                "ssm:StartSession"
            ],
            "Resource": [
                "arn:aws:ec2:us-east-1:<account-id>:instance/i-<basti-instance-id>",
                "arn:aws:ec2:us-east-1:<account-id>:security-group/sg-<basti-security-group-id>",
                "arn:aws:ssm:*:*:document/AWS-StartPortForwardingSessionToRemoteHost"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "ec2:DescribeSecurityGroupRules",
                "ec2:DescribeInstanceAttribute",
                "ec2:DescribeNetworkAcls",
                "ec2:DescribeSecurityGroups",
                "ec2:ModifySecurityGroupRules",
                "ec2:DescribeInstanceStatus"
            ],
            "Resource": "*"
        }
    ]
}

Instance randomly not connecting to SSM

Bug Description

In some cases, the SSM agent takes more than the default stop-timeout of 5 minutes to connect to SSM, therefore the EC2 can come up, but the user is not able to create an ssm session.
Also, the SSM agent could have crashed for some reason, which renders the same result: you cannot connect.

Steps to Reproduce

Disclaimer: this is hard to reproduce as it depends on several factors that are out of control of the user.

  1. basti init
  2. basti connect
  3. basti instance does not show up in session manager
  4. connection times out
  5. basti instance stops

Expected Behavior

Basti instance is usable via SSM

Current Behavior

See Steps to Reproduce

Possible Solution (Optional)

I see three options:

  1. increase / make the default stop-timeout configurable

  2. add additional reboot to the instance after init (manual reboot helped in my case)

  3. (preferred option) make the basti instance check if it the SSM agent connected successfully so a session can be initialized. If not, (force) restart the SSM agent, wait X s, recheck. If basti instance cannot connect to SSM, perform reboot. If reboot does not help, terminate the instance.

Related Issues/PRs

none

Secure server hardening

Basti init starts an EC2 instance. Then it is in the VPC for potentially a long time (even though "off" when not in use). However, how does the instance get security patches? How is the instance monitored for security purposes? This type of documentation should be in the README so that a CISO can easily review to determine if Basti will work in their organization. Also, they would probably want to know the base image (assuming it is using a public one maintained by AWS or similar organization).

Side note: could basti work with fargate too instead of ec2?

homebrew formula to use `brew install basti`

Feature Description

Install the app without npm

Use Case

It would be nice to make installation easier on osx and linux by using homebrew without npm dependency

Proposed Solution

by supporting homebrew formula to use brew install basti.

A formula can be contributed to homebrew-core

https://docs.brew.sh/Formula-Cookbook

And updated via github action

https://github.com/cloudposse/atmos/blob/39d33c722a6d468df72f86d491171a0feba1d4fb/.github/workflows/build.yml#L38

Related Issues/PRs

N/A

basti: Store configuration in ~/.basti

Feature Description

Basti currently searches for a configuration file in your current working directory up to your home directory. This is great, however sometimes when you are using basti in directories above or outside the home directory it cannot find a configuration file. The solution for this would be to always check the home directory.

This could be in a .basti directory as this also allows other information related to basti to be stored here as well as leaving room for more features in the future. The other option is to just always check for .basti.yml (or json) files in the home directory.

Optionally setting instance family of EC2 instance

Feature Description

Currently, t2.micro is the default instance family and size that cannot be changed. This is fine for smaller setups that e.g. can benefit from the AWS free tier.

Adding the optional setting to change the instance family and size would be great to match an organizations requirements.

Use Case

For bigger setups at scale, it's a best practice to use either reserved instances or cost savings plans that may be limited to certain EC2 instance families.

If this is the case, basti instances would be charged at on demand pricing and would not benefit from existing cost saving measures.

Proposed Solution

Optionally setting the instance family and instance size as parameter in the CLI or in the config file.

Related Issues/PRs

Idea: github action

Basti can be integrated into github actions workflows but it's a bit hacky:

Here is how I did it:

npx basti connect --rds-instance $DB_INSTANCE_NAME --local-port $DB_PORT &
npx wait-on -t 60000 tcp:$DB_PORT

Notice the & at the end of the connect command to put basti into background mode.
One issue is it never stops the connection.

Would be great to have official github action which can incapsulate connection/wait and teardown using runs.post

Support multiple simultaneous connections

Summary

Sometimes you need to connect to multiple resources in your remote environment simultaneously. Currently, you need to run Basti multiple times in separate terminal windows. Being able to connect to multiple targets with a single Basti command would be useful.

Solution

UX

In interactive (basti connect) and automatic (basti connect <options>) modes, multiple target selection will become cumbersome. Multiconnect should only be supported in the predefined connection mode, when all the connection targets are defined in a configuration file.

A new top-level field "connection-groups" (the name is discussable) has to be introduced. The field will reference multiple connections. The connections might also be inlined like with target inlining.

connection-groups:
  prod:
    connections:
      - database-prod
      - cache-prod
  dev:
    connections:
      - database-dev
      - cache-dev

connections:
  database-dev:
    ...
  database-prod:
    ...
  cache-dev:
    ...
  cache-prod:
    ...

Connection groups and connection names must be unique. In other words, a connection group can't have the same name as a connection. This will allow to keep the connection command concise:

basti connect <connection | connection-group>

Tracking multiple connections

Basti must track and display the statuses of all the simultaneous connections. The application must exit when at least one of the connections dies.

Add --aws-profile command option

AWS CLI profile set up in the user's environment is expected to be the most common authentication method in Basti. If the user has multiple profiles set up, he or she can select a specific named profile with the AWS_PROFILE environment variable (it's a feature of AWS SDK).

Adding --aws-profile option would make Basti commands more readable and the profile selection feature more visible as well. The users would see that there's such an option in basti --help output.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.