-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create AES128 and AES256 encryption for parameters #4756
Conversation
protected[entity] case class ParameterValue protected[entity] (private val v: JsValue, val init: Boolean) { | ||
protected[entity] case class ParameterValue protected[entity] (private val v: JsValue, | ||
val init: Boolean, | ||
val e: JsValue = JsNull) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just store the encrypted value in v
and a boolean to indicate it's encrypted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding which scheme would allow someone later to migrate from scheme A to B if an issue surfaces in the former.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about something better than e
- secret
, or encrypted
or something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should e
be an option type (which would allow omission) - similarly would it be simpler if when present this value is meaningful (a string or bool and not null).
at this point i'm not sure what values this takes on yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, I went with your suggestion and locked down what the encryption schemes are allowed to do.
Can I get a WIP tag on this PR? |
e1e6e65
to
4e910e2
Compare
8726e0f
to
95f7693
Compare
0b37d1f
to
fea10b9
Compare
0b1d895
to
132fcd6
Compare
Encrypt just before putting into the db Decrypt only right before invoking the action
5c78b26
to
94ff4bd
Compare
Broke reading the kafka protocol into a new method to keep the strict parsing of the scheme intact. Use only base64 encoded keys.
94ff4bd
to
a94b2a8
Compare
Codecov Report
@@ Coverage Diff @@
## master #4756 +/- ##
===========================================
- Coverage 85.1% 43.75% -41.35%
===========================================
Files 190 198 +8
Lines 8578 8987 +409
Branches 601 621 +20
===========================================
- Hits 7300 3932 -3368
- Misses 1278 5055 +3777
Continue to review full report at Codecov.
|
WIP can be removed from this it seems ready to go. |
common/scala/src/main/scala/org/apache/openwhisk/core/entity/Parameter.scala
Show resolved
Hide resolved
case true => Some("init" -> p._2.init.toJson) | ||
case _ => None | ||
} | ||
val encrypt = p._2.encryption match { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a comment what the valid/possible values of encryption are?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some better tests and took your advice to tighten up this field. At first I though this might be where I stuck the IVs or other stuff the encryption scheme wanted to hold on to but I ended up just sticking that inside the raw value given that it's already a byte array.
@@ -129,7 +148,7 @@ protected[core] class Parameters protected[entity] (private val params: Map[Para | |||
|
|||
/** | |||
* A ParameterName is a parameter name for an action or trigger to bind to its environment. | |||
* It wraps a normalized string as a value type. | |||
* It wraps a normalized string as a valueread type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo?
case _ => Some("encryption" -> p._2.encryption.toJson) | ||
} | ||
// Have do use this slightly strange construction to get the json object order identical. | ||
JsObject(ListMap() ++ encrypt ++ init ++ Map("key" -> p._1.name.toJson, "value" -> p._2.value.toJson)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand what's happening here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There were tests which I did not want to alter that checked the order of the values in the JSObject. To keep them working correctly I needed to add each property in a specific way. To my mind those tests shouldn't rely on the ordering of what is really a map but with JSON that is somewhat unclear around the ordering guarantee.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that ordering shouldn't matter in general - without inspecting those tests, I wonder if the tests you're referring to are actually looking at precedence order (which properties should win when there are conflicts between two maps).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I double checked by mixing up the append order and this assert fails: https://github.com/apache/openwhisk/blob/master/tests/src/test/scala/org/apache/openwhisk/core/entity/test/SchemaTests.scala#L708
As it asserts the string equality of the json output. Given that I was hesitant to alter its order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed here 845241a.
protected[entity] case class ParameterValue protected[entity] (private val v: JsValue, val init: Boolean) { | ||
protected[entity] case class ParameterValue protected[entity] (private val v: JsValue, | ||
val init: Boolean, | ||
val e: JsValue = JsNull) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about something better than e
- secret
, or encrypted
or something else?
protected[entity] case class ParameterValue protected[entity] (private val v: JsValue, val init: Boolean) { | ||
protected[entity] case class ParameterValue protected[entity] (private val v: JsValue, | ||
val init: Boolean, | ||
val e: JsValue = JsNull) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should e
be an option type (which would allow omission) - similarly would it be simpler if when present this value is meaningful (a string or bool and not null).
at this point i'm not sure what values this takes on yet.
common/scala/src/main/scala/org/apache/openwhisk/core/entity/ParameterEncryption.scala
Outdated
Show resolved
Hide resolved
common/scala/src/main/scala/org/apache/openwhisk/core/entity/ParameterEncryption.scala
Outdated
Show resolved
Hide resolved
cf4eb47
to
d19ed21
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @mcdan for the clarifications - looking through the rest of the PR and tests.
common/scala/src/main/scala/org/apache/openwhisk/core/entity/Parameter.scala
Show resolved
Hide resolved
case _ => Some("encryption" -> p._2.encryption.toJson) | ||
} | ||
// Have do use this slightly strange construction to get the json object order identical. | ||
JsObject(ListMap() ++ encrypt ++ init ++ Map("key" -> p._1.name.toJson, "value" -> p._2.value.toJson)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree that ordering shouldn't matter in general - without inspecting those tests, I wonder if the tests you're referring to are actually looking at precedence order (which properties should win when there are conflicts between two maps).
d19ed21
to
60033b2
Compare
60033b2
to
115cf1e
Compare
a046bca
to
071671a
Compare
071671a
to
5c5d4a8
Compare
afe184d
to
b60b9e9
Compare
…verted to strings via spray.
use compactPrint + parseJson to convert to/from JSON/String
Not sure why travis isn't updating this but the build is green for this: https://travis-ci.org/apache/openwhisk/builds/646477660 |
Thanks for the nudge. Will review the newest commits. |
No worries we have this running now on our prod cluster now so it's at least working. |
common/scala/src/main/scala/org/apache/openwhisk/core/entity/Parameter.scala
Show resolved
Hide resolved
val byteBuffer = ByteBuffer.wrap(Base64.getDecoder.decode(cipherMessage)) | ||
val ivLength = byteBuffer.getInt | ||
if (ivLength != ivLen) { | ||
throw new IllegalArgumentException("invalid iv length") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decryption occurs in the invoker - this will therefore fail in the container proxy and we should add a test to cover failure and make sure the activation cleans up cleanly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have gone through this PR as careful as I can. Once this PR is merged, I have some enhancements and refactoring which I'll follow up with.
After this PR, when parameter encryption is turned on, the parameters on action update and package update are encrypted using the current scheme. When an action or package is retrieved, the parameters are not decoded
Triggers parameters are currently not locked. This should be considered as a subsequent PR.
response.updated.toEpochMilli should be > dummyUpdated | ||
} | ||
} | ||
// it should "ignore updated field when updating action" in { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this test fail?
@mcdan given that github will reattribute the commit I squash and commit, I defer to you to rebase, and fix up the commit message/merge. |
Encrypt just before putting into the db
Decrypt only right before invoking the action
Description
This will encrypt the default params for actions and packages at rest in the DB.
Currently implemented AES128 and 256 encryption, although 256 needs some work regarding packaging.
Related issue and scope
My changes affect the following components
Types of changes
Checklist: