AWS Dev Day Kyiv 2019
Track: Backend & Architecture
Session: ""How to implement authorization in your backend with AWS IAM""
Speaker: Stas Ivaschenko, AWS solutions architect at Provectus
Level: 400
Video: https://www.youtube.com/watch?v=4Jje_WJ4V7Q
AWS Dev Day is a free, full-day technical event where new developers will learn about some of the hottest topics in cloud computing, and experienced developers can dive deep on newer AWS services.
Provectus has organized AWS Dev Day Kyiv in close collaboration with Amazon Web Services: 800+ participants, 18 sessions, 3 tracks, a really AWSome Day!
Now, together with Zeo Alliance, we're building and nurturing AWS User Group Ukraine — join us on Facebook to stay updated about cloud technologies and AWS services: https://www.facebook.com/groups/AWSUserGroupUkraine
"
7. A new service starts up, where to get credentials?
1. Bake into ami or docker image or use a hardcode?
2. Provision with Chef/Puppet/Ansible/script over ssh?
3. Get from s3 bucket?
4. Parameter Store?
5. Vault?
6. Surprisingly many more ways, actually!
7. The questions is absolutely the same for any code you run: EC2,
Lambda, ECS
8. S3, Parameter Store, Vault
But how do you login there in the first place?
Ah, IAM instance profiles!
9. Inspired by how Vault authenticates users
https://www.hashicorp.com/resources/deep-dive-vault-aws-auth-backend
10. But why use Vault or Parameter Store, go
directly with IAM and STS
11. WhoAmI Request on STS
● This is a cornerstone of the entire idea
● Such request actually exists: sts:GetCallerIdentity
● Signed requests live for 15 min
● Discussed https://github.com/hashicorp/vault/issues/948
● Implemented in Vault https://github.com/hashicorp/vault/pull/1962
13. Example implementation
● API server - simple RoR api
● Client - python script
● https://github.com/sam50/ror_aws_iam_auth
● 2 instances, client has an EC2 instance profile with role
14. What Client is doing
1. Generates signed STS GetCallerIdentity request
2. Sends it to server http://<ip name>:3000/authenticate
3. Gets JWT Auth token
4. Uses that token to do things in API
17. What server is doing
1. A simple API ($rails new api1 --api)
2. Uses a JWT (gem 'jwt')
3. Uses simple command(gem 'simple_command')
4. Receives login(signed sts:GetCallerIdentity) at /authenticate
5. Sends signed request to STS*
6. (if-ok) Looks for the user by the Role ARN
7. (if-ok) issues a JWT token to the client
18. def authenticate_iam
uri = URI.parse("https://sts.amazonaws.com/")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = "Net::HTTP::#{@iam_http_request_method.capitalize}".constantize.new(uri.request_uri)
request.set_form_data(Rack::Utils.parse_nested_query(@iam_request_body))
headers = JSON.parse(@iam_request_headers)
headers.each do |header, value|
request[header]=value
end
if headers['X-APP-ID'] != 'APP1-live'
return false
end
response = http.request(request)
. . . . . . . . . . . .
19. . . . . . . . . . .
if response.code != '200' || response.body.empty?
return false
else
xml = Nokogiri::XML(response.body)
stsarn = xml.remove_namespaces!.xpath("GetCallerIdentityResponse/GetCallerIdentityResult/Arn").text
if stsarn.empty?
return false
else
return stsarn.gsub("arn:aws:sts","arn:aws:iam").gsub("assumed-role","role").gsub(//[A-z0-9-]*$/,"")
end
end
return false
end
20. git clone https://github.com/sam50/ror_aws_iam_auth
cd ror_aws_iam_auth
bundle install
rake db:migrate
rails c
>User.create!(name:"client1", iamarn: "<Your role ARN here
arn:aws:iam::xxxx:role/role-name")
rails s -b 0.0.0.0 3000