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

Question: Does Camel looks for IAM roles from Env variables #282

Closed
saranyaeu2987 opened this issue Jun 17, 2020 · 30 comments
Closed

Question: Does Camel looks for IAM roles from Env variables #282

saranyaeu2987 opened this issue Jun 17, 2020 · 30 comments

Comments

@saranyaeu2987
Copy link

saranyaeu2987 commented Jun 17, 2020

This is a followup of #267.

@valdar @oscerd

We configured EKS k8s pod with serviceaccount with IAM role for S3 authentication (https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html) which will create 2 ENV variables inside pod

AWS_ROLE_ARN=arn:aws:iam::AWS_ACCOUNT_ID:role/IAM_ROLE_NAME
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token

When I try to run Camel Sink connector, I get Access Denied issue for S3

image

QUESTION: Does camel.component.aws-s3.useIAMCredentials: true looks for IAM role arn from those env variables in Pod?

@oscerd
Copy link
Contributor

oscerd commented Jun 18, 2020

The useiamcredentials option just looks for using the ec2 IAM credentials and use them.

@saranyaeu2987
Copy link
Author

@oscerd
Where do you look for IAM credentials in a EC2 instance? Are Env variables in credentials provider chain?

@oscerd
Copy link
Contributor

oscerd commented Jun 18, 2020

That's related to the underline instance. It's the IAM role with you created the ec2 instance. No the env variables are not taken into account. With the Aws2 components you can inject your own client instance and it will look to env variables if you don't provide a credential provider

@valdar
Copy link
Member

valdar commented Jun 18, 2020

@saranyaeu2987 there are more info here: aws/aws-sdk-java-v2#1470 but you need sdk version >= 2.10.11, so you need to use camel-aws2-*-kafka-connector versions...

@saranyaeu2987
Copy link
Author

saranyaeu2987 commented Jun 18, 2020

@valdar
Thanks for prompt response. I am currently using camel-aws-s3-kafka-connector-0.2.0.jar
https://repo1.maven.org/maven2/org/apache/camel/kafkaconnector/camel-aws2-s3-kafka-connector/0.2.0/ has only 0.2.0 version.
Where can I find camel-aws2-2.10.11-kafka-connector jar/binaries ?

@geota
Copy link

geota commented Jun 18, 2020

@valdar is correct. This should be as easy as Camel using the correct SDK version that has support for the AWS_WEB_IDENTITY_TOKEN_FILE env var. This should just be crawled in the DefaultCredentialProvider chain that the SDK executes to find credentials.

@oscerd
Copy link
Contributor

oscerd commented Jun 18, 2020

For the env variables for secret and access key, the standard client instance should check them out of the box

@geota
Copy link

geota commented Jun 18, 2020

@oscerd we are trying to get EKS role based credentials working. To be clear, this is the official AWS supported way of providing role base credentials to Kubernetes pods. Our company does not allow access key/secret keys to avoid credential management overhead (securing, cycling, invalidating etc) and enforces all AWS access to use roles.

AWS added a new way to source credentials in their SDKs to support K8s pod scoped IAM roles. @valdar linked the correct issue discussing this need in the java-sdk. It was fxed via aws/aws-sdk-java-v2#1501 and released as part of AWS Java SDK 2.10.11

See:
https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/
https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html

@oscerd
Copy link
Contributor

oscerd commented Jun 18, 2020

Anyway, it should possible when instancing your own client. Using the correct version

@saranyaeu2987
Copy link
Author

saranyaeu2987 commented Jun 18, 2020

@oscerd @valdar
Camel repo has only camel-aws2-0.2.0-kafka-connector.jar , Does it support aws-sdk >= 2.10.11 ?

@saranyaeu2987
Copy link
Author

@valdar
I am not very successful in resolving access issue.

I tried both camel-aws2-s3-kafka-connector-0.2.0.jar and camel-aws-s3-kafka-connector-0.2.0.jar both gave me access issue.

Below are list of plugins used.
Screen Shot 2020-06-18 at 2 07 33 PM

I am unsure if camel-aws2-s3-kafka-connector-0.2.0.jar and camel-aws-s3-kafka-connector-0.2.0.jar uses aws-sdk >= 2.10.11

@oscerd
Copy link
Contributor

oscerd commented Jun 18, 2020

Only the Aws2 connectors are based on sdk v2. The version used on 0.2.0 kafka connector of sdk v2 is 2.11.5

@saranyaeu2987
Copy link
Author

saranyaeu2987 commented Jun 18, 2020

@oscerd @valdar
I tried 2 images having camel aws2 jars and both gave the same following error
Image 1 with following plugins obtained from https://repo1.maven.org/maven2/org/apache/camel/kafkaconnector/camel-aws-s3-kafka-connector/0.2.0/ and replaced 2 aws jars ( camel-aws-s3-3.2.0.jar, camel-aws-s3-kafka-connector-0.2.0.jar) with aws2 jar (camel-aws2-s3-3.3.0.jar, camel-aws2-s3-kafka-connector-0.2.0.jar)

Screen Shot 2020-06-18 at 3 00 38 PM

Image 2 with following plugins obtained from https://repo1.maven.org/maven2/org/apache/camel/kafkaconnector/camel-aws2-s3-kafka-connector/0.2.0/
Screen Shot 2020-06-18 at 3 13 32 PM

Caused by: java.lang.IllegalArgumentException: Error configuring property: camel.component.aws-s3.configuration.autocloseBody because cannot find component with name aws-s3. Make sure you have the component on the classpath
	at org.apache.camel.main.BaseMainSupport.lambda$autoConfigurationFromProperties$15(BaseMainSupport.java:989)
	at org.apache.camel.main.BaseMainSupport.computeProperties(BaseMainSupport.java:1249)
	at org.apache.camel.main.BaseMainSupport.autoConfigurationFromProperties(BaseMainSupport.java:985)
	at org.apache.camel.main.BaseMainSupport.autoconfigure(BaseMainSupport.java:562)
	at org.apache.camel.main.BaseMainSupport.postProcessCamelContext(BaseMainSupport.java:607)
	at org.apache.camel.main.BaseMainSupport.initCamelContext(BaseMainSupport.java:440)
	at org.apache.camel.main.Main.doInit(Main.java:109)
	at org.apache.camel.support.service.BaseService.init(BaseService.java:83)
	at org.apache.camel.support.service.BaseService.start(BaseService.java:111)
	at org.apache.camel.main.MainSupport.run(MainSupport.java:83)
	at org.apache.camel.kafkaconnector.utils.CamelMainSupport$CamelContextStarter.run(CamelMainSupport.java:220)
	... 3 more
2020-06-18 18:43:23,384 ERROR WorkerSinkTask{id=heb-s3-s123456-connector-0} Task is being killed and will not recover until manually restarted (org.apache.kafka.connect.runtime.WorkerTask) [task-thread-heb-s3-s123456-connector-0]
2020-06-18 18:43:23,384 INFO Stopping CamelSinkTask connector task (org.apache.camel.kafkaconnector.CamelSinkTask) [task-thread-heb-s3-s123456-connector-0]
2020-06-18 18:43:23,384 INFO Stopping CamelContext (org.apache.camel.kafkaconnector.utils.CamelMainSupport) [task-thread-heb-s3-s123456-connector-0]
2020-06-18 18:43:23,384 INFO CamelContext stopped (org.apache.camel.kafkaconnector.utils.CamelMainSupport) [task-thread-heb-s3-s123456-connector-0]
2020-06-18 18:43:23,384 INFO CamelSinkTask connector task stopped (org.apache.camel.kafkaconnector.CamelSinkTask) [task-thread-heb-s3-s123456-connector-0]

I feel camel-aws2-s3-.jar is giving me this error, because if I have camel-aws-s3-.jar doesnt through above error.

Please guide me which jar Am I missing !!

@oscerd
Copy link
Contributor

oscerd commented Jun 18, 2020

The scheme for aws2-s3 is aws2-s3, so it is camel.component.aws2-s3...

@oscerd
Copy link
Contributor

oscerd commented Jun 18, 2020

You have all the information and download links here
https://camel.apache.org/camel-kafka-connector/latest/connectors.html

@saranyaeu2987
Copy link
Author

saranyaeu2987 commented Jun 18, 2020

@oscerd @valdar

You have all the information and download links here
https://camel.apache.org/camel-kafka-connector/latest/connectors.html

Yes, thats where I am getting all jars from

I still getting access denied issues after using aws2-s3. TBH I am clueless

@oscerd
Copy link
Contributor

oscerd commented Jun 18, 2020

Please report your configuration, what you're setting, how is your client instance?

@oscerd
Copy link
Contributor

oscerd commented Jun 18, 2020

And you don't have to replace any jar in your plugin. Simply download the Aws2 s3 zipped connector and unzip it in your plugin path. Don't mix up dependencies.

@saranyaeu2987
Copy link
Author

And you don't have to replace any jar in your plugin. Simply download the Aws2 s3 zipped connector and unzip it in your plugin path. Don't mix up dependencies.

Thats what I did in last run.

Configurations

  1. K8S on EKS cluster. Pod instance config
    Screen Shot 2020-06-18 at 5 24 30 PM

  2. Yaml file

apiVersion: kafka.strimzi.io/v1alpha1
kind: KafkaConnector
metadata:
  name: s3-abcd-connector
  labels:
    strimzi.io/cluster: emd-kafka-cluster
spec:
  class: org.apache.camel.kafkaconnector.CamelSinkConnector
  tasksMax: 1
  config:
    key.converter: org.apache.kafka.connect.storage.StringConverter
    value.converter: org.apache.kafka.connect.storage.StringConverter
    topics: DB.EMD.COMPANY.0
    camel.sink.url: aws2-s3://<bucketname>?keyName=s3-connect/${date:now:yyyyMMdd}/${date:now:yyyyMMdd-HHmmssSSS}
    camel.sink.maxPollDuration: 1000
    camel.sink.maxBatchPollSize: 10
    camel.component.aws2-s3.configuration.autocloseBody: false
    camel.component.aws2-s3.useIAMCredentials: true

  1. Env variables property set in pod
[kafka@emd-kafka-cluster-connect-5fb8cdf44d-jf6s2 kafka]$ printenv |grep aws
AWS_ROLE_ARN=arn:aws:iam::<arn>:role/emd-kafka-cluster-connect
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token
  1. (K8s Pod Configuration)
    Service Account which has access to bucket
ML-C02Z605SLVDQ:selumalai-k8s-s3-connect e192270$ aws-vault exec heb-dsol-foundational-projects-bld-staff -- kubectl  get serviceaccounts emd-kafka-cluster-connect -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<xxxxxxxxx>:role/emd-kafka-cluster-connect
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{"eks.amazonaws.com/role-arn":"arn:aws:iam::<xxxxxxxx>:role/emd-kafka-cluster-connect"},"creationTimestamp":"2020-06-17T21:48:25Z","labels":{"app.kubernetes.io/instance":"emd-kafka-cluster","app.kubernetes.io/managed-by":"strimzi-cluster-operator","app.kubernetes.io/name":"kafka-connect","app.kubernetes.io/part-of":"strimzi-emd-kafka-cluster","strimzi.io/cluster":"emd-kafka-cluster","strimzi.io/kind":"KafkaConnect","strimzi.io/name":"strimzi"},"name":"emd-kafka-cluster-connect","namespace":"default","resourceVersion":"855936","selfLink":"/api/v1/namespaces/default/serviceaccounts/emd-kafka-cluster-connect","uid":"24bdb5d3-1d43-4bf6-b883-b275b0f5397e"},"secrets":[{"name":"emd-kafka-cluster-connect-token-glprh"}]}
  creationTimestamp: "2020-06-17T22:19:54Z"
  labels:
    app.kubernetes.io/instance: emd-kafka-cluster
    app.kubernetes.io/managed-by: strimzi-cluster-operator
    app.kubernetes.io/name: kafka-connect
    app.kubernetes.io/part-of: strimzi-emd-kafka-cluster
    strimzi.io/cluster: emd-kafka-cluster
    strimzi.io/kind: KafkaConnect
    strimzi.io/name: strimzi
  name: emd-kafka-cluster-connect
  namespace: default
  resourceVersion: "859885"
  selfLink: /api/v1/namespaces/default/serviceaccounts/emd-kafka-cluster-connect
  uid: 528c4309-4581-4fcb-a66f-f64741299709
secrets:
- name: emd-kafka-cluster-connect-token-glprh
- name: emd-kafka-cluster-connect-token-bvq9n

@oscerd
Copy link
Contributor

oscerd commented Jun 19, 2020

If you use the useIAMCredential parameter, the client won't check for env variables. The documentation is clear on this: "Set whether the S3 client should expect to load credentials on an EC2 instance or to expect static credentials to be passed in."

You need to provide your own client instance, like explained here: https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/credentials.html

Region region = Region.US_WEST_2; S3Client s3 = S3Client.builder() .region(region) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build();

And then reference this as camel.sink.endpoint.amazonS3Client

@saranyaeu2987
Copy link
Author

saranyaeu2987 commented Jun 19, 2020

@oscerd

  1. If I dont provide
    camel.component.aws2-s3.useIAMCredentials: true
    Camel expects static for value for camel.component.aws-s3.accessKey AND camel.component.aws-s3.secretKey right ? What value should I need to provide them?

  2. Also, camel.sink.endpoint.amazonS3Client is a reference to a com.amazonaws.services.s3.AmazonS3 in the registry.
    I didnt understand why we need to set this config ? and what value goes into it ?

@oscerd
Copy link
Contributor

oscerd commented Jun 19, 2020

  1. useIamCredentials works by using the underline EC2 credentials used to create the ec2 instance, if you don't use that you need to provide static credentials.

  2. You need to create an instance of the client and pass it to the configuration like we did for example here: https://github.com/apache/camel-kafka-connector/blob/master/examples/CamelAmqpSourceConnector.properties#L27 with the #class notation.

I'll try to create an example or something when I'll have time.

@saranyaeu2987
Copy link
Author

saranyaeu2987 commented Jun 19, 2020

@oscerd

Do you mean something like below ? Please let me know if I am wrong

public class CustomS3Client implements S3Client{
    private static Logger log = LoggerFactory.getLogger(customS3Client.class);
    Region region = Region.US_EAST_1;
    S3Client s3;
    public CustomS3Client() {
        this.s3 = S3Client.builder() .region(region) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()).build();;
    }

    @Override
    public String serviceName() {
        return "S3 Client with Env variable Auth";
    }

    @Override
    public void close() {

    }
    public static void main(String args[]){
        CustomS3Client customs3Client = new CustomS3Client();
        log.info("customs3Client created!");
    }
}

and in kafkaconnector.yaml

apiVersion: kafka.strimzi.io/v1alpha1
kind: KafkaConnector
metadata:
  name: s3-abcd-connector
  labels:
    strimzi.io/cluster: emd-kafka-cluster
spec:
  class: org.apache.camel.kafkaconnector.CamelSinkConnector
  tasksMax: 1
  config:
    key.converter: org.apache.kafka.connect.storage.StringConverter
    value.converter: org.apache.kafka.connect.storage.StringConverter
    topics: DB.EMD.COMPANY.0
    camel.sink.url: aws2-s3://test1232?keyName=s3-connect/${date:now:yyyyMMdd}/${date:now:yyyyMMdd-HHmmssSSS}
    camel.component.aws2-s3.configuration.autocloseBody: false
    camel.sink.endpoint.amazonS3Client =#class:org.apache.camel.kafkaconnector.CustomS3Client. <-- class will be added in org.apache.camel.kafkaconnector


@oscerd
Copy link
Contributor

oscerd commented Jun 19, 2020

yes, something like that

@saranyaeu2987
Copy link
Author

saranyaeu2987 commented Jun 19, 2020

@oscerd
I get this error now. If my S3Client class and yaml file right ?

org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: aws2-s3://heb-stg-emd-store-raw-ora.pemd?keyName=s3-connect/20200619/20200619-152832018 due to: useIAMCredentials is set to false, AmazonS3Client or accessKey and secretKey must be specified

Here is the kafkaconnector.yaml file

apiVersion: kafka.strimzi.io/v1alpha1
kind: KafkaConnector
metadata:
  name: s3-abcde-connector
  labels:
    strimzi.io/cluster: emd-kafka-cluster
spec:
  class: org.apache.camel.kafkaconnector.CamelSinkConnector
  tasksMax: 1
  config:
    key.converter: org.apache.kafka.connect.storage.StringConverter
    value.converter: org.apache.kafka.connect.storage.StringConverter
    topics: DB.EMD.COMPANY.0
    camel.sink.url: aws-s3://testse1232?keyName=s3-connect/${date:now:yyyyMMdd}/${date:now:yyyyMMdd-HHmmssSSS}
    camel.sink.maxPollDuration: 1000
    camel.sink.maxBatchPollSize: 10
    camel.component.aws2-s3.configuration.autocloseBody: false
    camel.sink.endpoint.amazonS3Client:org.apache.camel.kafkaconnector.CustomS3Client


@oscerd
Copy link
Contributor

oscerd commented Jun 19, 2020

I do have to try. I'll have a look next week, maybe.

@saranyaeu2987
Copy link
Author

@oscerd @valdar

Is the above error is because camel-aws2-s3 uses only StaticCredentialsProvider (accesskey and secret) and not WebIdentityTokenFileCredentialsProvider in case of no useIAMCredentials ?

https://github.com/apache/camel/blob/39cbd7f6866cb041d77f6fddc3c7c0721e4d0926/components/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/client/AWS2S3ClientFactory.java#L40

Is this a bug at camel-aws2-s3 because WebIdentityTokenFileCredentialsProvider is the one which looks for credentials in Env variable: AWS_WEB_IDENTITY_TOKEN_FILE?

@oscerd
Copy link
Contributor

oscerd commented Jun 19, 2020

It's not a bug, not all the credential provider can be supported in the component out of the box. We have to choose and btw it's something else. You need to instantiate the client and from the error it's clear that the client is not in the registry.

@oscerd
Copy link
Contributor

oscerd commented Jun 19, 2020

Any client instantiated should work. So it's definitely something in the way you are defining the client and configuring it.

@saranyaeu2987
Copy link
Author

saranyaeu2987 commented Jun 19, 2020

You need to instantiate the client and from the error it's clear that the client is not in the registry.
Any client instantiated should work. So it's definitely something in the way you are defining the client and configuring it.

--> ok, How to check if that my custom S3 client is in registry or not and what is this registry?

This is how I have added - I have created a separate jar with one class HEBS3Client with following definition

public class HEBS3Client implements S3Client{
    private static Logger log = LoggerFactory.getLogger(HEBS3Client.class);
    Region region = Region.US_EAST_1;
    S3Client s3;

    public static void main(String args[]){
        HEBS3Client hebs3Client = new HEBS3Client();
        hebs3Client.s3 = S3Client.builder() .region(hebs3Client.region) .credentialsProvider(WebIdentityTokenFileCredentialsProvider.create()).build();

    public String serviceName() {
        return "";
    }
    public void close() {
    }

with config
camel.sink.endpoint.amazonS3Client: heb.dsol.fp.HEBS3Client

and added jar in docker container which have other camel files.

  1. Any other config or setting needed to add S3client class in registry ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants