AWS IoT SDK - main L#206 Error subscribing : -28 (C code) - aws-sdk

I am trying to run the example in this tutorial from AWS IoT (AWS IoT Embedded C SDK).
My aws_iot_config.h file has the following configuration:
#define AWS_IOT_MQTT_HOST "XXXXXXX.iot.us-east-2.amazonaws.com" ///< Customer specific MQTT HOST. The same will be used for Thing Shadow
#define AWS_IOT_MQTT_PORT 8883 ///< default port for MQTT/S
#define AWS_IOT_MQTT_CLIENT_ID "c-sdk-client-id" ///< MQTT client ID should be unique for every device
#define AWS_IOT_MY_THING_NAME "SM1" ///< Thing Name of the Shadow this device is associated with
#define AWS_IOT_ROOT_CA_FILENAME "iotRootCA.pem" ///< Root CA file name
#define AWS_IOT_CERTIFICATE_FILENAME "deviceCert.crt" ///< device signed certificate file name
#define AWS_IOT_PRIVATE_KEY_FILENAME "deviceCert.key" ///< Device private key filename
This is how my policies are:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:us-east-2:338639570104:topic/sm1"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:us-east-2:338639570104:topic/sm1"
}
]
}
When I run the subscribe_publish_sample example, I am getting the following error:
DEBUG: iot_tls_connect L#236 ok
[ Protocol is TLSv1.2 ]
[ Ciphersuite is TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 ]
DEBUG: iot_tls_connect L#238 [ Record expansion is 29 ]
DEBUG: iot_tls_connect L#243 . Verifying peer X.509 certificate...
DEBUG: iot_tls_connect L#252 ok
DEBUG: iot_tls_connect L#262 . Peer certificate information ...
DEBUG: iot_tls_connect L#264 cert. version : 3
serial number : 3C:75:FE:30:01:DD:A3:B9:EF:72:DC:F6:7A:5C:A2:54
issuer name : C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec Class 3 ECC 256 bit SSL CA - G2
subject name : C=US, ST=Washington, L=Seattle, O=Amazon.com, Inc., CN=*.iot.us-east-2.amazonaws.com
issued on : 2017-10-12 00:00:00
expires on : 2018-10-13 23:59:59
signed using : ECDSA with SHA256
EC key size : 256 bits
basic constraints : CA=false
subject alt name : iot.us-east-2.amazonaws.com, *.iot.us-east-2.amazonaws.com
key usage : Digital Signature
ext key usage : TLS Web Server Authentication, TLS Web Client Authentication
Subscribing...
ERROR: main L#206 Error subscribing : -28
Can anyone show me what is happening? Am I missing something?

As I did not find out a good and complete tutorial related to process of sending data from a device to AWS IoT, including all the steps needed, I tried changing the policy I was using to:
{
"Effect": "Allow",
"Action": "iot:*",
"Resource": "*"
}
Though this wildcard on Resource apparently is not so good, it was the way I used, since the other policies were not working.

The AWS IoT core policy actions are at https://docs.aws.amazon.com/iot/latest/developerguide/iot-policy-actions.html
The sample client needs all four MQTT policies and needs iot:Publish, iot:Receive, and iot:Subscribe on the sdkTest topic. The topic name is hardcoded to sdkTest in the sample. So this works:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:Connect",
"Resource": "arn:aws:iot:us-east-2:338639570104:client/c-sdk-client-id"
},
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:us-east-2:338639570104:client/c-sdk-client-id"
},
{
"Effect": "Allow",
"Action": "iot:Receive",
"Resource": "arn:aws:iot:us-east-2:338639570104:client/c-sdk-client-id"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:us-east-2:338639570104:client/c-sdk-client-id"
},
{
"Effect": "Allow",
"Action": "iot:Publish",
"Resource": "arn:aws:iot:us-east-2:338639570104:*sdkTest*"
},
{
"Effect": "Allow",
"Action": "iot:Receive",
"Resource": "arn:aws:iot:us-east-2:338639570104:*sdkTest*"
},
{
"Effect": "Allow",
"Action": "iot:Subscribe",
"Resource": "arn:aws:iot:us-east-2:338639570104:*sdkTest*"
}
]
}

Related

Json policy script for denying object upload to aws s3 if the object doesn't uses aws s3 encryption or aws:kms encryption

Hi I want to create a s3 policy for my bucket which denies the user to upload an object which doesn't uses aws s3 encryption or aws kms encryption (It must use one of the encryption). Here is the link for the policy generator https://awspolicygen.s3.amazonaws.com/policygen.html
I have generated this policy.
{
"Id": "Policy1631518070654",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1631518063107",
"Action": [
"s3:PutObject"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::webserver7/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
},
"StringNotLike": {
"s3:x-amz-server-side-encryption-aws-kms-key-id": "aws:kms"
}
},
"Principal": "*"
}
]
}
We can Interpret the policy as follows.... "If the object doesn't uses aws s3 encryption AND aws:kms encryption then deny the upload.
but we can't use the two encryption at the same time. So I want the policy as follows.
"If the object doesn't uses aws s3 encryption OR aws:kms encryption then deny the object upload.
If you want OR, you need to have two statements:
{
"Id": "Policy1631518070654",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1631518063107",
"Action": [
"s3:PutObject"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::webserver7/*",
"Condition": {
"StringNotLike": {
"s3:x-amz-server-side-encryption-aws-kms-key-id": "aws:kms"
}
},
"Principal": "*"
},
{
"Sid": "Stmt16315180631072",
"Action": [
"s3:PutObject"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::webserver7/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
},
"Principal": "*"
}
]
}
This is not possible to add this kind of policy at the moment. Try using policy for single encryption only.

Amazon S3 bucket policy allow access to ONLY specific http

I'm trying to restrict access to objects (media files) in an Amazon S3 bucket to a specific referral domain, privatewebsite.com, with a bucket policy, but keep getting access denied, no matter the domain referred.
I have the following settings for Block Public Access
Block public access to buckets and objects granted through new access control lists (ACLs) - On
Block public access to buckets and objects granted through any access control lists (ACLs) - On
Block public access to buckets and objects granted through new public bucket policies - Off
Block public and cross-account access to buckets and objects through any public bucket policies - Off
I've added the following code, URL with and without, http:// and https://, yet still get access denied. (privatewebsite.com, https://privatewebsite.com, http://privatewebsite.com)
{
"Version": "2012-10-17",
"Id": "Policy8675309",
"Statement": [
{
"Sid": "Stmt8675309",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-media-bucket/*",
"Condition": {
"StringLike": {
"aws:Referer": "https://privatewebsite.com"
}
}
},
{
"Sid": "Explicit deny to ensure requests are allowed only from specific referer.",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-media-bucket/*",
"Condition": {
"StringNotLike": {
"aws:Referer": [
"https://privatewebsite.com/*",
"http://privatewebsite.com/*"
]
}
}
}
]
}
Can anyone see any obvious errors in my bucket policy?
I expect this policy to ALLOW any request, when coming from a page on privatewebsite.com, while DENY-ing all other requests, but at the moment ALL requests are denied.
From Bucket Policy Examples - Restricting Access to a Specific HTTP Referrer:
{
"Version": "2012-10-17",
"Id": "http referer policy example",
"Statement": [
{
"Sid": "Allow get requests originating from www.example.com and example.com.",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::examplebucket/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"http://www.example.com/*",
"http://example.com/*"
]
}
}
}
]
}
This method only grants Allow access for the given Referer. There is no need to use a Deny policy with it because access is denied by default. Thus, only the Allow permissions are granted.
Try this for you string-like section (allow section):
"StringLike": {
"aws:Referer": [
"https://privatewebsite.com/*",
"http://privatewebsite.com/*"
]
}

AWS IAM Policy To Restrict S3 Access (Prefix) Based On IAM User's Tag

A variety of IAM users are sharing access to an S3 bucket. The S3 bucket has content separated by user so each user has a unique area they have access to.
For instance:
S3 Bucket: example-bucket.
IAM User: UserOne. This user is tagged with sampleTag=u11111.
IAM User: UserTwo. This user is tagged with sampleTag=u22222.
Many more tagged IAM users.
I'd like to write an IAM policy such that:
UserOne has access to read+write content to s3://example-bucket/u11111/* and read content from s3://example-bucket/config/u11111/
UserTwo has access to read+write content to s3://example-bucket/u22222/* and read content from s3://example-bucket/config/u22222/
Etc...
Note that the S3 key includes the value of the sampleTag in the path.
I'd like this single policy to be able to be applied to the entire group of IAM users without need to include an individual policy for each user.
I expected this to be possible thanks to ${aws:PrincipalTag/sampleTag} which I thought would inject the tag value in that location in the resource strings. But after playing with the policy simulator, it doesn't seem to accomplish this.
Current policy looks like:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets"
],
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::example-bucket",
"arn:aws:s3:::example-bucket-test"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::example-bucket",
"arn:aws:s3:::example-bucket-test"
],
"Condition": {
"StringEquals": {
"s3:prefix": [
"",
"${aws:PrincipalTag/sampleTag}/"
],
"s3:delimiter": ["/"]
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::example-bucket",
"arn:aws:s3:::example-bucket-test"
],
"Condition": {
"StringLike": {
"s3:prefix": ["${aws:PrincipalTag/sampleTag}/*"]
}
}
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl"
],
"Resource": [
"arn:aws:s3:::example-bucket/config/${aws:PrincipalTag/sampleTag}/*",
"arn:aws:s3:::example-bucket-test/config/${aws:PrincipalTag/sampleTag}/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::example-bucket/${aws:PrincipalTag/sampleTag}/*",
"arn:aws:s3:::example-bucket-test/${aws:PrincipalTag/sampleTag}/*"
]
}
]
}
I think the last two policies to not work. I can't find documentation to say if you can embed variables into the Resource strings or not, but s3:prefix doesn't seem to be available for GetObject or PutObject operations -- so I'm not sure how else to restrict the scope of those permissions.
Any ideas as to what is wrong or how to accomplish this would be appreciated!
I think it is possible to use ${aws:PrincipalTag} in the Ressource property of a policy. Just look into the docs of IAM. The example uses the PrincipalTag as last part of the Ressource value.
(Just use Strg + F and type PrincipalTag on the docs website an you find the example)
You are right, the last two policies will not work.
According to documentation aws:PrincipalTag/tag-key works with string operators, hence aws:PrincipalTag/tag-key usage will only works inside Condition policy elements.
Also, s3:prefix condition key only work for ListBucket & ListBucketVersions actions: https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazons3.html#amazons3-policy-keys
You can have PrincipalTag as part of the resource.
This works.
{
"Sid": "FullPermissionOnlyForPrefix",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::mybucket/${aws:PrincipalTag/team}*",
"arn:aws:s3:::mybucket/${aws:PrincipalTag/team}/*"
]
}

Create a single IAM user to access only specific S3 bucket

I have many S3 buckets in my AWS account. But now I created an IAM user and a new S3 bucket, I would like to give this user the ability to access the new S3 bucket using a client like CyberDuck.
I tried to create so many policies. But after that this user getting permission to list all my other buckets also. How can I give access to listing and writing access to a single S3 bucket?
First you create a Policy to allow access to a single S3 bucket (IAM -> Policies -> Create Policy). You can use AWS Policy Generator (http://awspolicygen.s3.amazonaws.com/policygen.html), it should look something like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1528735049406",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:HeadBucket",
"s3:ListBucket",
"s3:ListObjects",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::YOURBUCKETNAME"
}
]
}
Save the policy and note the name you gave to it, then go to IAM -> Users and select the desired user. In the permissions tab, click 'Add permissions', then select 'Attach existing policies directly' near the top. Find your policy by its name, tick its checkbox and complete the process.
Per this ( https://aws.amazon.com/blogs/security/writing-iam-policies-grant-access-to-user-specific-folders-in-an-amazon-s3-bucket/ )
they’ll need to be able to at least list all the buckets. But other than that, this also provides an example policy, which I just used last night for my own account, so I can confirm that it works.
Update
Okay, I've tested and confirmed using CyberDuck that the following policy (customized to your environment of course) will prevent users from viewing all root buckets, and only allow them access to the bucket you specify:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAllInBucket",
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::bucket-for-single-user"
}
]
}
Just make sure that when you specify the path in CyberDuck, that you enter it as: bucket-for-single-user.s3.amazonaws.com.
Also, only START unrestricted like that, just to make sure it's working for you (since access appears to be an issue). After that, apply restrictions, you know...least privilege and all.
According to Cyberduck Help / Howto / Amazon S3, it supports directly entering the Bucket name, as <bucketname>.s3.amazonaws.com. If this is possible with the client you are using, you don't need s3:ListAllMyBuckets permissions.
Actions should be grouped by the Resources that they can parse
(Conditions are also potentially different per Action).
This IAM policy will allow full control of all the content (aka in the bucket)
without controlling of the S3 bucket subresources (aka of the bucket):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "BucketOperations",
"Effect": "Allow",
"Action": "s3:ListBucket*",
"Resource": "arn:aws:s3:::<bucketname>"
},
{
"Sid": "ObjectOperations",
"Effect": "Allow",
"Action": [
"s3:AbortMultipartUpload",
"s3:ListMultipartUploads",
"s3:DeleteObject*",
"s3:GetObject*",
"s3:PutObject*"
],
"Resource": "arn:aws:s3:::<bucketname>/*"
},
{
"Sid": "DenyAllOthers",
"Effect": "Deny",
"Action": "s3:*",
"NotResource": [
"arn:aws:s3:::<bucketname>",
"arn:aws:s3:::<bucketname>/*"
]
}
]
}
If you aren't specifically trying to lock the IAM user out of every
possible public S3 bucket, you can leave the "DenyAllOthers" Sid off,
without granting additional permissions to the users.
FYI, the AWS ReadOnlyAccess policy automatically gives s3:* to
anything it's attached to. I recommend ViewOnlyAccess (which will
unfortunately grant s3:ListAllMyBuckets without the DenyAllOthers).
Create my own policy and working for me. The IAM user can just list all bucket. But cant do anything on another bucket. The user can only get access to the specific bucket with reading, write, delete files privileges.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "<EXAMPLE_SID>",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::<MYBUCKET>"
},
{
"Sid": "<EXAMPLE_SID>",
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
}, {
"Sid": "<EXAMPLE_SID>",
"Effect": "Deny",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::<MYotherBUCKET>"
}, {
"Sid": "<EXAMPLE_SID>",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::<MYBUCKET>/*"
}
]
}
Then add this policy also to this user. This policy will restrict all type of operation to listed other s3 bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "<EXAMPLE_SID>",
"Effect": "Deny",
"Action": [
"s3:PutAnalyticsConfiguration",
"s3:GetObjectVersionTagging",
"s3:CreateBucket",
"s3:ReplicateObject",
"s3:GetObjectAcl",
"s3:DeleteBucketWebsite",
"s3:PutLifecycleConfiguration",
"s3:GetObjectVersionAcl",
"s3:PutBucketAcl",
"s3:PutObjectTagging",
"s3:DeleteObject",
"s3:GetIpConfiguration",
"s3:DeleteObjectTagging",
"s3:GetBucketWebsite",
"s3:PutReplicationConfiguration",
"s3:DeleteObjectVersionTagging",
"s3:GetBucketNotification",
"s3:PutBucketCORS",
"s3:DeleteBucketPolicy",
"s3:GetReplicationConfiguration",
"s3:ListMultipartUploadParts",
"s3:PutObject",
"s3:GetObject",
"s3:PutBucketNotification",
"s3:PutBucketLogging",
"s3:PutObjectVersionAcl",
"s3:GetAnalyticsConfiguration",
"s3:GetObjectVersionForReplication",
"s3:GetLifecycleConfiguration",
"s3:ListBucketByTags",
"s3:GetInventoryConfiguration",
"s3:GetBucketTagging",
"s3:PutAccelerateConfiguration",
"s3:DeleteObjectVersion",
"s3:GetBucketLogging",
"s3:ListBucketVersions",
"s3:ReplicateTags",
"s3:RestoreObject",
"s3:GetAccelerateConfiguration",
"s3:GetBucketPolicy",
"s3:PutEncryptionConfiguration",
"s3:GetEncryptionConfiguration",
"s3:GetObjectVersionTorrent",
"s3:AbortMultipartUpload",
"s3:PutBucketTagging",
"s3:GetBucketRequestPayment",
"s3:GetObjectTagging",
"s3:GetMetricsConfiguration",
"s3:DeleteBucket",
"s3:PutBucketVersioning",
"s3:PutObjectAcl",
"s3:ListBucketMultipartUploads",
"s3:PutMetricsConfiguration",
"s3:PutObjectVersionTagging",
"s3:GetBucketVersioning",
"s3:GetBucketAcl",
"s3:PutInventoryConfiguration",
"s3:PutIpConfiguration",
"s3:GetObjectTorrent",
"s3:ObjectOwnerOverrideToBucketOwner",
"s3:PutBucketWebsite",
"s3:PutBucketRequestPayment",
"s3:GetBucketCORS",
"s3:PutBucketPolicy",
"s3:GetBucketLocation",
"s3:ReplicateDelete",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::<MYotherBUCKET>/*",
"arn:aws:s3:::<MYotherBUCKET>"
]
}
]
}
I was recently able to get this to work using Amazon's documentation. The key for me was to point the IAM User to the specific bucket NOT the S3 console. Per the documentation, "Warning: After you change these permissions, the user gets an Access Denied error when they access the main Amazon S3 console. The main console link is similar to the following:
https://s3.console.aws.amazon.com/s3/home
Instead, the user must access the bucket using a direct console link to the bucket, similar to the following:
https://s3.console.aws.amazon.com/s3/buckets/awsexamplebucket/"
My policy is below:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1589486662000",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::AWSEXAMPLEBUCKET",
"arn:aws:s3:::AWSEXAMPLEBUCKET/*"
]
}
]
}

How to give grained IAM control for AWS Aurora?

I want to give a least privilege IAM policy to control creation and deletion of AWS Aurora instances. Rights for DB Instances working fine, but DB Cluster objects can not be deleted:
User xxxxxxx is not authorized to perform: rds:DeleteDBCluster
Here is what rights I want:
{
"Sid": "313",
"Effect": "Allow",
"Action": [
"rds:ModifyDBCluster",
"rds:DeleteDBCluster"
],
"Resource": "arn:aws:rds:eu-west-1:123456789101:cluster:*",
"Condition": {
"StringEquals": {
"rds:cluster-tag/author": "qa"
}
}
}
But as far as I tested only this works:
{
"Sid": "313",
"Effect": "Allow",
"Action": [
"rds:ModifyDBCluster",
"rds:DeleteDBCluster"
],
"Resource": "*"
}