aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2021-11-16 21:50:31 -0800
committerMike Crute <mike@crute.us>2021-11-17 07:56:17 -0800
commit73ab23b5f74174ec6b6a988103306eeec389d5a8 (patch)
treeed56d604a22d36ca9bf658064442d29f0e0a18b0
parentcc58a3da7d647de8520e33dc4356672d2ed1a366 (diff)
downloadcloud-identity-broker-73ab23b5f74174ec6b6a988103306eeec389d5a8.tar.bz2
cloud-identity-broker-73ab23b5f74174ec6b6a988103306eeec389d5a8.tar.xz
cloud-identity-broker-73ab23b5f74174ec6b6a988103306eeec389d5a8.zip
Add some docs
-rw-r--r--README.md205
-rw-r--r--README_BROKER.md228
2 files changed, 431 insertions, 2 deletions
diff --git a/README.md b/README.md
index ca08bbd..1a892a5 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,207 @@
1# Cloud Identity Broker 1# Cloud Identity Broker
2 2
3// TODO: https://docs.gitlab.com/ee/api/jobs.html#get-job-tokens-job 3This is a cloud identity broker. Identity brokers exist to bridge
4// TODO: Admin UI 4authentication from one system into authentication to another system. In the
5case of this broker it bridges GitHub and GitLab authentication into temporary
6credentials for cloud providers. The broker has an interactive API that can be
7used in a web browser as well as a JSON/REST API that can be consumed
8programmatically.
5 9
10The reason this broker exists is to provide one secured location for long-lived
11cloud provider credentials that can be easily consumed from development
12environments and build systems while limiting the scope of access and time frame
13of access those systems have to cloud resources. This helps to increase the
14security of those accounts and reduce the risk of abuse. All access through the
15broker is chained to an authenticated and authorized user account and all
16access through those user accounts are logged for auditing. All credentials
17returned by the broker have a strict time limit after which they are useless.
6 18
19This broker started life as a piece of internal infrastructure specific to AWS
20that has been re-written and open sourced with the goal to support multiple
21clouds.
22
23For documentation the REST API look at the `README_BROKER.md` file.
24
25## Contributing
26
27Contributions are welcomed. Please send contributions to mike-at-crute-dot-us
28either through email in `git format-patch` format or send a link to a git repo
29and branch name that the author can pull and merge.
30
31If you're reading this on one of the author's git forge accounts (GitHub,
32GitLab, sr.ht, etc...) feel free to open a pull/merge request with your
33changes.
34
35The author reserves the right to request changes to contributions before
36merging them or to not merge them at all but will endeavour to be reasonable in
37those requests.
38
39## Building
40
41This requires Go 1.17 or newer to build. Provided that a simple `make` should
42create a `cloud-identity-broker` binary that's ready to use.
43
44The built binary embeds all of the templates in production mode and will
45require nothing more than the binary itself to run, if running in `--debug`
46mode then the `templates` folder must be available.
47
48## Running
49
50It's complicated, so probably don't?
51
52The application requires some bits of infrastructure to be in place for it to
53run but then can be exposed directly to the internet or put behind a reverse
54proxy. You will need:
55
56- [Mongodb](https://www.mongodb.com/)
57- [Vault](https://www.hashicorp.com/products/vault)
58- [GitHub Oauth Application](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app)
59- [SSL certificates](https://letsencrypt.org/).
60
61Once the requisite infrastructure (see below) is configured, run the binary
62like so:
63
64```
65VAULT_ROLE_ID="..." \
66VAULT_SECRET_ID="..." \
67VAULT_ADDR="https://your-vault-addr:8200" \
68 ./cloud-identity-broker \
69 --mongodb-uri="mongodb://your-mongodb-host:27017/your-db-name?authSource=admin" \
70 --mongodb-vault-path="database/static-creds/your-cred-name" \
71 --github-oauth-vault-path="service/service-name/github-oauth" \
72 web
73```
74
75### SSL Certificates
76
77SSL certificates of a cipher type compatible with Go's SSL library are required
78to run the binary, even in development mode. Obtain those certificates however
79you would normal do so.
80
81Both a key and certificate are required to be stored in the directory
82identified by `--tls-cache-dir` (which defaults to `./ssl/`). Both files should
83be of PEM format with the certificate named `cert.pem` and the key named
84`key.pem`.
85
86### Vault Setup
87
88Configure Vault per the manufacturers instructions. Create an AppRole for the
89identity broker and provide the credentials to the binary using the standard
90Vault environment variables.
91
92The binary will need access to a set of GitHub Oauth client credentials for a
93GitHub Oauth application that is used to authenticate users to the broker.
94Setup an application on GitHub and store the client ID and client secret in a
95JSON document in Vault the vault KV backend with the following format:
96
97```
98{
99 "client-id": "your client id",
100 "client-secret": "your client secret"
101}
102```
103
104Provide the path to this material with the `--github-oauth-vault-path` command
105line argument. You should omit the `kv/data/` prefix to the path.
106
107For each AWS cloud account to which the broker provides access a JSON document
108must be stored in the Vault KV backend. The format of this document is as
109follows. The path to this document is provided (with the `kv/data/` prefix
110omitted) in the `VaultMaterial` field of the `Account` record for the account
111in Mongodb.
112
113```
114{
115 "AccessKeyId": "...",
116 "SecretAccessKey": "...",
117 "Roles": {
118 "account-short-name": {
119 "ARN": "arn:aws:iam::...:role/...",
120 "ExternalId": "..."
121 }
122 }
123}
124```
125
126The fields are:
127
128- `AccessKeyId` which is the access key ID of an IAM user that can assume roles
129 in the target account.
130- `SecretAccessKey` is the secret key for the IAM user identified by the access
131 key ID.
132- `Roles` is a mapping of account `ShortName` to an AWS ARN and ExternalId used
133 for assuming roles. The `ARN` is the role to be assumed and the `ExternalId`
134 is the External ID configured in the role trust policy.
135
136Note that this application does **not** use the AWS Vault backend to assume
137roles due to limitations AWS places on roles assumed using assumed role
138credentials and not user credentials.
139
140Finally the broker will need access to a Mongodb credential. Currently this
141requires a static credential but in the future a dynamic credential will be
142acceptable. Create this credential and pass it in the `--mongodb-vault-path`
143argument. It should have the form `database/static-creds/your-cred-name`.
144
145### Mongodb Setup
146
147The application needs a Mongodb database with at least a `users` collection
148created. The rest are optional.
149
150To create the `users` collection insert a record to the collection that
151contains your GitHub username as the `_id` field and has `IsAdmin` set to true.
152For example:
153
154```
155db.users.insert({ "_id": "mcrute", "IsAdmin": true })
156```
157
158This is adequate to allow login via GitHub for the named user. All other fields
159will be populated automatically by the app.
160
161To create allowed AWS accounts for use in the broker add them to the `accounts`
162collection. Those records have the following form:
163
164```
165{
166 "_id": "acocunt-short-name",
167 "AccountNumber": 12345,
168 "AccountType": "aws",
169 "ConsoleSessionDuration": 21600000000000,
170 "DefaultRegion": "us-west-2",
171 "Name": "Some Description",
172 "Users": [
173 "username1",
174 "username2"
175 ],
176 "VaultMaterial": "some/path/as/above"
177}
178```
179
180- `_id` is the short name of the account. This must also map into a Vault
181 material per above.
182- `AccountNumber` is the AWS account number for the account being brokered.
183- `AccountType` is the string `aws` for now
184- `ConsoleSessionDuration` is the number of nanoseconds a console session can
185 exist before timing out. (Nanoseconds are silly, yes; it's a serialized
186 time.Time)
187- `DefaultRegion` is the region considered default, this is just used as an
188 indicator in the JSON API.
189- `Name` a longer form, descriptive name of the account.
190- `Users` a case-sensitive list of GitHub user names that have access to this
191 account
192- `VaultMaterial` the path to the Vault material that contains the account
193 credentials document, as above.
194
195## To Do
196
197- Allow GitLab CI jobs to auth using [job tokens](https://docs.gitlab.com/ee/api/jobs.html#get-job-tokens-job)
198- Implement an Admin UI, all admin ops are directly on the DB at the moment
199- Support dynamic mongodb credentials
200- Support for other clouds
201 - GCP
202 - OCI
203 - Azure
204
205## Contributors
206
207- [Mike Crute](https://mike.crute.us)
diff --git a/README_BROKER.md b/README_BROKER.md
new file mode 100644
index 0000000..03db1af
--- /dev/null
+++ b/README_BROKER.md
@@ -0,0 +1,228 @@
1# AWS Identity Broker
2
3The identity broker is used to obtain short-lived and per-region credentials
4for an account. Opt-in regions require the use of a long-lived credential (e.g.
5IAM user), enabling global STS tokens, or an STS token sourced in that region.
6The identity broker holds long-term credentials and uses them to acquire
7short-term credentials in a given region. The broker also provides a list of
8opt-in regions and should be used to enumerate regions.
9
10For human-interactive users the identity broker performs OAUTH against GitHub
11to chain the user's GitHub identity to the tokens they are given from the
12broker. The broker also provides the user an API key to use when interacting
13with the broker programmatically.
14
15# The API
16
17The identity broker API is a REST-ful service with an entry-point of
18`/api/account`. All further navigation through the API follows links within the
19hypertext.
20
21**Note:** Outside of the account entry-point, URI formats should be considered
22opaque implementation details of the broker API and should never be templated.
23Beyond the account entry-point, nothing in this specification is normative with
24respect to URI paths and locations.
25
26## Media Formats
27
28There are two supported media types in the API `application/vnd.broker.v1+json`
29and `application/vnd.broker.v2+json`. A client that requests the default media
30type or `application/json` will recieve the V1 media type.
31
32To request a specific media type use the `Accept` header:
33
34```
35Accept: application/vnd.broker.v2+json
36```
37
38## Authentication
39
40All requests to the API must be authenticated with a broker-specific key. That
41key is provided to the broker in the `Authorization` header with a sub-type of
42`Bearer`. When the broker determines that the key is either expired or invalid
43it must redirect the user to `/logout` to indicate that the user is logged out
44and must log-in again.
45
46API keys are bearer tokens and thus must only be exchanged over HTTPS.
47
48Example of authorization header:
49
50```
51Authorization: Bearer ...an auth token...
52```
53
54Legacy versions of the API supported an `X-API-Key` header, which is now
55deprecated but remains supported for backwards compatability.
56
57## Status Codes
58
59`200 OK`: indicates that the request to the broker was successful.
60
61`302 Found`: indicates that the broker is providing a redirect. Users should
62check the redirect, if it is to the location `/logout` the user should consider
63themselves logged out and proceed to login. This condition should not be
64followed. Otherwise the user should follow all redirects.
65
66`400 Bad Request`: indicates that some part of the request is invalid as
67submitted. The hypertext MAY provide a description of this error and how to
68remedy it.
69
70`401 Unauthorized`: indicates that the authentication or authorzation for the
71user has failed. This is not retryable, a user should obtain a new
72authorization token before attempting another request.
73
74`429 Rate Limit Exceeded`: indicates that the broker has rate-limited the user.
75A user should discontinue requests to the broker immediately and wait for at
76least 30 seconds before continuing their requests. The rate limit parameters
77are specific to the broker and not controlled by this spec.
78
79`500 Server Error`: indicates a server error condition that is not under the
80user's control.
81
82## Account End-point
83
84### V1 Media Type
85
86The account end-point acts as a index of the rest of the API. It presents a
87list of accounts to which the user has access as well as links to navigate
88further into the API. The format of this document is:
89
90`short_name` (string): a url-safe name for the account, used as the primary
91account identifier within the broker.
92
93`account_number` (integer): the AWS account number
94
95`name` (string): a user-friendly name for the account
96
97`vendor` (string): the name of the cloud vendor (currently only `aws`)
98
99`console_redirect_url` (uri): a URI that, when followed, leads to a resource
100that redirects the user to an authenticated console session.
101
102`get_console_url` (uri): a URI that, when followed, leads to a console URL
103resource.
104
105`credentials_url` (uri): a URI that, when followed, leads to a region list
106resource.
107
108`global_credential_url` (uri): a URI that, when followed, leads to a credential
109resource which provides a credential usable by all non-opt-in regions. The
110contents of this resource are a STS global credential which is not usable in
111opt-in regions.
112
113```
114[
115 {
116 "short_name": "primary-account",
117 "vendor": "aws",
118 "account_number": 123456789012,
119 "name": "Primary AWS Account",
120 "console_redirect_url": "https://broker/api/account/primary-account/console?redirect=1",
121 "get_console_url": "https://broker/api/account/primary-account/console",
122 "credentials_url": "https://broker/api/account/primary-account/credentials",
123 "global_credential_url": "https://broker/api/account/primary-account/credentials/global"
124 }
125]
126```
127
128### V2 Media Type
129
130The fiends in the V2 media type have identical meaning to those in the V1 media
131type but the top level container format is different. Instead of containing a
132list of accounts with a `vendor` field V2 responses are a map of vendors to a
133list of accounts.
134
135```
136{
137 "aws": [
138 {
139 "short_name": "primary-account",
140 "account_number": 123456789012,
141 "name": "Primary AWS Account",
142 "console_redirect_url": "https://broker/api/account/primary-account/console?redirect=1",
143 "get_console_url": "https://broker/api/account/primary-account/console",
144 "credentials_url": "https://broker/api/account/primary-account/credentials",
145 "global_credential_url": "https://broker/api/account/primary-account/credentials/global"
146 }
147 ]
148}
149```
150
151## Console URL Resource
152
153**Note:** This resource is not used by the build scripts.
154
155The console URL resource provides a URL to the AWS console. This resource is
156designed for interactive use.
157
158When provided the query parameter `redirect` with a value of `1` this resource
159will not generate a body and will instead redirect to the URL that would have
160been returned for `console_url`.
161
162`console_url` (uri): a link to the AWS console with authentication credentials
163embedded.
164
165```
166{
167 "console_url": "https://signin.aws.amazon.com/federation?..."
168}
169```
170
171## Credential Resource
172
173The credential resource provides a set of credentials that can be used to
174configure AWS tools to access an account.
175
176`access_key` (string): the AWS access key ID
177
178`secret_key` (string): the AWS secret access key
179
180`session_token` (string): the AWS session token
181
182`expiration` (iso-formatted date): the date and time when the credential will
183expire
184
185```
186{
187 "access_key": "ASIA123ABC456DEF567G",
188 "secret_key": "r7KcIuGdPwoUG2YOLISX2XDrVts55IFGTGaY5Tqa",
189 "session_token": "7C7FyvzyneaS/eRCVDcjHOSTTIHQyvhGqW...",
190 "expiration": "2020-01-01T00:00:00Z"
191}
192```
193
194The API will set a valid `Expires` header that matches the `expiration` field
195of this resource to facilitate use of HTTP caches.
196
197## Region List Resource
198
199The region list resource provides a list of regions associated with the account
200both opted-in and not. For opted-in regions the resource includes a link to a
201credential resource for that region.
202
203`name` (string): AWS name for the region
204
205`enabled` (boolean): indicates if the region is enabled and opted-in for this
206account.
207
208`credentials_url` (uri): a URI that, when followed, leads to a credential
209resource containing a credential for access to that region. The credential
210provided will be usable against the region-local STS endpoint for the specified
211region. This also applies for classic regions, which typically use a global
212endpoint and credential. The returned credential is scoped to the acquiring
213region and may not be usable against the global endpoints or a different
214regional endpoint.
215
216```
217[
218 {
219 "name": "af-south-1",
220 "enabled": false
221 },
222 {
223 "name": "us-west-2",
224 "enabled": true,
225 "credentials_url": "https://broker/api/account/primary-account/credentials/us-west-2"
226 }
227]
228```