title: S3 with boto, encrypt at rest
body: <p>We're trying to have a fully encrypted bucket in AWS.</p>
  
  <p>We have a key, <code>key = "arn:aws:kms:*****"</code>, a bucketName, <code>bucketName = "MyUniqueBucket"</code> and some json I want to upload &amp; encrypt at rest: <code>payload = { "foo": "bar" }</code></p>
  
  <p>The encryption encforce policy:</p>
  
  <pre><code>policy = {
    "Version": "2012-10-17",
    "Id": "PutObjPolicy",
    "Statement": [{
      "Sid": "DenyUnEncryptedObjectUploads",
       "Effect": "Deny",
       "Principal": "*",
       "Action": "s3:PutObject",
       "Resource": ("arn:aws:s3:::%s/*") % bucketName,
       "Condition": {
          "StringNotEquals": {
             "s3:x-amz-server-side-encryption":"aws:kms"
          }
        }
      }
    ]
  }
  </code></pre>
  
  <p>Now with <code>boto</code> we connect to <code>eu-west-1</code>:</p>
  
  <pre><code>def get_bucket():
    conn = s3.connect_to_region("eu-west-1")
    try:
      return conn.get_bucket(bucketName)
    except S3ResponseError:
      return conn.create_bucket(bucketName, location=Location.EU)
  </code></pre>
  
  <p>With the bucket we now want to set that policy:</p>
  
  <pre><code>bucket = get_bucket()
  bucket.set_policy(json.dumps(policy))
  </code></pre>
  
  <p>Now next up I want to upload a file and encrypt it with my security key (to enable rotation, as the default master key doesn't allow that). </p>
  
  <pre><code>headers = {
    "x-amz-server-side-encryption-aws-kms-key-id": key,
    "x-amz-server-side-encryption" : "aws:kms"
  }
  
  bucketKey = Key(bucket, "fileName.json")
  bucketKey.set_metadata("Content-Type", "application/json")
  bucketKey.set_contents_from_string(json.dumps(payload), headers = headers)
  </code></pre>
  
  <p>However it raises an error:</p>
  
  <pre><code>&lt;Message&gt;The request signature we calculated does not match the signature you provided. Check your key and signing method.&lt;/Message&gt;
  </code></pre>
  
  <p>What I've checked:</p>
  
  <p>I have rights to use the key
  I am connected with v4 signature
  I can upload in a bucket without encryption
  I can upload with headers set for encryption without my own custom key (i.e. use the default key) (notice that gives the MD5 vs ETAG problem).</p>
  
  <p><strong>But I must be doing something wrong with passing the key because it doesn't matter whether it's disabled or not. It still gives the signature error</strong></p>
  
  <p>Anything I'm missing? </p>