Unable to connect to AWS service[API Gateway] from IOT Core device[Inside docker container]

0

I have created a component using GreengrassV2 and running multiple containers inside this component. Now, my requirement is to call API Gateway and fetch some data into one of the docker containers running on the local device inside the component. I am using "import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;" for fetching the credentials but getting

05:45:06.476 INFO  - Calling API Gateway with request params com.amazon.spiderIoT.stowWorkcell.entities.ApiGatewayRequest@e958e637
Exception in thread "main" com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: [EnvironmentVariableCredentialsProvider: Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY)), SystemPropertiesCredentialsProvider: Unable to load AWS credentials from Java system properties (aws.accessKeyId and aws.secretKey), WebIdentityTokenCredentialsProvider: To use assume role profiles the aws-java-sdk-sts module must be on the class path., com.amazonaws.auth.profile.ProfileCredentialsProvider@7c36db44: profile file cannot be null, com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@6c008c24: Failed to connect to service endpoint: ]
	at com.amazonaws.auth.AWSCredentialsProviderChain.getCredentials(AWSCredentialsProviderChain.java:136)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.getCredentialsFromContext(AmazonHttpClient.java:1269)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.runBeforeRequestHandlers(AmazonHttpClient.java:845)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:794)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:781)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:755)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:715)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:697)
	at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:561)
	at com.amazon.spiderIoT.stowWorkcell.client.ApiGatewayClient.execute(ApiGatewayClient.java:134)
	at com.amazon.spiderIoT.stowWorkcell.client.ApiGatewayClient.execute(ApiGatewayClient.java:79)
	at com.amazon.spiderIoT.stowWorkcell.StowWorkcellService.startMQTTSubscriberForSortLocationEvents(StowWorkcellService.java:120)
	at com.amazon.spiderIoT.stowWorkcell.StowWorkcellService.onInitialize(StowWorkcellService.java:65)
	at com.amazon.spideriot.sdk.service.Service.run(Service.java:79)
	at com.amazon.spiderIoT.stowWorkcell.StowWorkcellServiceDriver.main(StowWorkcellServiceDriver.java:26)

My dependencyConfiguration looks like :-

{
  "aws.greengrass.TokenExchangeService": {
    "componentVersion": "2.0.3",
    "DependencyType": "HARD"
  },
  "aws.greengrass.DockerApplicationManager": {
    "componentVersion": "2.0.4"
  },
  "aws.greengrass.Cloudwatch": {
    "componentVersion": "3.0.0"
  },
  "aws.greengrass.Nucleus": {
    "componentVersion": "2.4.0",
    "configurationUpdate": {
      "merge": "{\"logging\":{\"level\":\"INFO\"}, \"iotRoleAlias\": \"GreengrassV2TestCoreTokenExchangeRoleAlias\"}"
    }
  },
  "aws.greengrass.LogManager": {
    "componentVersion": "2.2.3",
    "configurationUpdate": {
      "merge": "{\"logsUploaderConfiguration\":{\"systemLogsConfiguration\": {\"uploadToCloudWatch\": \"true\",\"minimumLogLevel\": \"INFO\",\"diskSpaceLimit\": \"10\",\"diskSpaceLimitUnit\": \"MB\",\"deleteLogFileAfterCloudUpload\": \"false\"},\"componentLogsConfigurationMap\": {\"LedService\": {\"minimumLogLevel\": \"INFO\",\"diskSpaceLimit\": \"20\",\"diskSpaceLimitUnit\": \"MB\",\"deleteLogFileAfterCloudUpload\": \"false\"}}},\"periodicUploadIntervalSec\": \"5\"}"
    }
  }
}

Java code for using AWS credentials

public class APIGatewayModule extends AbstractModule {

    @Provides
    @Singleton
    public AWSCredentialsProvider getAWSCredentialProvider() {

        return new DefaultAWSCredentialsProviderChain();
    }

    @Provides
    @Singleton
    public ApiGatewayClient getApiGatewayClient(final AWSCredentialsProvider awsCredentialsProvider) {
        System.out.println("Getting client configurations");
        final com.amazonaws.ClientConfiguration clientConfiguration = new com.amazonaws.ClientConfiguration();
        System.out.println("Got client configurations" + clientConfiguration);
        return new ApiGatewayClient(clientConfiguration, Region.getRegion(Regions.fromName("us-east-1")), awsCredentialsProvider, AmazonHttpClient.builder().clientConfiguration(clientConfiguration).build());
    }
}

I have been following this doc: https://docs.aws.amazon.com/greengrass/v2/developerguide/device-service-role.html My question is regarding everywhere in this document, it is mentioned that "AWS IoT Core credentials provider", what credentials provider should we use? Also, as mentioned in this doc we should use --provision true when "When you run the AWS IoT Greengrass Core software, you can choose to provision the AWS resources that the core device requires." But we started without this flag, how can this be tackled and is there any other document that provides reference to using credentials provider and calling API Gateway from AWS SDK Java.

On SSH to docker, i could find that the variable is set

AWS_CONTAINER_CREDENTIALS_FULL_URI=http://localhost:38135/2016-11-01/credentialprovider/

But unable to curl from docker to this URL, is this how this is suppose to work?

3 Answers
0
Accepted Answer

Worked after adding retries and updating nucleus to 2.5.6. Thanks!

Shivam
answered 2 years ago
0

When components run containers, there are a couple things that need to be completed. You've confirmed the first which is injecting the AWS_CONTAINER_CREDENTIALS_FULL_URI environment variable into the container.

The Nucleus sets up the credential provider (TES) on localhost of the host system. In order for containers to access that instead of their own localhost, the container needs access to the host's networking namespace as mentioned here.

For the container's docker run command (or equivalent if using other container manager or docker-compose), try adding --network host and see if curl works. If so, you're container should be able to use the endpoint to get credentials.

If this doesn't work, can you provide the lifecycle portion of the recipe file?

AWS
Gavin_A
answered 2 years ago
  • Added lifecycle portion below. curl ${AWS_CONTAINER_CREDENTIALS_FULL_URI} is giving empty response, when IOT core software installed using default provision.

    curl ${AWS_CONTAINER_CREDENTIALS_FULL_URI} is giving curl: (7) Failed to connect to localhost port 38135 after 0 ms: Connection refused", when IOT core software installed using provision=true

  • Can you test netstat -na inside the container and see if the host's processes are showing? Based on the recipe and compose files, this should be working. And to confirm, is Greengrass Core nucleus running as a process along side dockerd on the host? Asking to clarify the coreservice container.

0

Yes, i am using network_mode as host in docker-compose file.

docker-compose file for reference.

version: "3"

networks:
  core:

services:
  core:
    image: "XXXXXXX.dkr.ecr.us-east-1.amazonaws.com/coreservice-1.0:latest"
    container_name: core
    # networks:
    #   - core
    network_mode: host
    environment:
      AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT: ${AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT}
      SVCUID: ${SVCUID}
    volumes:
      - ${AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT}:${AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT}

  stowservice:
    image: "XXXXXXX.dkr.ecr.us-east-1.amazonaws.com/stowworkcellservice-1.0:latest"
    container_name: stowservice
    network_mode: host
    # networks:
    #   - core
    #   - host
    # ports:
    #   - '38134:38135'
    environment:
      AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT: ${AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT}
      SVCUID: ${SVCUID}
      AWS_CONTAINER_CREDENTIALS_FULL_URI: ${AWS_CONTAINER_CREDENTIALS_FULL_URI}
      AWS_CONTAINER_AUTHORIZATION_TOKEN: ${AWS_CONTAINER_AUTHORIZATION_TOKEN}
      PROVISION: "true"
    depends_on:
      - core
      - ledservice
      - scannerservice
    volumes:
      - ${AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT}:${AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT}
    command: --uri localhost:4400 --port 9100 --name stow

Lifecycle class for reference :

"Manifests": [
    {
      "Platform": {
        "os": "all"
      },
      "Lifecycle": {
        "Setenv": {
        },
        "Run": "docker rm core -f && docker rm stowservice -f && docker-compose -f {artifacts:path}/docker-compose.yml up -d"
      },
      "Artifacts": [
        {
          "URI": "docker:XXXXXXX.dkr.ecr.us-east-1.amazonaws.com/coreservice-1.0:latest"
        },
        {
          "URI": "s3://bucket/docker-compose.yml"
        },
        {
          "URI": "docker:XXXXXXX.dkr.ecr.us-east-1.amazonaws.com/stowworkcellservice-1.0:latest"
        }
      ]
    }
  ],
Shivam
answered 2 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions