Example #1
0
def test_read_only_write_only_eq():
    """
    By default readOnly and writeOnly are never compared.
    But we should load the correct data from each side (K8S or APPGATE)
    """
    EntityTest4 = load_test_open_api_spec(
        secrets_key=None, reload=True).entities['EntityTest4'].cls
    e_data = {
        'fieldOne': 'writeOnly',
        'fieldTwo': 'readOnly',
    }
    e = APPGATE_LOADER.load(e_data, None, EntityTest4)
    assert e == EntityTest4(fieldOne=None, fieldTwo='readOnly')
    e = APPGATE_LOADER.load(e_data, None, EntityTest4)
    assert e == EntityTest4(fieldOne=None, fieldTwo='----')
    assert e.fieldTwo == 'readOnly'
    assert e.fieldOne is None

    e = K8S_LOADER.load(e_data, None, EntityTest4)
    assert e == EntityTest4(fieldOne='writeOnly', fieldTwo=None)

    e = K8S_LOADER.load(e_data, None, EntityTest4)
    assert e == EntityTest4(fieldOne='-----', fieldTwo=None)
    assert e.fieldOne == 'writeOnly'
    assert e.fieldTwo is None
Example #2
0
def test_compare_entity_with_secrets_with_metadata_1():
    EntityTest2 = load_test_open_api_spec(
        reload=True,
        k8s_get_secret=_k8s_get_secret).entities['EntityTest2'].cls
    data_1 = {
        'fieldOne': {
            'type': 'k8s/secret',
            'name': 'secret-storage-1',
            'key': 'field-one'
        },
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is a field',
    }
    data_2 = {
        'fieldOne': {
            'type': 'k8s/secret',
            'name': 'secret-storage-1',
            'key': 'field-one'
        },
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is a field',
        'created': '2020-09-10T12:20:14Z',
        'updated': '2020-09-10T12:20:14Z'
    }

    appgate_metadata = {
        'generation': 1,
        'latestGeneration': 1,
        'creationTimestamp': '2020-09-10T10:20:14Z',
        'modificationTimestamp': '2020-09-09T12:20:14Z',
    }
    e1 = EntityWrapper(K8S_LOADER.load(data_1, appgate_metadata, EntityTest2))
    e2 = EntityWrapper(APPGATE_LOADER.load(data_2, None, EntityTest2))

    assert e1 == e2

    data_2 = {
        'fieldOne': {
            'type': 'k8s/secret',
            'name': 'secret-storage-1',
            'key': 'field-one'
        },
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is a field different',
        'created': '2020-09-10T12:20:14Z',
        'updated': '2020-09-08T12:20:14Z'
    }
    e3 = EntityWrapper(APPGATE_LOADER.load(data_2, None, EntityTest2))
    assert e1 != e3
Example #3
0
def test_compare_entity_with_secrets():
    """
    If we are missing metadata frm k8s we should always update the entity
    """
    EntityTest2 = load_test_open_api_spec(
        reload=True,
        k8s_get_secret=_k8s_get_secret).entities['EntityTest2'].cls
    data_1 = {
        'fieldOne': {
            'type': 'k8s/secret',
            'name': 'secret-storage-1',
            'key': 'field-one'
        },
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is a field',
    }
    data_2 = {
        'fieldOne': {
            'type': 'k8s/secret',
            'name': 'secret-storage-1',
            'key': 'field-one'
        },
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is a field',
        'created': '2020-09-10T12:20:14Z',
        'updated': '2020-09-10T12:20:14Z'
    }
    e1 = EntityWrapper(K8S_LOADER.load(data_1, None, EntityTest2))
    e2 = EntityWrapper(APPGATE_LOADER.load(data_2, None, EntityTest2))
    assert e1 != e2
Example #4
0
def test_loader_1():
    EntityTest1 = load_test_open_api_spec(
        secrets_key=None, reload=True).entities['EntityTest1'].cls
    entity_1 = {
        'fieldOne': 'this is read only',
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is deprecated',
        'fieldFour': 'this is a field',
        'from': 'this has a weird key name',
    }
    e = APPGATE_LOADER.load(entity_1, None, EntityTest1)
    assert e == EntityTest1(fieldOne='this is read only',
                            fieldTwo=None,
                            fieldFour='this is a field',
                            fromm='this has a weird key name')
    assert e != EntityTest1(fieldOne=None,
                            fieldTwo='this is write only',
                            fieldFour='this is a field that changed')
    assert e.fieldOne == 'this is read only'
    assert e.fieldTwo is None

    e = K8S_LOADER.load(entity_1, None, EntityTest1)
    assert e == EntityTest1(fieldOne=None,
                            fieldTwo='this is write only',
                            fieldFour='this is a field',
                            fromm='this has a weird key name')
    assert e != EntityTest1(fieldOne=None,
                            fieldTwo='this is write only',
                            fieldFour='this is a field that changed',
                            fromm='this has a weird key name')
Example #5
0
def test_write_only_attribute_load():
    EntityTest2 = load_test_open_api_spec(
        secrets_key=None, reload=True).entities['EntityTest2'].cls
    e_data = {
        'fieldOne': '1234567890',
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is a field',
    }
    e = APPGATE_LOADER.load(e_data, None, EntityTest2)
    # writeOnly fields are not loaded from Appgate
    assert e.fieldOne is None
    assert e.fieldTwo is None
    assert e.fieldThree == 'this is a field'
    # writeOnly fields are not compared by default
    assert e == EntityTest2(fieldOne='1234567890',
                            fieldTwo='this is write only',
                            fieldThree='this is a field')

    e = K8S_LOADER.load(e_data, None, EntityTest2)
    # writeOnly fields are loaded from K8S
    assert e.fieldOne == '1234567890'
    assert e.fieldTwo == 'this is write only'
    assert e.fieldThree == 'this is a field'
    # writeOnly fields are not compared by default
    assert e == EntityTest2(fieldOne=None,
                            fieldTwo=None,
                            fieldThree='this is a field')
    assert e.appgate_metadata.passwords == {'fieldOne': '1234567890'}
    assert e.appgate_metadata.password_fields == frozenset({'fieldOne'})
Example #6
0
def test_compare_plan_entity_pem():
    EntityCert = load_test_open_api_spec(
        secrets_key=None, reload=True).entities['EntityCert'].cls
    appgate_data = {
        'name': 'c1',
        'fieldOne': PEM_TEST,
        'fieldTwo': {
            'version': 1,
            'serial': '3578',
            'issuer': join_string(ISSUER),
            'subject': join_string(SUBJECT),
            'validFrom': '2012-08-22T05:26:54.000Z',
            'validTo': '2017-08-21T05:26:54.000Z',
            'fingerprint': 'Xw+1FmWBquZKEBwVg7G+vnToFKkeeooUuh6DXXj26ec=',
            'certificate': join_string(CERTIFICATE_FIELD),
            'subjectPublicKey': join_string(PUBKEY_FIELD),
        }
    }
    k8s_data = {'name': 'c1', 'fieldOne': PEM2}
    current_entities = EntitiesSet(
        {EntityWrapper(APPGATE_LOADER.load(appgate_data, None, EntityCert))})
    new_e = K8S_LOADER.load(k8s_data, None, EntityCert)
    expected_entities = EntitiesSet({EntityWrapper(new_e)})
    plan = compare_entities(current_entities, expected_entities, BUILTIN_TAGS)
    assert plan.modify.entities == frozenset({EntityWrapper(new_e)})
    assert plan.modifications_diff == {
        'c1': [
            '--- \n', '+++ \n', '@@ -3,10 +3,10 @@\n', '     "fieldTwo": {\n',
            '-        "version": 1,\n', '-        "serial": "3578",\n',
            '+        "version": 3,\n', '+        "serial": "0",\n',
            '         "issuer": "[email protected], CN=Frank4DD Web CA, OU=WebCert Support, O=Frank4DD, L=Chuo-ku, ST=Tokyo, C=JP",\n',
            '         "subject": "CN=www.example.com, O=Frank4DD, ST=Tokyo, C=JP",\n',
            '-        "validFrom": "2012-08-22T05:26:54.000Z",\n',
            '-        "validTo": "2017-08-21T05:26:54.000Z",\n',
            '-        "fingerprint": "Xw+1FmWBquZKEBwVg7G+vnToFKkeeooUuh6DXXj26ec=",\n',
            '-        "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNFakNDQVhzQ0FnMzZNQTBHQ1NxR1NJYjNEUUVCQlFVQU1JR2JNUXN3Q1FZRFZRUUdF'
            'd0pLVURFT01Bd0cKQTFVRUNCTUZWRzlyZVc4eEVEQU9CZ05WQkFjVEIwTm9kVzh0YTNVeEVUQVBCZ05WQkFvVENFWnlZVzVyTkVSRQpNUmd3RmdZRFZRUUxFdzlYWldKRFpYS'
            'jBJRk4xY0hCdmNuUXhHREFXQmdOVkJBTVREMFp5WVc1ck5FUkVJRmRsCllpQkRRVEVqTUNFR0NTcUdTSWIzRFFFSkFSWVVjM1Z3Y0c5eWRFQm1jbUZ1YXpSa1pDNWpiMjB3SG'
            'hjTk1USXcKT0RJeU1EVXlOalUwV2hjTk1UY3dPREl4TURVeU5qVTBXakJLTVFzd0NRWURWUVFHRXdKS1VERU9NQXdHQTFVRQpDQXdGVkc5cmVXOHhFVEFQQmdOVkJBb01DRVp'
            '5WVc1ck5FUkVNUmd3RmdZRFZRUUREQTkzZDNjdVpYaGhiWEJzClpTNWpiMjB3WERBTkJna3Foa2lHOXcwQkFRRUZBQU5MQURCSUFrRUFtL3hta0htRVFydXJFLzByZS9qZUZS'
            'TGwKOFpQakJvcDd1TEhobmlhN2xRRy81ekR0WklVQzNSVnBxRFN3QnV3L05Ud2VHeXVQK284QUc5OEh4cXhUQndJRApBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNEdCQUJTM'
            'lRMdUJlVFBtY2FUYVVXL0xDQjJOWU95OEdNZHpSMW14CjhpQkl1Mkg2L0UydGlZM1JJZXZWMk9XNjFxWTIvWFJRZzdZUHh4M2ZmZVV1Z1g5RjRKL2lQbm51MXpBeHh5QnkKMl'
            'ZndUt2NFNXalJGb1JrSWZJbEhYMHFWdmlNaFNsTnkyaW9GTHk3SmNQWmIrdjNmdERHeXdVcWNCaVZEb2VhMApIbitHbXhaQQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",\n',
            '+        "validFrom": "1901-12-13T20:45:52.000Z",\n',
            '+        "validTo": "2038-01-19T03:14:07.000Z",\n',
            '+        "fingerprint": "6b7fb51b56acaf0a8f9b9a3f8ca6737cb97821ddb830106c9fc9a14b8bfdfa36",\n',
            '+        "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNHakNDQVlPZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRVUZBRENCbXpFTE1Ba0dB'
            'MVVFQmhNQ1NsQXgKRGpBTUJnTlZCQWdUQlZSdmEzbHZNUkF3RGdZRFZRUUhFd2REYUhWdkxXdDFNUkV3RHdZRFZRUUtFd2hHY21GdQphelJFUkRFWU1CWUdBMVVFQ3hNUFYyV'
            'mlRMlZ5ZENCVGRYQndiM0owTVJnd0ZnWURWUVFERXc5R2NtRnVhelJFClJDQlhaV0lnUTBFeEl6QWhCZ2txaGtpRzl3MEJDUUVXRkhOMWNIQnZjblJBWm5KaGJtczBaR1F1WT'
            'I5dE1DSVkKRHpFNU1ERXhNakV6TWpBME5UVXlXaGdQTWpBek9EQXhNVGt3TXpFME1EZGFNRW94Q3pBSkJnTlZCQVlUQWtwUQpNUTR3REFZRFZRUUlEQVZVYjJ0NWJ6RVJNQTh'
            'HQTFVRUNnd0lSbkpoYm1zMFJFUXhHREFXQmdOVkJBTU1EM2QzCmR5NWxlR0Z0Y0d4bExtTnZiVEJjTUEwR0NTcUdTSWIzRFFFQkFRVUFBMHNBTUVnQ1FRQ2IvR2FRZVlSQ3U2'
            'c1QKL1N0NytONFZFdVh4aytNR2ludTRzZUdlSnJ1VkFiL25NTzFraFFMZEZXbW9OTEFHN0Q4MVBCNGJLNC82andBYgozd2ZHckZNSEFnTUJBQUV3RFFZSktvWklodmNOQVFFR'
            'kJRQURnWUVBbnpkZVFCRzJjclhudlp5SGdDTDlkU25tCmxuYVhKSVRPLy8rRzU5dUN2REtiblgrQkt2WFh4WFFJYTdHbXR6WXV3M0xDL2pKSkwzMDdyL0NFQ1pyNnZWOUkKS0'
            'huMjcreU90clBET3dURHRYeWFZT2FmOFY2ZmtTVk4zaUx4N3RiRVA2UjB1RUt4YVZhcU1aNzFlZDNTTzFPTAp3cTBqOEdrS1kvSy96bDJOd3pjPQotLS0tLUVORCBDRVJUSUZ'
            'JQ0FURS0tLS0tCg==",\n',
            '         "subjectPublicKey": "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJv8ZpB5hEK7qxP9K3v43hUS5'
            'fGT4waKe7ix4Z4mu5UBv+cw7WSFAt0Vaag0sAbsPzU8Hhsrj/qPABvfB8asUwcCAwEAAQ=="\n'
        ]
    }
Example #7
0
 def entity_client(self, entity: type, api_path: str,
                   singleton: bool) -> EntityClient:
     dumper = APPGATE_DUMPER
     return EntityClient(
         appgate_client=self,
         path=f'/admin/{api_path}',
         singleton=singleton,
         load=lambda d: APPGATE_LOADER.load(d, None, entity),
         dump=lambda e: dumper.dump(e))
Example #8
0
def test_compare_plan_entity_bytes():
    EntityTest3Appgate = load_test_open_api_spec(
        secrets_key=None, reload=True).entities['EntityTest3Appgate'].cls
    # fieldOne is writeOnly :: byte
    # fieldTwo is readOnly :: checksum of fieldOne
    # fieldThree is readOnly :: size of fieldOne
    e_data = {
        'id':
        '6a01c585-c192-475b-b86f-0e632ada6769',  # Current data always has ids
        'name': 'entity1',
        'fieldOne': None,
        'fieldTwo': SHA256_FILE,
        'fieldThree': 1563,
    }
    entities_current = EntitiesSet(
        {EntityWrapper(APPGATE_LOADER.load(e_data, None, EntityTest3Appgate))})
    e_data = {
        'name': 'entity1',
        'fieldOne': BASE64_FILE_W0,
        'fieldTwo': None,
        'fieldThree': None,
    }
    e_metadata = {'uuid': '6a01c585-c192-475b-b86f-0e632ada6769'}
    entities_expected = EntitiesSet({
        EntityWrapper(K8S_LOADER.load(e_data, e_metadata, EntityTest3Appgate))
    })
    plan = compare_entities(entities_current, entities_expected, BUILTIN_TAGS)
    assert plan.modify.entities == frozenset()
    assert plan.modifications_diff == {}

    assert compute_diff(
        list(entities_current.entities)[0],
        list(entities_expected.entities)[0]) == []

    # Let's change the bytes
    e_data = {
        'name': 'entity1',
        'fieldOne': 'Some other content',
        'fieldTwo': None,
        'fieldThree': None,
    }
    new_e = K8S_LOADER.load(e_data, e_metadata, EntityTest3Appgate)

    entities_expected = EntitiesSet({EntityWrapper(new_e)})
    plan = compare_entities(entities_current, entities_expected, BUILTIN_TAGS)
    assert plan.modify.entities == frozenset({EntityWrapper(new_e)})
    assert plan.modifications_diff == {
        'entity1': [
            '--- \n', '+++ \n', '@@ -2,4 +2,4 @@\n',
            '     "name": "entity1",\n',
            '-    "fieldTwo": "0d373afdccb82399b29ba0d6d1a282b4d10d7e70d948257e75c05999f0be9f3e",\n',
            '-    "fieldThree": 1563\n',
            '+    "fieldTwo": "c8f4fc85b689f8f3a70e7024e2bb8c7c8f4f7f9ffd2a1a8d01fc8fba74d1af34",\n',
            '+    "fieldThree": 12\n', ' }'
        ]
    }
Example #9
0
def test_load_entities_v12():
    """
    Read all yaml files in v12 and try to load them according to the kind.
    """
    open_api = generate_api_spec(Path(SPEC_DIR).parent / 'v12')
    entities = open_api.entities
    for f in os.listdir('tests/resources/v12'):
        with (Path('tests/resources/v12') / f).open('r') as f:
            documents = list(yaml.safe_load_all(f))
            for d in documents:
                e = entities[d['kind']].cls
                assert isinstance(APPGATE_LOADER.load(d['spec'], None, e), e)
Example #10
0
def test_appgate_metadata_secrets_dump_from_appgate():
    EntityTest2 = load_test_open_api_spec(
        secrets_key=None, reload=True).entities['EntityTest2'].cls
    e1_data = {
        'fieldThree': 'this is a field',
    }
    e1 = APPGATE_LOADER.load(e1_data, None, EntityTest2)
    e2_data = {
        'fieldThree': 'this is a field',
        'appgate_metadata': {
            'passwordFields': ['fieldOne'],
        }
    }
    d = K8S_DUMPER.dump(e1)
    assert d == e2_data
Example #11
0
def test_write_only_password_attribute_load():
    e_data = {
        'fieldOne': ENCRYPTED_PASSWORD,  # password
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is a field',
    }
    EntityTest2 = load_test_open_api_spec().entities['EntityTest2'].cls

    e = APPGATE_LOADER.load(e_data, None, EntityTest2)
    # writeOnly passwords are not loaded from Appgate
    assert e.fieldOne is None
    assert e.fieldTwo is None
    assert e.fieldThree == 'this is a field'
    assert e.fieldThree == 'this is a field'
    # writeOnly passwords are not compared
    assert e == EntityTest2(fieldOne='wrong-password',
                            fieldTwo='some value',
                            fieldThree='this is a field')
    # normal fields are compared
    assert e != EntityTest2(
        fieldOne=None,
        fieldTwo=None,
        fieldThree='this is a field with a different value')

    # normal writeOnly fields are not compared when compare_secrets is True
    assert e == EntityTest2(fieldOne=None,
                            fieldTwo='some value',
                            fieldThree='this is a field')

    e = K8S_LOADER.load(e_data, None, EntityTest2)
    # writeOnly password fields are loaded from K8S
    assert e.fieldOne == '1234567890'  # decrypted password
    assert e.fieldTwo == 'this is write only'
    assert e.fieldThree == 'this is a field'
    # writeOnly password fields are not compared by default
    assert e == EntityTest2(fieldOne=None,
                            fieldTwo=None,
                            fieldThree='this is a field')
    assert e != EntityTest2(
        fieldOne=None,
        fieldTwo=None,
        fieldThree='this is a field with a different value')
Example #12
0
def test_compare_entities_updated_changed():
    EntityTest2 = load_test_open_api_spec(
        reload=True,
        k8s_get_secret=_k8s_get_secret).entities['EntityTest2'].cls
    data_1 = {
        'fieldOne': {
            'type': 'k8s/secret',
            'name': 'secret-storage-1',
            'key': 'field-one'
        },
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is a field',
    }
    data_2 = {
        'fieldOne': {
            'type': 'k8s/secret',
            'name': 'secret-storage-1',
            'key': 'field-one'
        },
        'fieldTwo': 'this is write only',
        'fieldThree': 'this is a field',
        'created': '2020-09-10T12:20:14Z',
        'updated': '2020-09-10T12:20:14Z'
    }
    appgate_metadata = {
        'generation': 1,
        'latestGeneration': 1,
        'creationTimestamp': '2020-09-10T10:20:14Z',
        'modificationTimestamp': '2020-09-16T12:20:14Z',
    }
    e1 = EntityWrapper(K8S_LOADER.load(data_1, appgate_metadata, EntityTest2))
    e2 = EntityWrapper(APPGATE_LOADER.load(data_2, None, EntityTest2))

    diff = compute_diff(e2, e1)
    assert diff == [
        '--- \n', '+++ \n', '@@ -2,3 +2,3 @@\n',
        '     "fieldThree": "this is a field",\n',
        '-    "updated": "2020-09-10T12:20:14.000Z"\n',
        '+    "updated": "2020-09-16T12:20:14.000Z"\n', ' }'
    ]
Example #13
0
def test_bytes_load():
    EntityTest3 = load_test_open_api_spec(
        secrets_key=None, reload=True).entities['EntityTest3'].cls
    # fieldOne is writeOnly :: byte
    # fieldTwo is readOnly :: checksum of fieldOne
    e_data = {
        'fieldOne': BASE64_FILE_W0,
        'fieldTwo': SHA256_FILE,
    }
    # writeOnly with format bytes is never read from APPGATE
    # readOnly associated as checksum to writeOnly bytes is always read from APPGATE
    e = APPGATE_LOADER.load(e_data, None, EntityTest3)
    assert e.fieldOne is None
    assert e.fieldTwo == SHA256_FILE
    assert e == EntityTest3(fieldTwo=SHA256_FILE)
    # writeOnly bytes is never compared
    assert e == EntityTest3(fieldOne='Some value', fieldTwo=SHA256_FILE)
    # readOnly associated to writeOnly bytes is compared
    assert e != EntityTest3(fieldOne='Some value', fieldTwo='22222')

    e_data = {
        'fieldOne': BASE64_FILE_W0,
        'fieldTwo': None,
    }
    e = K8S_LOADER.load(e_data, None, EntityTest3)
    # When reading from K8S the checksum field associated to bytes is computed
    # by the operator
    assert e.fieldOne == BASE64_FILE_W0
    assert e.fieldTwo == SHA256_FILE
    # We never compare the bytes field itself, only the associated checksum field
    assert e == EntityTest3(fieldOne=None,
                            fieldTwo=SHA256_FILE,
                            fieldThree=SIZE_FILE)
    assert e != EntityTest3(
        fieldOne=BASE64_FILE_W0, fieldTwo='1111111', fieldThree=SIZE_FILE)
    assert e != EntityTest3(
        fieldOne=BASE64_FILE_W0, fieldTwo=SHA256_FILE, fieldThree=666)
Example #14
0
def test_certificate_pem_load():
    EntityCert = load_test_open_api_spec(
        secrets_key=None, reload=True).entities['EntityCert'].cls
    EntityCert_Fieldtwo = load_test_open_api_spec(
        secrets_key=None).entities['EntityCert_Fieldtwo'].cls
    cert = EntityCert_Fieldtwo(
        version=1,
        serial='3578',
        issuer=join_string(ISSUER),
        subject=join_string(SUBJECT),
        validFrom=datetime.datetime(2012,
                                    8,
                                    22,
                                    5,
                                    26,
                                    54,
                                    tzinfo=datetime.timezone.utc),
        validTo=datetime.datetime(2017,
                                  8,
                                  21,
                                  5,
                                  26,
                                  54,
                                  tzinfo=datetime.timezone.utc),
        fingerprint=FINGERPRINT,
        certificate=join_string(CERTIFICATE_FIELD),
        subjectPublicKey=join_string(PUBKEY_FIELD))

    e0_data = {
        'fieldOne': PEM_TEST,
        'fieldTwo': {
            'version': 1,
            'serial': '3578',
            'issuer': join_string(ISSUER),
            'subject': join_string(SUBJECT),
            'validFrom': '2012-08-22T05:26:54.000Z',
            'validTo': '2017-08-21T05:26:54.000Z',
            'fingerprint': FINGERPRINT,
            'certificate': join_string(CERTIFICATE_FIELD),
            'subjectPublicKey': join_string(PUBKEY_FIELD),
        }
    }
    e0 = APPGATE_LOADER.load(e0_data, None, EntityCert)
    assert e0.fieldOne is None
    assert e0.fieldTwo == cert

    e1_data = {
        'fieldOne': PEM_TEST,
    }

    e1 = K8S_LOADER.load(e1_data, None, EntityCert)
    assert e1.fieldOne == PEM_TEST
    assert e1.fieldTwo == cert
    assert e1 == EntityCert(fieldOne='Crap data that is ignored',
                            fieldTwo=cert)
    assert e1 == e0

    cert2 = EntityCert_Fieldtwo(
        version=1,
        serial='3578',
        issuer=join_string(ISSUER),
        subject=join_string(SUBJECT),
        validFrom=datetime.datetime(2017,
                                    3,
                                    6,
                                    16,
                                    50,
                                    58,
                                    516000,
                                    tzinfo=datetime.timezone.utc),
        validTo=datetime.datetime(2025,
                                  3,
                                  6,
                                  16,
                                  50,
                                  58,
                                  516000,
                                  tzinfo=datetime.timezone.utc),
        fingerprint=FINGERPRINT,
        certificate=join_string(CERTIFICATE_FIELD),
        subjectPublicKey=join_string(PUBKEY_FIELD))
    e2 = EntityCert(fieldOne=None, fieldTwo=cert2)
    assert e1 != e2

    e2_dumped = DIFF_DUMPER.dump(e2)
    # Just check that it's dumped properly
    assert e2_dumped['fieldTwo']['validFrom'] == '2017-03-06T16:50:58.516Z'