Skip to content
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

adds authentication helper for aws eks #404

Merged
merged 4 commits into from
Apr 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,40 @@ Kubeclient::Client.new(
```


#### Amazon EKS Credentials

On Amazon EKS by default the authentication method is IAM. When running kubectl a temporary token is generated by shelling out to
the aws-iam-authenticator binary which is sent to authenticate the user.
See [aws-iam-authenticator](https://github.com/kubernetes-sigs/aws-iam-authenticator).
To replicate that functionality, the `Kubeclient::AmazonEksCredentials` class can accept a set of IAM credentials and
contains a helper method to generate the authentication token for you.

This requires a set of gems which are _not_ included in
`kubeclient` dependencies (`aws-sigv4`) so you should add them to your bundle.
You will also require either the `aws-sdk` v2 or `aws-sdk-core` v3 gems to generate the required `Aws:Credentials` object to pass to this method.

To obtain a token:

```ruby
require 'aws-sdk-core'
# Use keys
credentials = Aws::Credentials.new(access_key, secret_key)
# Or a profile
credentials = Aws::SharedCredentials.new(profile_name: 'default').credentials

auth_options = {
bearer_token: Kubeclient::AmazonEksCredentials.token(credentials, eks_cluster_name)
}
client = Kubeclient::Client.new(
eks_cluster_https_endpoint, 'v1', auth_options: auth_options
)
```

Note that this returns a token good for one minute. If your code requires authorization for longer than that, you should plan to
acquire a new one, see [How to manually renew](#how-to-manually-renew-expired-credentials) section.



#### Google's Application Default Credentials

On Google Compute Engine, Google App Engine, or Google Cloud Functions, as well as `gcloud`-configured systems
Expand Down
46 changes: 46 additions & 0 deletions lib/kubeclient/aws_eks_credentials.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

module Kubeclient
# Get a bearer token to authenticate against aws eks.
class AmazonEksCredentials
class AmazonEksDependencyError < LoadError # rubocop:disable Lint/InheritException
end

class << self
def token(credentials, eks_cluster)
begin
require 'aws-sigv4'
require 'base64'
require 'cgi'
rescue LoadError => e
raise AmazonEksDependencyError,
'Error requiring aws gems. Kubeclient itself does not include the following ' \
'gems: [aws-sigv4]. To support auth-provider eks, you must ' \
"include it in your calling application. Failed with: #{e.message}"
end
# https://github.com/aws/aws-sdk-ruby/pull/1848
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean one needs a sufficiently new aws-sdk-core? Is ainimal version worth documenting?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that you mention this, the only requirement is aws-sigv4. aws-sdk is not required. consumers can use any version of aws-sdk v2 or aws-sdk-core v3 as long as it contains a credentials object it can pass through to the aws-sig4 pre-signer class. i'll update the documentation

# Get a signer
# Note - sts only has ONE endpoint (not regional) so 'us-east-1' hardcoding should be OK
signer = Aws::Sigv4::Signer.new(
service: 'sts',
region: 'us-east-1',
credentials: credentials
)

# https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/Sigv4/Signer.html#presign_url-instance_method
presigned_url_string = signer.presign_url(
http_method: 'GET',
url: 'https://sts.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15',
body: '',
credentials: credentials,
expires_in: 60,
headers: {
'X-K8s-Aws-Id' => eks_cluster
}
)
kube_token = 'k8s-aws-v1.' + Base64.urlsafe_encode64(presigned_url_string.to_s).chomp('==')
kube_token
end
end
end
end