0
votes

I am trying to use the credentials provider to access an aws S3 bucket from my IoT device. I implemented all the steps in this blogpost: https://aws.amazon.com/blogs/security/how-to-eliminate-the-need-for-hardcoded-aws-credentials-in-devices-by-using-the-aws-iot-credentials-provider/ ; however, when I use the credentials provided by the service to access S3 I get 'AmazonS3Exception: The AWS Access Key Id you provided does not exist in our records.' (Java SDK) My role has the following access policy:

{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Effect": "Allow",
           "Action": [
              "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::*/*"
       }
   ]
}

and this rust relationship:

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "Service": "credentials.iot.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
      }
   ]
}

I used the credentials provider endpoint from here:

aws iot describe-endpoint --endpoint-type iot:CredentialProvider

The device certificate and keys work fine to access the MQTT message broker.

edit the system time and server time differ for 1 hour, hence the token looks as if it is expired when I get it ("expiration" field in the token is the same time as current system time). This should not make any difference should it? Is there a way to directly use the role, instead of an alias to test this assumption?

This is how I access s3 in java:

    final AmazonS3 s3 = AmazonS3ClientBuilder.standard()
            .withCredentials(
                    new AWSStaticCredentialsProvider(
                            new BasicAWSCredentials(
                                    securityToken.getCredentials().getAccessKeyId(),
                                    securityToken.getCredentials().getSecretAccessKey()
                            )
                    )
            ).withRegion(Regions.US_EAST_1)
            .build();

    final ObjectMetadata object = s3.getObject(new GetObjectRequest(
            "iot-raspberry-test", "updateKioskJob.json"
    ), new File("/downloads/downloaded.json"));

This is the policy attached to the certificate of my thing:

{
  "Version": "2012-10-17",
  "Statement": {
     "Effect": "Allow",
     "Action": "iot:AssumeRoleWithCertificate",
     "Resource": "arn:aws:iot:us-east-1:myaccountid:rolealias/s3-access-role-alias"
  }
}

What could I be missing? Thanks in advance!

1

1 Answers

0
votes

The first policy is not complete:

{
   "Version": "2012-10-17",
   "Statement": [
       {
           "Effect": "Allow",
           "Action": [
              "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::*/*"
       }
   ]
}

Load it in the simulator and you can see that it won't work. S3 needs listing access (not GetObject).

See following example:

{
   "Version": "2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "s3:ListBucket"
         ],
         "Resource":"arn:aws:s3:::bucket-name"
      },
      {
         "Effect":"Allow",
         "Action":[
            "s3:GetObject"
         ],
         "Resource":"arn:aws:s3:::bucket-name/*"
      }
   ]
}