amazon-archives / aws-sdk-unity

ARCHIVED: The aws sdk for unity is now distributed as a part of aws sdk for dotnet:
https://github.com/aws/aws-sdk-net
Other
105 stars 43 forks source link

unable to use KMS server side encryption for PostObject #123

Closed citiusaltius closed 8 years ago

citiusaltius commented 8 years ago

Hey,

Sorry, so I realized that I didn't reply to issue #62 . I'm still having the same issue with being rejected with a bad response for setting the AWS:KMS metadata/header as such for 2.0.0.5, and this doesn't change in 2.1.0.1, either. Can you please advise on how to achieve SSE with the Unity API?

As tested before, the metadata portion - aside from the encryption - is completely functional.

Thank you!

` Client = new AmazonS3Client( GlobalBehaviour.Creds, Defines.Global.StorageConfig);

        PostObjectRequest Req = new PostObjectRequest();
        Req.Bucket = Defines.Global.StorageBucket;
        Req.Key = "users/" + GlobalBehaviour.Creds.GetIdentityId() + "/uploads/";
        if (KeyPrefix.Length > 0)
        {
            Req.Key += KeyPrefix;
        }
        else if (KeyPrefix.Length == 0)
        {
            // do nothing if no key prefix
        }
        else
        {
            throw new UnityException("Cannot have a trailing slash for key prefix");
        }
        Req.Key += System.DateTime.UtcNow.Ticks + "|" + 
            GlobalBehaviour.Creds.DeviceId + "|" + 
            GlobalBehaviour.Creds.GetIdentityId();
        if (KeyPostfix.Length > 0)
        {
            Req.Key += KeyPostfix;
        }

        Utils.DebugBehaviour.WriteLine("Uploaded to:\n" + Req.Key);

        // Assign 5 MB memorystream max
        MemoryStream ms = new MemoryStream(5000000);
        StreamWriter sw = new StreamWriter(ms, Encoding.UTF8);
        sw.Write(Body);
        sw.Flush();
        Req.ContentType = ObjectType;

        Req.Metadata.Add("UserId", GlobalBehaviour.Creds.GetIdentityId());
        Req.Metadata.Add("DeviceId", GlobalBehaviour.DeviceId);
        Req.Metadata.Add("S3Key", Req.Key);

        Req.Metadata.Add("TimestampCreation", Defines.Global.UtcNowTimestampFormatAmz());
        Req.Metadata.Add("Type", ObjectType);
        Req.Metadata.Add("Subtype", ObjectSubtype);

        //AdditionalHeaders.Add(Amazon.Util.HeaderKeys.XAmzServerSideEncryptionHeader, "aws:kms");
        //AdditionalHeaders.Add(Amazon.Util.HeaderKeys.XAmzServerSideEncryptionAwsKmsKeyIdHeader, Defines.Global.EncryptionKey);

        // Add additional metadata if dictionary exists and is not empty
        if (Metadata != null && Metadata.Count > 0)
        {
            foreach (string key in Metadata.Keys)
            {
                if(Req.Metadata.ContainsKey(key) == false)
                {
                    Req.Metadata.Add(key, Metadata[key]);
                }
                else
                {
                    Utils.DebugBehaviour.WriteLine(key + " already exists with value \n" +
                        Req.Metadata[key] + "\n and cannot take on new value\n" + 
                        Metadata[key]);
                }

            }
        }

        if (IsEncrypted == true)
        {
            Req.Metadata.Add(Amazon.Util.HeaderKeys.XAmzServerSideEncryptionHeader, "aws:kms");
            Req.Metadata.Add(Amazon.Util.HeaderKeys.XAmzServerSideEncryptionAwsKmsKeyIdHeader, Defines.Global.StorageHipaaEncryptionKey);
        }

        // Create signed policy
        StringBuilder MetadataAddPolicy = new StringBuilder();
        foreach (string Key in Req.Metadata.Keys)
        {
            string KeyLower = Key.ToLower();
            MetadataAddPolicy.Append(",\n{\"");
            if (Key.StartsWith("x-amz") == true)
            {
                MetadataAddPolicy.Append(KeyLower + "\": \"" + Req.Metadata[Key]);
            }
            else
            {
                MetadataAddPolicy.Append("x-amz-meta-" + KeyLower + "\": \"" + Req.Metadata[Key]);
            }
            MetadataAddPolicy.Append("\"}");
        }

        string policyString = "";
        if (Req.Key.LastIndexOf('/') == -1)
        {
            policyString = "{\"expiration\": \""
                + System.DateTime.UtcNow.AddHours(24).ToString("yyyy-MM-ddTHH:mm:ssZ")
                + "\",\"conditions\": "
                + "["
                + "{\"bucket\": \"" + Req.Bucket + "\"},"
                + "[\"starts-with\", \"$key\", \"" + "\"],"
                + "{\"acl\": \"private\"},"
                + "[\"eq\", \"$Content-Type\", " + "\"" + Req.ContentType + "\"" + "]"
                + MetadataAddPolicy.ToString()
                + "]}";
        }
        else
        {
            policyString = "{\"expiration\": \""
                + System.DateTime.UtcNow.AddHours(24).ToString("yyyy-MM-ddTHH:mm:ssZ")
                + "\",\"conditions\": "
                + "["
                + "{\"bucket\": \"" + Req.Bucket + "\"},"
                + "[\"starts-with\", \"$key\", \"" + Req.Key.Substring(0, Req.Key.LastIndexOf('/')) + "/\"],"
                + "{\"acl\": \"private\"},"
                + "[\"eq\", \"$Content-Type\", " + "\"" + Req.ContentType + "\"" + "]"
                + MetadataAddPolicy.ToString()
                + "]}";
        }

        Debug.Log(policyString);

        Req.SignedPolicy = Amazon.S3.Util.S3PostUploadSignedPolicy.GetSignedPolicy(policyString, GlobalBehaviour.Creds);

        ms.Seek(0, SeekOrigin.Begin);
        Req.InputStream = ms;

        Dictionary<string, string> AdditionalHeaders = new Dictionary<string, string>();
        if (IsEncrypted == true)
        {

            AdditionalHeaders.Add(Amazon.Util.HeaderKeys.XAmzServerSideEncryptionHeader, "aws:kms");
             AdditionalHeaders.Add(Amazon.Util.HeaderKeys.XAmzServerSideEncryptionAwsKmsKeyIdHeader, Defines.Global.EncryptionKey);
            Client.PostObjectAsync(Req, Callback, AdditionalHeaders);
        }
        else
        {
            Client.PostObjectAsync(Req, Callback, new Dictionary<string, string>());
        }`

results in a policy of

{"expiration": "2016-01-29T18:43:18Z","conditions": [{"bucket": "projectpage"},["starts-with", "$key", "users/us-east-1:11111111-1111-1111-1111-111111111111/uploads/conversations/1111/"],{"acl": "private"},["eq", "$Content-Type", "NewConversationMessage"], {"x-amz-meta-userid": "us-east-1:11111111-1111-1111-1111-111111111111"}, {"x-amz-meta-deviceid": "fc2146a142def58893fffe1458376203516dd17c"}, {"x-amz-meta-s3key": "users/us-east-1:11111111-1111-1111-1111-111111111111/uploads/conversations/1111/635896033985005242|fc2146a142def58893fffe1458376203516dd17c|us-east-1:11111111-1111-1111-1111-111111111111"}, {"x-amz-meta-timestampcreation": "20160128T184318Z"}, {"x-amz-meta-type": "NewConversationMessage"}, {"x-amz-meta-subtype": "RawTextMessage"}, {"x-amz-meta-conversationid": "1111"}, {"x-amz-meta-test": "newValue"}, {"x-amz-meta-identityidsender": "1111"}, {"x-amz-server-side-encryption": "aws:kms"}, {"x-amz-server-side-encryption-aws-kms-key-id": "11111111-1111-1111-1111-111111111111"}]}

and a request response:

Exception while posting the result objectreceieved error BadRequest UnityEngine.Debug:Log(Object) Assets.Scripts.Utils.DebugBehaviour:WriteLine(String) (at Assets/Scripts/Utils/DebugBehaviour.cs:23) Assets.Scripts.DataStorage.Storage:postObjectAsyncComplete(AmazonServiceResult`2) (at Assets/Scripts/DataStorage/Storage.cs:291) Amazon.S3.cAnonStorey3C:<>m65(AmazonWebServiceRequest, AmazonWebServiceResponse, Exception, AsyncOptions) (at Assets/AWSSDK/src/Services/S3/Custom/_unity/AmazonS3Client.unity.cs:69)

karthiksaligrama commented 8 years ago

kms currently with post object request isnt supported. Because using kms with s3 requires that you use SigV4 signing and currently the unity sdk uses sigv2 signing for postobject request. I'll add this to feature requests

karthiksaligrama commented 8 years ago

I would encourage you to try out the new sdk which has an ability to use PutObject calls and can support kms encryption. If you have any questions please raise an issue on our dotnet sdk repository