Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/buildkite/iam-ssh-agent

Keyless SSH Agent for IAM Entities
https://github.com/buildkite/iam-ssh-agent

authentication aws-sam continuous-integration iam serverless ssh-agent ssh-keys

Last synced: 4 months ago
JSON representation

Keyless SSH Agent for IAM Entities

Lists

README

        

> [!IMPORTANT]
> This package is no longer actively maintained or supported.

# iam-ssh-agent

A replacement ssh-agent that uses the caller's IAM identity to access a list of
permitted ssh identities.

`iam-ssh-agent` is designed to be used in less trusted continuous integration
environments where you want to use an ssh key to clone source control
repositories without providing the raw key material.

`iam-ssh-agent` is split into two components: a binary that binds a unix domain
socket with the ssh-agent protocol, and a serverless API that uses API Gateway
and Lambda functions to answer `list keys` and `sign data` requests.

- [`/agent`](agent) a Rust crate that builds the `iam-ssh-agent`
binary.
- [`/service`](service) an AWS SAM project that deploys the serverless
backend for the `iam-ssh-agent` binary.

For deployment instructions see the [`service` README](service/README.md#deploying).
Once you have successfully deployed the service you can
[add keys](#adding-keys), [grant](#granting-access-to-keys), and
[test](#testing-access) access.

For development and testing:

- [`/client`](client) a node package used for testing the ssh-agent
implementation and comparing output to other ssh-agent implementations.

## Protocol

By storing the ssh private keys behind a service boundary, and providing an
authenticated, access controlled signing service, client environments can
authenticate without access to the ssh private keys.

![](images/protocol.png)

_Generated using https://sequencediagram.org/_

## Agent

The agent binary should be a near drop-in replacement for existing uses of
ssh-agent, or provide a pathway for you to remove private key material from
continuous integration hosts. It should be installed in the same place you
currently use `ssh`.

The agent requires an `IAM_SSH_AGENT_BACKEND_URL` environment variable. This URL
will be printed following a successful deploy of the [service](#service) and
will be formatted like `https://{api-gateway-id}.execute-api.{region}.amazonaws.com/Prod`.

The agent binary will auto discover IAM credentials in the expected places:
environment variables, EC2 instance metadata, or ECS task metadata. Requests to
the API Gateway will be signed with these credentials and the service will
provide access to keys listed in the DynamoDB Permissions table for the caller's
IAM entity.

The agent can be installed from the Debian packages attached to the
[GitHub releases](https://github.com/buildkite/iam-ssh-agent/releases) or
using `cargo` to build the binary yourself. It is also published to Docker hub
as [buildkite/iam-ssh-agent](https://hub.docker.com/r/buildkite/iam-ssh-agent).

## Service

An API Gateway is configured to forward requests to two lambdas: ListIdentities
and GetSignature. The `iam-ssh-agent` never sees the raw key material, it can
only ask for a list of available keys or a signature for a key it has access
to.

Keys are stored in AWS Systems Manager Parameter Store where the private keys
can be encrypted with a KMS key. Key permissions are stored in a DynamoDB table
keyed by [IAM Entity Unique ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids).

See the [deploying guide](service/README.md#deploying) for instructions on how
to deploy the service in your AWS Organization.

### Adding Keys

You can add keys to AWS Systems Manager Parameter Store using the AWS CLI or
Console. Public and private keys are stored in separate parameters. The
ListIdentities lambda has access to the public key parameters and the
GetSignature lambda has access to both.

You can use any hierarchy to store your public and private keys in SSM so long
as the parameter paths end in `key.pub` and `key` respectively.

Example key hierarchies:

```
# GitHub repository deploy key
/github/keithduncan/iam-ssh-agent/key.pub
/github/keithduncan/iam-ssh-agent/key

# Machine user key
/github/machine-user1/key.pub
/github/machine-user1/key

# GitLab Global Key
/gitlab.company.com/global/name/key.pub
/gitlab.company.com/global/name/key
```

The GetSignature lambda IAM role includes a policy that permits `kms:Decrypt`
using the `aws/ssm` KMS key. You can store your ssh private keys in a
`SecureString` parameter encrypted with that key to prevent unintended access to
the raw key material. Deploying this service to a unique AWS account also
helps limit access to the key material.

To generate and store an ssh key pair in the Parameter Store:

```
# Don't enter a passphrase, the private key will be encrypted using a KMS key
$ ssh-keygen -f test-key

# Store the keys in Parameter Store
$ aws ssm put-parameter \
--name /github/username/repository/key.pub \
--type String \
--value "$(