Support serializing encrypted secret objects
In memory, we store secrets as deserialized YAML objects, which can be dicts, lists, scalars, or our own custom EncryptedPKCS1_OAEP subclass of YamlObject. We need to be able to serialize a (potentially) encrypted secret in order to transmit it to the executor via ZK. The easiest and most sensible serialization mechanism is to reverse our deserialization and use YAML. This change supports this by indicating that an EncryptedPKCS1_OAEP object is safe to serialize using the SafeDumper. Any time we safe_dump to yaml a Python data structure with an EncryptedPKCS1_OAEP in it, it will be serialized using our custom tag. This also corrects an unrelated parameter name typo in the safe_dump method. Change-Id: I1034946e5261003d9e83119ceee99b89d0dc53a1
This commit is contained in:
parent
819bae3559
commit
707570e46b
|
@ -412,6 +412,7 @@ repo {repo} on branch {branch}. The error was:
|
||||||
class EncryptedPKCS1_OAEP(yaml.YAMLObject):
|
class EncryptedPKCS1_OAEP(yaml.YAMLObject):
|
||||||
yaml_tag = u'!encrypted/pkcs1-oaep'
|
yaml_tag = u'!encrypted/pkcs1-oaep'
|
||||||
yaml_loader = yaml.SafeLoader
|
yaml_loader = yaml.SafeLoader
|
||||||
|
yaml_dumper = yaml.SafeDumper
|
||||||
|
|
||||||
def __init__(self, ciphertext):
|
def __init__(self, ciphertext):
|
||||||
if isinstance(ciphertext, list):
|
if isinstance(ciphertext, list):
|
||||||
|
@ -432,6 +433,16 @@ class EncryptedPKCS1_OAEP(yaml.YAMLObject):
|
||||||
def from_yaml(cls, loader, node):
|
def from_yaml(cls, loader, node):
|
||||||
return cls(node.value)
|
return cls(node.value)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_yaml(cls, dumper, data):
|
||||||
|
ciphertext = data.ciphertext
|
||||||
|
if isinstance(ciphertext, list):
|
||||||
|
ciphertext = [yaml.ScalarNode(value=base64.b64encode(x))
|
||||||
|
for x in ciphertext]
|
||||||
|
else:
|
||||||
|
ciphertext = base64.b64encode(ciphertext)
|
||||||
|
return yaml.ScalarNode(tag=cls.yaml_tag, value=ciphertext)
|
||||||
|
|
||||||
def decrypt(self, private_key):
|
def decrypt(self, private_key):
|
||||||
if isinstance(self.ciphertext, list):
|
if isinstance(self.ciphertext, list):
|
||||||
return ''.join([
|
return ''.join([
|
||||||
|
|
|
@ -9,8 +9,11 @@
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import types
|
||||||
import yaml
|
import yaml
|
||||||
from yaml import YAMLObject, YAMLError # noqa: F401
|
from yaml import ( # noqa: F401
|
||||||
|
YAMLObject, YAMLError, ScalarNode, MappingNode
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Explicit type ignore to deal with provisional import failure
|
# Explicit type ignore to deal with provisional import failure
|
||||||
|
@ -26,9 +29,14 @@ except ImportError:
|
||||||
Mark = yaml.Mark
|
Mark = yaml.Mark
|
||||||
|
|
||||||
|
|
||||||
|
yaml.add_representer(types.MappingProxyType,
|
||||||
|
yaml.representer.SafeRepresenter.represent_dict,
|
||||||
|
Dumper=SafeDumper)
|
||||||
|
|
||||||
|
|
||||||
def safe_load(stream, *args, **kwargs):
|
def safe_load(stream, *args, **kwargs):
|
||||||
return yaml.load(stream, *args, Loader=SafeLoader, **kwargs)
|
return yaml.load(stream, *args, Loader=SafeLoader, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def safe_dump(stream, *args, **kwargs):
|
def safe_dump(data, *args, **kwargs):
|
||||||
return yaml.dump(stream, *args, Dumper=SafeDumper, **kwargs)
|
return yaml.dump(data, *args, Dumper=SafeDumper, **kwargs)
|
||||||
|
|
Loading…
Reference in New Issue