-
Notifications
You must be signed in to change notification settings - Fork 4
Add Rake task for inserting pre-generated access token into database #368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
6f68f7b
to
34f3891
Compare
34f3891
to
7293c37
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this a good idea, it makes sense to be able to generate access tokens by authorising with AWS, rather than needing to get an access token from another team member. It also consolidates how we give permissions to individuals which is nice.
lib/tasks/access_tokens.rake
Outdated
|
||
access_token = AccessToken.create!( | ||
description: "inserted with `rails access_tokens:insert`", | ||
owner: ENV["USER"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just looking dev where I presume you've run this and the user is listed as ruby
. The user is intended to be the name of the developer (or app such as forms-runner) who owns the key and I think that's important to maintain.
bash-3.2$ forms data_api -d forms-api -s "select DISTINCT owner from access_tokens where description LIKE 'inserted with%';" | jq '.records[]' -r
{
"owner": "ruby"
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a fair point. I wasn't sure how to get the user information in, I thought that maybe it didn't matter so much, but if you think it does I'll have another think about it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah the reasons it's important are that we use the owner in our logs to log who made the API call (and it'll be important for general access auditing):
payload[:requested_by] = "#{@access_token.owner}-#{@access_token.id}" if @access_token.present? |
And we'll need to use it for management of those keys (for example when someone leaves) and to notify people for key rotation etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed the task slightly to add the owner as a parameter as well as the token digest.
I did spend a while looking into whether it was possible to get the AWS user who started the EC2 task out of the ECS metadata somehow, but I couldn't find anything straightforward.
904e4f0
to
bd2bc48
Compare
This task allows inserting a token into the access tokens table without already having an API token. To use this, generate a UUID or other random string, and then pass the hex encoded sha256 digest of that to the `insert` task: ```bash TOKEN="$(ruby -e 'require "securerandom"; puts "forms_#{SecureRandom.uuid}"')" TOKEN_DIGEST="$(ruby -e "require 'digest'; puts Digest::SHA256.hexdigest('$TOKEN')")" bin/rails "access_tokens:insert[$USER, $TOKEN_DIGEST]" ``` Then don't forget to save the token somewhere safe!
bd2bc48
to
9fc4db7
Compare
|
What is the need to pre-generate an access token? I'm not a huge fan or pre-generating because its then left done to the dev to create or pass in whatever they like and potentially expose our system with a weak token. We already have a method on the AccessToken model which will generate the token for us, https://github.com/alphagov/forms-api/blob/main/app/models/access_token.rb#L6. I understand the issue of devs potentially being locked out of a service because there hasn't been an initial token generated. This is because api endpoints require a valid token but if we only need this to create new tokens then I think we should still be letting the model define that the token for that use is. |
access_token = AccessToken.create!( | ||
description: "inserted with `rails access_tokens:insert`", | ||
owner: args[:owner], | ||
token_digest: args[:token_digest], | ||
) | ||
pp(access_token) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rough example of how we might want to do it without leaving it down to the dev to generate/use a strong token
access_token = AccessToken.create!( | |
description: "inserted with `rails access_tokens:insert`", | |
owner: args[:owner], | |
token_digest: args[:token_digest], | |
) | |
pp(access_token) | |
access_token = AccessToken.new( | |
description: "inserted with `rails access_tokens:insert`", | |
owner: args[:owner]) | |
access_token.generate_token | |
if access_token.save | |
pp(access_token) | |
end |
@aliuk2012 I did think about how to use the existing token generation code, however the problem I was concerned about is that any output from running a task is logged to AWS CloudWatch. So the token that is generated would be readable to anyone with access to AWS. |
@lfdebrux interesting, both approaches could open up our service to attack. Lets have a chat about it as a team and see how much risk we are prepared to take on. |
What problem does this pull request solve?
Currently our method for creating access tokens for developers on the team is to rely on there being a developer around who already has API access [1].
However, at the moment there aren't very many developers already in the access tokens database, which creates a bit of a single point of failure problem.
This PR adds an alternate method; if the developer who wants access already has access to the support role in production (which is more likely than them already having an API key), they can use this task to insert the hash of a key they pre-generate into the forms-api database.
To use this to add a token to the development app, for example, you can run in your shell:
Things to consider when reviewing