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

IAM Role for Service Account(IRSA) support for models stored in S3 #2113

Closed
surajkota opened this issue Mar 24, 2022 · 7 comments · Fixed by #2373
Closed

IAM Role for Service Account(IRSA) support for models stored in S3 #2113

surajkota opened this issue Mar 24, 2022 · 7 comments · Fixed by #2373

Comments

@surajkota
Copy link

surajkota commented Mar 24, 2022

/kind feature

Currently, AWS users need to create a secret with long term/static IAM credentials for downloading models stored in S3. Security best practice is to use IAM role for service account(IRSA) which enables automatic credential rotation and fine grained access control

Describe the solution you'd like
Support annotating IAM role in a service account which can be used by storage initializer to download models from S3.

Anything else you would like to add:
It will be super helpful to know the customers/users interested in this feature for appropriate prioritization. Please upvote or comment on the issue if you are interested in this feature

related: awslabs/kubeflow-manifests#44

@surajkota surajkota changed the title IAM Role for Service Account(IRSA) support for models in S3 IAM Role for Service Account(IRSA) support for models stored in S3 Mar 24, 2022
@yuzisun
Copy link
Member

yuzisun commented May 5, 2022

for reference https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html

@matty-rose
Copy link
Contributor

matty-rose commented May 8, 2022

Hi, this functionality currently exists but just isn't documented in the KServe guide. However there are some quirks required in order to get kserve to parse the annotations from the secret - an example and reasoning can be found in my comment here. I'm happy to contribute updates to the documentation, but wanted to check with @yuzisun whether it would be worth adding functionality to this code that makes this easier for end users.

A proposed solution could be to explicitly check for the eks role annotation on the service account and then either

  1. also attempt to parse the relevant s3 annotations from the ServiceAccount instead of requiring an attached secret, so that users of IRSA functionality would not need to create the aws-secret resource
  2. OR still require an attached secret for the s3 annotations, but add the required env variables to the storage-init container even if the AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY data fields are not present

If either of you @yuzisun @surajkota have any thoughts on this approach I'd love to hear them

@yuzisun
Copy link
Member

yuzisun commented May 8, 2022

@matty-rose option 1 sounds reasonable to me, also I think those s3 annotations(e.g s3-region, s3-endpoint/s3-usehttps) are more sensible to be added to the configmap so you do not need to configure for each service account.

In summary for s3 we first look for the IM Role annotation on service account and then check if it is attached with a secret of AWS credential data, the controller then inject the necessary environment variables based on global configurations or annotation overrides if secret presents.

dimara added a commit to arrikto/kserve that referenced this issue Aug 2, 2022
Until now KServe was using the global HTTP endpoint for S3 by default
unless the user explicitly provides it with the corresponding
annotation. If one wants to use IAM roles for service accounts instead
of Secrets with HMAC credentials, storage-initializer will fail in case:

* the bucket is configured with SSE
* if the bucket allow
* of an airgapped environment

Specifically, if the bucket is configured with SSE it fails with:

  botocore.exceptions.ClientError: An error occurred (InvalidArgument) when calling the GetObject operation: Requests specifying Server Side Encryption with AWS KMS managed keys must be made over a secure connection.

If the bucket policy allows HTTPS requests only it fails with:

  botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

In case of an airgapped environment, S3 is only available via the
regional VPC endpoint so requests to the global endpoint will hang.

Handle the above cases by letting boto3 decide the S3 endpoint based
on the environment. In case of IRSA, AWS will set AWS_REGION and
AWS_DEFAULT_REGION and as such boto3 will use the regional endpoint.
boto3 will use HTTPS by default which is inline with the default value
of s3-usehttps annotation. Finally, if the bucket is in different region
boto3 will be automatically redirected there.

Also handle the case where endpoint_url is unset or empty, where boto3
fails with:

  ValueError: Invalid endpoint:

With this commit, one can use service accounts with the `role-arn` and
`sts-regional-endpoints` annotations directly without the need of an
attached secret.

Refs kserve#2003
Refs kserve#2113

Signed-off-by: Dimitris Aragiorgis <dimara@arrikto.com>
@yuzisun yuzisun mentioned this issue Aug 7, 2022
9 tasks
@dimara
Copy link
Contributor

dimara commented Aug 8, 2022

We bumped into this issue as well with KServe 0.6 when trying to access a private bucket with SSE using IRSA only (without any secrets). storage-initialiazer failed with (the rather confusing):

botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

Once we removed the (recommended) bucket policy for allowing only HTTPS requests, storage-initializer failed with:

botocore.exceptions.ClientError: An error occurred (InvalidArgument) when calling the GetObject operation: Requests specifying Server Side Encryption with AWS KMS managed keys must be made over a secure connection.

This is because it ended up using the global HTTP endpoint for S3, that is http://s3.amazonaws.com:

endpoint_url=os.getenv("AWS_ENDPOINT_URL", "http://s3.amazonaws.com"),

Besides the HTTPS issue described above, storage-initializer will not work in an air-gapped env where we need to access the regional VPC endpoint.

So how about removing the hardcoded default value for the endpoint_url and let boto3 decide S3 endpoint based on its env?

In case of IRSA the pod will get AWS_REGION and AWS_DEFAULT_REGION so boto3 will use the regional endpoint. If the bucket is located in a different region boto3 will handle the redirect automatically. Finally, boto3 will use HTTPS by default. So things will work out of the box.

@surajkota
Copy link
Author

surajkota commented Aug 8, 2022

@dimara thanks for reporting the issue. Are you able to use #2003 (comment) as a workaround to override just the s3 endpoint in the serving.kserve.io/s3-endpoint annotation? credential can still be pulled using IRSA

Letting AWS SDK decide the default S3 endpoint based on the env seems reasonable to me with the option to override using configmap/secret

@dimara
Copy link
Contributor

dimara commented Aug 9, 2022

@surajkota

as a workaround to override just the s3 endpoint in the serving.kserve.io/s3-endpoint annotation

Since we were using IRSA we wanted to avoid creating dummy secrets and attach them to service accounts.

Letting AWS SDK decide the default S3 endpoint based on the env seems reasonable to me with the option to override using configmap/secret

I agree. The said fix is orthogonal with the PR that @matty-rose opened recently (see #2373). Will try to send a PR for that.

dimara added a commit to arrikto/kserve that referenced this issue Aug 9, 2022
Until now KServe was using the global HTTP endpoint for S3 by default
unless the user explicitly provides it with the corresponding
annotation. If one wants to use IAM roles for service accounts instead
of Secrets with HMAC credentials, storage-initializer will fail in case:

* the bucket is configured with SSE
* if the bucket allow
* of an airgapped environment

Specifically, if the bucket is configured with SSE it fails with:

  botocore.exceptions.ClientError: An error occurred (InvalidArgument) when calling the GetObject operation: Requests specifying Server Side Encryption with AWS KMS managed keys must be made over a secure connection.

If the bucket policy allows HTTPS requests only it fails with:

  botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

In case of an airgapped environment, S3 is only available via the
regional VPC endpoint so requests to the global endpoint will hang.

Handle the above cases by letting boto3 decide the S3 endpoint based
on the environment.

In case of IRSA, AWS will set AWS_REGION and AWS_DEFAULT_REGION and as
such boto3 will use the regional endpoint. boto3 will use HTTPS by
default which is inline with the default value of s3-usehttps
annotation. Finally, if the bucket is in different region boto3 will be
automatically redirected there.

This change should not break existing deployments that don't use IRSA
but don't set s3-endpoint either; boto3 will default using the global
HTTPS endpoint, https://s3.amazonaws.com.

Handle also the case where endpoint_url is unset or empty, where boto3
fails with:

  ValueError: Invalid endpoint:

With this commit, one can use service accounts with the
`eks.amazonaws.com/role-arn` and `eks.amazonaws.com/sts-regional-endpoints`
annotations directly without the need of an attached secret.

Refs kserve#2003
Refs kserve#2113

Signed-off-by: Dimitris Aragiorgis <dimara@arrikto.com>
dimara added a commit to arrikto/kserve that referenced this issue Aug 9, 2022
Until now KServe was using the global HTTP endpoint for S3 by default
unless the user explicitly provides it with the corresponding
annotation. If one wants to use IAM roles for service accounts instead
of Secrets with HMAC credentials, storage-initializer will fail in case:

* the bucket is configured with SSE
* if the bucket allows HTTPS requests only
* of an airgapped environment

Specifically, if the bucket is configured with SSE it fails with:

  botocore.exceptions.ClientError: An error occurred (InvalidArgument) when calling the GetObject operation: Requests specifying Server Side Encryption with AWS KMS managed keys must be made over a secure connection.

If the bucket policy allows HTTPS requests only it fails with:

  botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

In case of an airgapped environment, S3 is only available via the
regional VPC endpoint so requests to the global endpoint will hang.

Handle the above cases by letting boto3 decide the S3 endpoint based
on the environment.

In case of IRSA, AWS will set AWS_REGION and AWS_DEFAULT_REGION and as
such boto3 will use the regional endpoint. boto3 will use HTTPS by
default which is inline with the default value of s3-usehttps
annotation. Finally, if the bucket is in different region boto3 will be
automatically redirected there.

This change should not break existing deployments that don't use IRSA
but don't set s3-endpoint either; boto3 will default using the global
HTTPS endpoint, https://s3.amazonaws.com.

Handle also the case where endpoint_url is unset or empty, where boto3
fails with:

  ValueError: Invalid endpoint:

With this commit, one can use service accounts with the
`eks.amazonaws.com/role-arn` and `eks.amazonaws.com/sts-regional-endpoints`
annotations directly without the need of an attached secret.

Refs kserve#2003
Refs kserve#2113

Signed-off-by: Dimitris Aragiorgis <dimara@arrikto.com>
dimara added a commit to arrikto/kserve that referenced this issue Sep 5, 2022
Until now KServe was using the global HTTP endpoint for S3 by default
unless the user explicitly provides it with the corresponding
annotation. If one wants to use IAM roles for service accounts instead
of Secrets with HMAC credentials, storage-initializer will fail in case:

* the bucket is configured with SSE
* if the bucket allows HTTPS requests only
* of an airgapped environment

Specifically, if the bucket is configured with SSE it fails with:

  botocore.exceptions.ClientError: An error occurred (InvalidArgument) when calling the GetObject operation: Requests specifying Server Side Encryption with AWS KMS managed keys must be made over a secure connection.

If the bucket policy allows HTTPS requests only it fails with:

  botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

In case of an airgapped environment, S3 is only available via the
regional VPC endpoint so requests to the global endpoint will hang.

Handle the above cases by letting boto3 decide the S3 endpoint based
on the environment.

In case of IRSA, AWS will set AWS_REGION and AWS_DEFAULT_REGION and as
such boto3 will use the regional endpoint. boto3 will use HTTPS by
default which is inline with the default value of s3-usehttps
annotation. Finally, if the bucket is in different region boto3 will be
automatically redirected there.

This change should not break existing deployments that don't use IRSA
but don't set s3-endpoint either; boto3 will default using the global
HTTPS endpoint, https://s3.amazonaws.com.

Handle also the case where endpoint_url is unset or empty, where boto3
fails with:

  ValueError: Invalid endpoint:

With this commit, one can use service accounts with the
`eks.amazonaws.com/role-arn` and `eks.amazonaws.com/sts-regional-endpoints`
annotations directly without the need of an attached secret.

Refs kserve#2003
Refs kserve#2113

Signed-off-by: Dimitris Aragiorgis <dimara@arrikto.com>
kserve-oss-bot pushed a commit that referenced this issue Sep 7, 2022
Until now KServe was using the global HTTP endpoint for S3 by default
unless the user explicitly provides it with the corresponding
annotation. If one wants to use IAM roles for service accounts instead
of Secrets with HMAC credentials, storage-initializer will fail in case:

* the bucket is configured with SSE
* if the bucket allows HTTPS requests only
* of an airgapped environment

Specifically, if the bucket is configured with SSE it fails with:

  botocore.exceptions.ClientError: An error occurred (InvalidArgument) when calling the GetObject operation: Requests specifying Server Side Encryption with AWS KMS managed keys must be made over a secure connection.

If the bucket policy allows HTTPS requests only it fails with:

  botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

In case of an airgapped environment, S3 is only available via the
regional VPC endpoint so requests to the global endpoint will hang.

Handle the above cases by letting boto3 decide the S3 endpoint based
on the environment.

In case of IRSA, AWS will set AWS_REGION and AWS_DEFAULT_REGION and as
such boto3 will use the regional endpoint. boto3 will use HTTPS by
default which is inline with the default value of s3-usehttps
annotation. Finally, if the bucket is in different region boto3 will be
automatically redirected there.

This change should not break existing deployments that don't use IRSA
but don't set s3-endpoint either; boto3 will default using the global
HTTPS endpoint, https://s3.amazonaws.com.

Handle also the case where endpoint_url is unset or empty, where boto3
fails with:

  ValueError: Invalid endpoint:

With this commit, one can use service accounts with the
`eks.amazonaws.com/role-arn` and `eks.amazonaws.com/sts-regional-endpoints`
annotations directly without the need of an attached secret.

Refs #2003
Refs #2113

Signed-off-by: Dimitris Aragiorgis <dimara@arrikto.com>

Signed-off-by: Dimitris Aragiorgis <dimara@arrikto.com>
alexagriffith pushed a commit to alexagriffith/kserve that referenced this issue Sep 19, 2022
Until now KServe was using the global HTTP endpoint for S3 by default
unless the user explicitly provides it with the corresponding
annotation. If one wants to use IAM roles for service accounts instead
of Secrets with HMAC credentials, storage-initializer will fail in case:

* the bucket is configured with SSE
* if the bucket allows HTTPS requests only
* of an airgapped environment

Specifically, if the bucket is configured with SSE it fails with:

  botocore.exceptions.ClientError: An error occurred (InvalidArgument) when calling the GetObject operation: Requests specifying Server Side Encryption with AWS KMS managed keys must be made over a secure connection.

If the bucket policy allows HTTPS requests only it fails with:

  botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied

In case of an airgapped environment, S3 is only available via the
regional VPC endpoint so requests to the global endpoint will hang.

Handle the above cases by letting boto3 decide the S3 endpoint based
on the environment.

In case of IRSA, AWS will set AWS_REGION and AWS_DEFAULT_REGION and as
such boto3 will use the regional endpoint. boto3 will use HTTPS by
default which is inline with the default value of s3-usehttps
annotation. Finally, if the bucket is in different region boto3 will be
automatically redirected there.

This change should not break existing deployments that don't use IRSA
but don't set s3-endpoint either; boto3 will default using the global
HTTPS endpoint, https://s3.amazonaws.com.

Handle also the case where endpoint_url is unset or empty, where boto3
fails with:

  ValueError: Invalid endpoint:

With this commit, one can use service accounts with the
`eks.amazonaws.com/role-arn` and `eks.amazonaws.com/sts-regional-endpoints`
annotations directly without the need of an attached secret.

Refs kserve#2003
Refs kserve#2113

Signed-off-by: Dimitris Aragiorgis <dimara@arrikto.com>

Signed-off-by: Dimitris Aragiorgis <dimara@arrikto.com>
Signed-off-by: alexagriffith <agriffith96@gmail.com>
@surajkota
Copy link
Author

Feature was reviewed and merged in: #2373

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Status: Done
Development

Successfully merging a pull request may close this issue.

5 participants