You're getting "Invalid request provided: AWS::CloudFront::PublicKey" because CloudFront Public Keys are immutable
This is the web page I wish I had found when I spent the afternoon sorting through why AWS CloudFormation kept telling me:
Resource handler returned message: "Invalid request provided: AWS::CloudFront::PublicKey"
Like me, you might be working on a Serverless.com stack and are trying to restrict access to items in an S3 bucket through CloudFront.
You might even be putting the public key text block into a YAML multiline string in an external configuration file and pulling that into your serverless.yml
file.
And you are pulling your hair out because when you run updates on your stack, you get this error.
So in frustration, you blow away the stack and recreate it.
It works fine at first, but soon you are back at that same error above.
Do you want to know why?
An AWS::CloudFront::PublicKey resource is immutable, you idiot. (Me idiot, actually. Hopefully you are fortunate in finding this page early in your quest to solve the problem.)
The clue came from this issue report in the CloudFormation coverage roadmap page:
As mentioned in the API documentation : UpdatePublicKey
UpdatePublicKey action lets you update just the Comment field. The values EncodedKey and Name are immutable, and cannot be updated once created. To update the Key or the Name, a new PublicKey must be created using CreatePublicKey and use it.
The resources section of my serverless.yml
file looks like this:
1 2 3 4 5 6 7 |
|
I'm using Rich Buggy's 'Keeping secrets out of Git' technique to store secrets outside of the serverless.yml
file, so I have a custom section that looks like this:
1 2 3 4 5 |
|
... which reads in this file:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
... and populates the variables you saw in the fragment at the top. (If you've read this far and are interested in how I set up serverless.com projects, check out the blog post I wrote earlier this week on the topic.)
The practical upshot is if any three of those properties need to change—Name
, CallerReference
, or EncodedKey
—what you must do is either:
- Change the name of the resource—
WebsiteDistributionPublicKey
at line 1 in the YAML at the top—in some way (add a letter to the name, remove a letter, etc.) in addition to updating the resource properties, or - Comment out the entire
AWS::CloudFront::PublicKey
resource, deploy (to delete it), uncomment and modify, then deploy again.
As the commenter on the issue mentioned above said, this is not common behavior for other AWS services in CloudFormation. Hopefully, AWS will give us a CloudFormation path that is cleaner than the above two options.