aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 1a892a556341c42eadc07e9cec856e9559b535e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# Cloud Identity Broker

This is a cloud identity broker. Identity brokers exist to bridge
authentication from one system into authentication to another system. In the
case of this broker it bridges GitHub and GitLab authentication into temporary
credentials for cloud providers. The broker has an interactive API that can be
used in a web browser as well as a JSON/REST API that can be consumed
programmatically.

The reason this broker exists is to provide one secured location for long-lived
cloud provider credentials that can be easily consumed from development
environments and build systems while limiting the scope of access and time frame
of access those systems have to cloud resources. This helps to increase the
security of those accounts and reduce the risk of abuse. All access through the
broker is chained to an authenticated and authorized user account and all
access through those user accounts are logged for auditing. All credentials
returned by the broker have a strict time limit after which they are useless.

This broker started life as a piece of internal infrastructure specific to AWS
that has been re-written and open sourced with the goal to support multiple
clouds.

For documentation the REST API look at the `README_BROKER.md` file.

## Contributing

Contributions are welcomed. Please send contributions to mike-at-crute-dot-us
either through email in `git format-patch` format or send a link to a git repo
and branch name that the author can pull and merge.

If you're reading this on one of the author's git forge accounts (GitHub,
GitLab, sr.ht, etc...) feel free to open a pull/merge request with your
changes.

The author reserves the right to request changes to contributions before
merging them or to not merge them at all but will endeavour to be reasonable in
those requests.

## Building

This requires Go 1.17 or newer to build. Provided that a simple `make` should
create a `cloud-identity-broker` binary that's ready to use.

The built binary embeds all of the templates in production mode and will
require nothing more than the binary itself to run, if running in `--debug`
mode then the `templates` folder must be available.

## Running

It's complicated, so probably don't?

The application requires some bits of infrastructure to be in place for it to
run but then can be exposed directly to the internet or put behind a reverse
proxy. You will need:

- [Mongodb](https://www.mongodb.com/)
- [Vault](https://www.hashicorp.com/products/vault)
- [GitHub Oauth Application](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app)
- [SSL certificates](https://letsencrypt.org/).

Once the requisite infrastructure (see below) is configured, run the binary
like so:

```
VAULT_ROLE_ID="..." \
VAULT_SECRET_ID="..." \
VAULT_ADDR="https://your-vault-addr:8200" \
    ./cloud-identity-broker \
		--mongodb-uri="mongodb://your-mongodb-host:27017/your-db-name?authSource=admin" \
		--mongodb-vault-path="database/static-creds/your-cred-name" \
		--github-oauth-vault-path="service/service-name/github-oauth" \
		web
```

### SSL Certificates

SSL certificates of a cipher type compatible with Go's SSL library are required
to run the binary, even in development mode. Obtain those certificates however
you would normal do so.

Both a key and certificate are required to be stored in the directory
identified by `--tls-cache-dir` (which defaults to `./ssl/`). Both files should
be of PEM format with the certificate named `cert.pem` and the key named
`key.pem`.

### Vault Setup

Configure Vault per the manufacturers instructions. Create an AppRole for the
identity broker and provide the credentials to the binary using the standard
Vault environment variables.

The binary will need access to a set of GitHub Oauth client credentials for a
GitHub Oauth application that is used to authenticate users to the broker.
Setup an application on GitHub and store the client ID and client secret in a
JSON document in Vault the vault KV backend with the following format:

```
{
    "client-id": "your client id",
    "client-secret": "your client secret"
}
```

Provide the path to this material with the `--github-oauth-vault-path` command
line argument. You should omit the `kv/data/` prefix to the path.

For each AWS cloud account to which the broker provides access a JSON document
must be stored in the Vault KV backend. The format of this document is as
follows. The path to this document is provided (with the `kv/data/` prefix
omitted)  in the `VaultMaterial` field of the `Account` record for the account
in Mongodb.

```
{
    "AccessKeyId": "...",
    "SecretAccessKey": "...",
    "Roles": {
        "account-short-name": {
            "ARN": "arn:aws:iam::...:role/...",
            "ExternalId": "..."
        }
    }
}
```

The fields are:

- `AccessKeyId` which is the access key ID of an IAM user that can assume roles
  in the target account.
- `SecretAccessKey` is the secret key for the IAM user identified by the access
  key ID.
- `Roles` is a mapping of account `ShortName` to an AWS ARN and ExternalId used
  for assuming roles. The `ARN` is the role to be assumed and the `ExternalId`
  is the External ID configured in the role trust policy.

Note that this application does **not** use the AWS Vault backend to assume
roles due to limitations AWS places on roles assumed using assumed role
credentials and not user credentials.

Finally the broker will need access to a Mongodb credential. Currently this
requires a static credential but in the future a dynamic credential will be
acceptable. Create this credential and pass it in the `--mongodb-vault-path`
argument. It should have the form `database/static-creds/your-cred-name`.

### Mongodb Setup

The application needs a Mongodb database with at least a `users` collection
created. The rest are optional.

To create the `users` collection insert a record to the collection that
contains your GitHub username as the `_id` field and has `IsAdmin` set to true.
For example:

```
db.users.insert({ "_id": "mcrute", "IsAdmin": true })
```

This is adequate to allow login via GitHub for the named user. All other fields
will be populated automatically by the app.

To create allowed AWS accounts for use in the broker add them to the `accounts`
collection. Those records have the following form:

```
{
    "_id": "acocunt-short-name",
    "AccountNumber": 12345,
    "AccountType": "aws",
    "ConsoleSessionDuration": 21600000000000,
    "DefaultRegion": "us-west-2",
    "Name": "Some Description",
    "Users": [
        "username1",
        "username2"
    ],
    "VaultMaterial": "some/path/as/above"
}
```

- `_id` is the short name of the account. This must also map into a Vault
  material per above.
- `AccountNumber` is the AWS account number for the account being brokered.
- `AccountType` is the string `aws` for now
- `ConsoleSessionDuration` is the number of nanoseconds a console session can
  exist before timing out. (Nanoseconds are silly, yes; it's a serialized
  time.Time)
- `DefaultRegion` is the region considered default, this is just used as an
  indicator in the JSON API.
- `Name` a longer form, descriptive name of the account.
- `Users` a case-sensitive list of GitHub user names that have access to this
  account
- `VaultMaterial` the path to the Vault material that contains the account
  credentials document, as above.

## To Do

- Allow GitLab CI jobs to auth using [job tokens](https://docs.gitlab.com/ee/api/jobs.html#get-job-tokens-job)
- Implement an Admin UI, all admin ops are directly on the DB at the moment
- Support dynamic mongodb credentials
- Support for other clouds
  - GCP
  - OCI
  - Azure

## Contributors

- [Mike Crute](https://mike.crute.us)