web-dev-qa-db-fra.com

Comment configurer cette application de démarrage à ressort pour utiliser le rôle IAM au lieu de clés et de secrets?

J'ai une application de démarrage de printemps qui communique avec S3 et SQS. Cela a fonctionné bien en utilisant des clés et des secrets AWS secrets, mais j'ai découvert que j'ai une restriction dans laquelle je ne peux pas utiliser ces informations d'identification, mais devez-vous authentifier à l'aide d'un rôle d'instance IAM.

Je n'ai pas de chance en faisant ce léger changement de changement.

J'ai créé une stratégie IAM pour permettre à mon utilisateur d'accéder à la file d'attente S3 Seau et SQS, voici:

foopolicy.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:*"
      ],
      "Resource": [
        "arn:aws:s3:::foo-demo-bucket"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "sqs:*"
      ],
      "Resource": [
        "arn:aws:sqs:::mysqsqueue"
      ]
    }
  ]
}

Ensuite, j'ai créé un rôle IAM à l'aide de cette politique et j'ai créé une relation de confiance pour le rôle permettant à Powerer d'assumer ce rôle

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::1234567890:user/foouser",
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Je gère l'application d'un terminal Bash où j'ai configuré l'AWS CLI, de sorte que de son point de vue, je suis connecté en tant que pliseur et le pignon a été ajouté au rôle d'entité de confiance.

Cependant, lorsque j'exécute mon application, comme configuré, je reçois l'erreur:

... Le jeton de sécurité inclus dans la demande est invalide. ...

 Java -Dconfig.file=./src/main/resources/application.yml -jar ./target/demo-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.7.RELEASE)

2019-08-14 15:39:07.223  INFO 58892 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication v0.0.1-SNAPSHOT on A6485192 with PID 58892 (/Users/foo/bar/src/demos3/target/demo-0.0.1-SNAPSHOT.jar started by foo in /Users/foo/bar/src/demos3)
2019-08-14 15:39:07.225  INFO 58892 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2019-08-14 15:39:10.785  INFO 58892 --- [           main] faultConfiguringBeanFactoryPostProcessor : No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.
2019-08-14 15:39:10.790  INFO 58892 --- [           main] faultConfiguringBeanFactoryPostProcessor : No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.
2019-08-14 15:39:10.793  INFO 58892 --- [           main] faultConfiguringBeanFactoryPostProcessor : No bean named 'integrationHeaderChannelRegistry' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created.
2019-08-14 15:39:10.810  INFO 58892 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'credentialsProvider' of type [com.amazonaws.auth.DefaultAWSCredentialsProviderChain] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-08-14 15:39:10.824  INFO 58892 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.integration.config.IntegrationManagementConfiguration' of type [org.springframework.integration.config.IntegrationManagementConfiguration$$EnhancerBySpringCGLIB$$364c7eab] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-08-14 15:39:10.838  INFO 58892 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'integrationDisposableAutoCreatedBeans' of type [org.springframework.integration.config.annotation.Disposables] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-08-14 15:39:11.206  WARN 58892 --- [           main] c.a.a.p.i.BasicProfileConfigLoader       : Your profile name includes a 'profile ' prefix. This is considered part of the profile name in the Java SDK, so you will need to include this prefix in your profile name when you reference this profile from your Java code.
2019-08-14 15:39:12.729  WARN 58892 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleMessageListenerContainer' defined in class path resource [org/springframework/cloud/aws/messaging/config/annotation/SqsConfiguration.class]: Invocation of init method failed; nested exception is com.amazonaws.services.sqs.model.AmazonSQSException: The security token included in the request is invalid. (Service: AmazonSQS; Status Code: 403; Error Code: InvalidClientTokenId; Request ID: 0b676d6d-5b41-5535-9d31-38a3d491aba6)
2019-08-14 15:39:12.735  INFO 58892 --- [           main] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-08-14 15:39:12.740 ERROR 58892 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleMessageListenerContainer' defined in class path resource [org/springframework/cloud/aws/messaging/config/annotation/SqsConfiguration.class]: Invocation of init method failed; nested exception is com.amazonaws.services.sqs.model.AmazonSQSException: The security token included in the request is invalid. (Service: AmazonSQS; Status Code: 403; Error Code: InvalidClientTokenId; Request ID: 0b676d6d-5b41-5535-9d31-38a3d491aba6)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1778) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:593) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:515) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.Java:320) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.Java:222) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:318) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:199) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.Java:845) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.Java:877) ~[spring-context-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:549) ~[spring-context-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.boot.SpringApplication.refresh(SpringApplication.Java:743) [spring-boot-2.1.7.RELEASE.jar!/:2.1.7.RELEASE]
  at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.Java:390) [spring-boot-2.1.7.RELEASE.jar!/:2.1.7.RELEASE]
  at org.springframework.boot.SpringApplication.run(SpringApplication.Java:312) [spring-boot-2.1.7.RELEASE.jar!/:2.1.7.RELEASE]
  at org.springframework.boot.SpringApplication.run(SpringApplication.Java:1214) [spring-boot-2.1.7.RELEASE.jar!/:2.1.7.RELEASE]
  at org.springframework.boot.SpringApplication.run(SpringApplication.Java:1203) [spring-boot-2.1.7.RELEASE.jar!/:2.1.7.RELEASE]
  at com.example.demo.DemoApplication.main(DemoApplication.Java:13) [classes!/:0.0.1-SNAPSHOT]
  at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_212]
  at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:62) ~[na:1.8.0_212]
  at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43) ~[na:1.8.0_212]
  at Java.lang.reflect.Method.invoke(Method.Java:498) ~[na:1.8.0_212]
  at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.Java:48) [demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
  at org.springframework.boot.loader.Launcher.launch(Launcher.Java:87) [demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
  at org.springframework.boot.loader.Launcher.launch(Launcher.Java:51) [demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
  at org.springframework.boot.loader.JarLauncher.main(JarLauncher.Java:52) [demo-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
Caused by: com.amazonaws.services.sqs.model.AmazonSQSException: The security token included in the request is invalid. (Service: AmazonSQS; Status Code: 403; Error Code: InvalidClientTokenId; Request ID: 0b676d6d-5b41-5535-9d31-38a3d491aba6)
  at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.Java:1660) ~[aws-Java-sdk-core-1.11.415.jar!/:na]
  at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.Java:1324) ~[aws-Java-sdk-core-1.11.415.jar!/:na]
  at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.Java:1074) ~[aws-Java-sdk-core-1.11.415.jar!/:na]
  at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.Java:745) ~[aws-Java-sdk-core-1.11.415.jar!/:na]
  at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.Java:719) ~[aws-Java-sdk-core-1.11.415.jar!/:na]
  at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.Java:701) ~[aws-Java-sdk-core-1.11.415.jar!/:na]
  at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.Java:669) ~[aws-Java-sdk-core-1.11.415.jar!/:na]
  at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.Java:651) ~[aws-Java-sdk-core-1.11.415.jar!/:na]
  at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.Java:515) ~[aws-Java-sdk-core-1.11.415.jar!/:na]
  at com.amazonaws.services.sqs.AmazonSQSClient.doInvoke(AmazonSQSClient.Java:2147) ~[aws-Java-sdk-sqs-1.11.415.jar!/:na]
  at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.Java:2116) ~[aws-Java-sdk-sqs-1.11.415.jar!/:na]
  at com.amazonaws.services.sqs.AmazonSQSClient.invoke(AmazonSQSClient.Java:2105) ~[aws-Java-sdk-sqs-1.11.415.jar!/:na]
  at com.amazonaws.services.sqs.AmazonSQSClient.executeGetQueueUrl(AmazonSQSClient.Java:1138) ~[aws-Java-sdk-sqs-1.11.415.jar!/:na]
  at com.amazonaws.services.sqs.AmazonSQSClient.getQueueUrl(AmazonSQSClient.Java:1110) ~[aws-Java-sdk-sqs-1.11.415.jar!/:na]
  at org.springframework.cloud.aws.messaging.support.destination.DynamicQueueUrlDestinationResolver.resolveDestination(DynamicQueueUrlDestinationResolver.Java:94) ~[spring-cloud-aws-messaging-2.1.2.RELEASE.jar!/:2.1.2.RELEASE]
  at org.springframework.cloud.aws.messaging.support.destination.DynamicQueueUrlDestinationResolver.resolveDestination(DynamicQueueUrlDestinationResolver.Java:38) ~[spring-cloud-aws-messaging-2.1.2.RELEASE.jar!/:2.1.2.RELEASE]
  at org.springframework.messaging.core.CachingDestinationResolverProxy.resolveDestination(CachingDestinationResolverProxy.Java:92) ~[spring-messaging-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.cloud.aws.messaging.listener.AbstractMessageListenerContainer.queueAttributes(AbstractMessageListenerContainer.Java:320) ~[spring-cloud-aws-messaging-2.1.2.RELEASE.jar!/:2.1.2.RELEASE]
  at org.springframework.cloud.aws.messaging.listener.AbstractMessageListenerContainer.initialize(AbstractMessageListenerContainer.Java:292) ~[spring-cloud-aws-messaging-2.1.2.RELEASE.jar!/:2.1.2.RELEASE]
  at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer.initialize(SimpleMessageListenerContainer.Java:111) ~[spring-cloud-aws-messaging-2.1.2.RELEASE.jar!/:2.1.2.RELEASE]
  at org.springframework.cloud.aws.messaging.listener.AbstractMessageListenerContainer.afterPropertiesSet(AbstractMessageListenerContainer.Java:267) ~[spring-cloud-aws-messaging-2.1.2.RELEASE.jar!/:2.1.2.RELEASE]
  at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer.afterPropertiesSet(SimpleMessageListenerContainer.Java:45) ~[spring-cloud-aws-messaging-2.1.2.RELEASE.jar!/:2.1.2.RELEASE]
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.Java:1837) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1774) ~[spring-beans-5.1.9.RELEASE.jar!/:5.1.9.RELEASE]
  ... 23 common frames omitted

Merci à quiconque peut m'aider à résoudre ceci

Voici la source de l'application qui démontre mon problème.

DemoApplication.java

package com.example.demo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@Slf4j
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  @Override
  public void run(String... args) throws Exception {
    while(true) {
      Thread.sleep(1000);
    }
  }
}

Application.yml

cloud:
  aws:
    stack:
      auto: false
    credentials:
      accessKey:
      secretKey:
      instanceProfile: true
      useDefaultAwsCredentialsChain: true
    region:
      static: us-east-1

aws:
  enabled: true
  region: us-east-1
  user: foouser
  access-key:
  secret-key:

  sqs:
    queue: mysqsqueue

  s3:
    bucket: foo-demo-bucket

aws.java

package com.example.demo;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.aws.messaging.listener.annotation.SqsListener;
import org.springframework.stereotype.Component;
import Java.io.File;

@Slf4j
@Component
public class AWS {

  @Autowired
  private AmazonS3 amazonS3;

  @Value("${aws.s3.bucket}")
  private String bucket;

  PutObjectResult upload(String filePath, String uploadKey) {
    File file = new File(filePath);
    return amazonS3.putObject(bucket, uploadKey, file);
  }

  @SqsListener("mysqsqueue")
  public void queueListener(String message) {
    System.out.println("Got an SQS message: " + message);
  }
}

awsconfiguration.java

package com.example.demo;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.sqs.AmazonSQSAsync;
import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.aws.messaging.config.annotation.EnableSqs;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
@EnableSqs
public class AWSConfiguration {

  @Value("${aws.region}")
  private String awsRegion;

  @Value("${aws.access-key}")
  private String awsAccessKey;

  @Value("${aws.secret-key}")
  private String awsSecretKey;

  @Bean
  @Primary
  public AmazonSQSAsync amazonSQSAsyncClient() {
    AmazonSQSAsync amazonSQSAsyncClient = AmazonSQSAsyncClientBuilder.standard()
        .withCredentials(amazonAWSCredentials())
        .withRegion(awsRegion)
        .build();
    return amazonSQSAsyncClient;
  }

  @Bean
  public AmazonS3 amazonS3Client() {
    AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
        .withCredentials(amazonAWSCredentials())
        .withRegion(awsRegion).build();
    return s3Client;
  }

  @Bean
  @Primary
  public AWSCredentialsProvider amazonAWSCredentials() {
    return new AWSCredentialsProvider() {
      public void refresh() {}
      public AWSCredentials getCredentials() {
        return new AWSCredentials() {
          public String getAWSSecretKey() {
            return awsSecretKey;
          }
          public String getAWSAccessKeyId() {
            return awsAccessKey;
          }
        };
      }
    };
  }
}
6
jjones

Votre politique IAM est fausse - la ressource SQS doit inclure des caractères génériques pour la région AWS et l'ID de compte (arn:aws:sqs:*:*:mysqsqueue à la place de arn:aws:sqs:::mysqsqueue).

La politique ci-dessous devrait fonctionner.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:*"
      ],
      "Resource": [
        "arn:aws:s3:::foo-demo-bucket"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "sqs:*"
      ],
      "Resource": [
        "arn:aws:sqs:*:*:mysqsqueue"
      ]
    }
  ]
}

Il est toujours préférable de confirmer si vos stratégies IAM sont spécifiées correctement en utilisant IAM Simulator car il attrape des erreurs les plus stupides.

1
mewa