Skip to content

Conversation

@saintentropy
Copy link
Contributor

Purpose

The purpose of this PR is to add a mechanism to allow a common package installation directory similar to the common custom node directly already supported in the PathManager. The common package directly will allow for the installation of packages that are available to all users on a specific machine. This common directory will supplement the current default user package and definitions directories located in user/appdata/...

Declarations

Check these if you believe they are true

  • The codebase is in a better state after this PR
  • Is documented according to the standards
  • The level of testing this PR includes is appropriate
  • User facing strings, if any, are extracted into *.resx files
  • All tests pass using the self-service CI.
  • Snapshot of UI changes, if any.
  • Changes to the API follow Semantic Versioning and are documented in the API Changes document.

Reviewers

@mjkkirschner @QilongTang

FYIs

@sm6srw @Dewb

}
catch
{
throw new Exception(String.Format(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do these exceptions end up in the console only or are they more visible to the user?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know yet. I will test and verify

var cert = asm.Modules.FirstOrDefault()?.GetSignerCertificate();
if (cert != null)
{
var cert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(cert);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you verified this works on linux/mac under mono? .net Core? - if not I wonder if this flow should be disabled if running on non windows platform?

var cert = asm.Modules.FirstOrDefault()?.GetSignerCertificate();
if (cert != null)
{
var cert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(cert);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code seems exactly the same - what am I missing? can't we use the version in dynamo core?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean? That there is similar code here and in the package loading path?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, there's a bunch of duplicate code here that can get out of sync.

discoveredPkg.Name, discoveredPkg.RootDirectory));
}

//Verify teh node libarary has a verified signed certificate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling the

discoveredPkg.Name, discoveredPkg.RootDirectory));
}

discoveredPkg.HasSignedEntryPoints = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what conditions will make this true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You get here when you have looped through each file in the node_libraries and verified it has a cert that is verified. Everywhere else you hit a exception

InitializePackageDirectories(packagesDirectories);
}

public PackageLoader(IEnumerable<string> packagesDirectories, IEnumerable<string> packageDirectoriesToVerify)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a summary for this constructor

InitializePackageDirectories(packagesDirectories);

if (packageDirectoriesToVerify == null)
throw new ArgumentNullException("packageDirectoriesToVerify");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nameof?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean

Copy link
Member

@mjkkirschner mjkkirschner Dec 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use nameof(packageDirectoriesToVerify)

return null;
}

private static void CheckPackageNodeLibraryCertificates(string directory, Package discoveredPkg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a giant method - please add a summary of what it does.

return assemblies;
}

private static bool IsFileInManifestNodeLibraries(IEnumerable<string> nodeLibraries, string filename, string path)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the name of this function.

}
}
catch
{;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dangling semicolon?


private static bool IsFileInManifestNodeLibraries(IEnumerable<string> nodeLibraries, string filename, string path)
{
foreach (var manifestFile in nodeLibraries)
Copy link
Member

@mjkkirschner mjkkirschner Dec 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this name (manifestFile) is confusing to me - what about nodeLibraryAssemblyName?

discoveredPkg.Name, discoveredPkg.RootDirectory));
}

foreach (var manifestFile in discoveredPkg.Header.node_libraries)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same with the name here - unless I am misunderstanding - personally I would get this confused with the manifest file itself - like the header file or the extensionManfiest

Copy link
Contributor

@aparajit-pratap aparajit-pratap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saintentropy could these changes prevent existing packages and extensions to stop loading if they fail the signed certificate checks?

return assemblies;
}

private static bool IsFileInManifestNodeLibraries(IEnumerable<string> nodeLibraries, string filename, string path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this check for the pkg.json file? Should it not be more appropriately named as IsManifestFileInNodeLibraries?


internal List<string> directoriesToVerifyCertificates = new List<string>();

private static bool CheckExtensionCertificates(ExtensionDefinition viewExtension)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the parameter name should simply be extension.

Comment on lines 140 to 159
//Verify the node library exists in the package bin directory
if (!File.Exists(viewExtension.AssemblyPath))
{
throw new Exception(String.Format(
"An extension called {0} found at {1} is missing dlls which are defined in the view extension definition. Ignoring it.",
viewExtension.TypeName, viewExtension.AssemblyPath));
}

//Verify that you can load the node library assembly into a Reflection only context
Assembly asm;
try
{
asm = Assembly.ReflectionOnlyLoadFrom(viewExtension.AssemblyPath);
}
catch
{
throw new Exception(String.Format(
"An extension called {0} found at {1} has a dll which could not be loaded. Ignoring it.",
viewExtension.TypeName, viewExtension.AssemblyPath));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These checks don't seem specific to checking certificates. Can they be moved outside this method?

Assembly asm;
try
{
asm = Assembly.ReflectionOnlyLoadFrom(viewExtension.AssemblyPath);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain why is this check sufficient? Aren't the assembly methods loaded not only for reflection but also for execution?

viewExtension.TypeName, viewExtension.AssemblyPath));
}

//Verify teh node libarary has a verified signed certificate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: the

}

throw new Exception(String.Format(
"A view extension called {0} found at {1} did not have a signed certificate. Ignoring it.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add to string resources.

{
throw new Exception(String.Format(
"A view extension called {0} found at {1} has a dll which could not be loaded. Ignoring it.",
viewExtension.TypeName, viewExtension.AssemblyPath));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add to resx files.

{
throw new Exception(String.Format(
"A view extension called {0} found at {1} is missing dlls which are defined in the view extension definition. Ignoring it.",
viewExtension.TypeName, viewExtension.AssemblyPath));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must be string resource.


throw new Exception(String.Format(
"An extension called {0} found at {1} did not have a signed certificate. Ignoring it.",
viewExtension.TypeName, viewExtension.AssemblyPath));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string resource

[DataMember]
public string TypeName { get; set; }

public bool RequiresSignedEntryPoint { get; internal set; } = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs a summary

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmmmm - does this effect existing extensions and their automatic serialization and deserialization?
Can you show a sample?

Copy link
Member

@mjkkirschner mjkkirschner Dec 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't this seem kind of fragile?... / easily defeat-able

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm... Didn't realize we automatically deserialize. But yes that would be not good

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't ever serialize or deserialize to this class automatically. We had build this class object always. But regardless, this does not have to be a public property. I will move it and the ViewExtension version to internal

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm - I see - Wonder why the dataMember attributes were used.

So you don't intend for this property to be deserialized?

[DataMember]
public string TypeName { get; set; }

public bool RequiresSignedEntryPoint { get; internal set; } = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comments etc

/// </summary>
public PackageUploadRequestBody Header { get; internal set; }

public bool RequiresSignedEntryPoints { get; internal set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to be public? Does this effect the package header? Summary if it needs to be public.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it effects header then we need to consider if this effects package upload/download?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will move this to internal as well

@mjkkirschner
Copy link
Member

@saintentropy the tests look good - but it would be useful to have the source for the dlls in the repo I guess... though I guess we can always decompile them...

@mjkkirschner mjkkirschner added the LGTM Looks good to me label Dec 12, 2019
@saintentropy
Copy link
Contributor Author

I guess I thought the sample packages were in the repo. I just signed the existing package sample

Copy link
Contributor

@QilongTang QilongTang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@QilongTang QilongTang merged commit 717bb16 into DynamoDS:master Dec 12, 2019
@QilongTang QilongTang added this to the 2.5.0 milestone Dec 13, 2019
saintentropy added a commit to saintentropy/Dynamo that referenced this pull request Dec 13, 2019
… definition directory alternative (DynamoDS#10208)

* Add common package folder location similar to common definitions directory to PathManager

* Initalize common package directory

* Add a list of root directories to verify certificates and check those before adding the package

* fix null value check

* Update comments

* Modify package and package loader to only check libraries defined in pkg.json manifest

* Check view extension for valid signed certificate if path matches root to check

* Upate extension loader to validate extension have valid certificate if they are found in directories requiring verification

* Rename package property for to RequiresSignedEntryPoints

* Fix bugs in package loader signed check

* Revise view extension / extension loading logic to avoid ext deff pointing to dll outside of check dir

* Comments

* Package PR comments

* Extension loading pr comments

* View extension pr comments

* On more comment

* Refactor .Net assembly cetificate verication to DynamoCrypto

* Consume validate method from DyanmoCrypto

* Add comments

* Move cert verification method to DynamoUtilities Class

* Add new CertificateVerification class to DynamoUtilities

* Update comments

* Extract package error messages to resource files

* Add comments and change RequiresSignedEntryPoints to internal

* Add test Cases for signed packages

(cherry picked from commit 717bb16)
mjkkirschner pushed a commit that referenced this pull request Dec 13, 2019
* AGD-1300 Add mechanism for common package directory similar to common definition directory alternative (#10208)

* Add common package folder location similar to common definitions directory to PathManager

* Initalize common package directory

* Add a list of root directories to verify certificates and check those before adding the package

* fix null value check

* Update comments

* Modify package and package loader to only check libraries defined in pkg.json manifest

* Check view extension for valid signed certificate if path matches root to check

* Upate extension loader to validate extension have valid certificate if they are found in directories requiring verification

* Rename package property for to RequiresSignedEntryPoints

* Fix bugs in package loader signed check

* Revise view extension / extension loading logic to avoid ext deff pointing to dll outside of check dir

* Comments

* Package PR comments

* Extension loading pr comments

* View extension pr comments

* On more comment

* Refactor .Net assembly cetificate verication to DynamoCrypto

* Consume validate method from DyanmoCrypto

* Add comments

* Move cert verification method to DynamoUtilities Class

* Add new CertificateVerification class to DynamoUtilities

* Update comments

* Extract package error messages to resource files

* Add comments and change RequiresSignedEntryPoints to internal

* Add test Cases for signed packages

(cherry picked from commit 717bb16)

* AGD-1300 Test Followup (#10211)

* Add untitlity test

(cherry picked from commit 2fcd3b5)

* Fix lib tests

(cherry picked from commit 7ae1302)

* Add check to package property

(cherry picked from commit 8e1bc3c)

* Mark test for failure

(cherry picked from commit 32d7a2d)

* Agd-1300 Turn on valid package test (#10213)

* Update the signed package file to uniqure namespace

(cherry picked from commit 0005f38)

* Add comment including the zt node

(cherry picked from commit 16c28de)

* Update comment

(cherry picked from commit 75346ca)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LGTM Looks good to me

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants