-
Notifications
You must be signed in to change notification settings - Fork 4
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
Redesign usage of CDSS with VaultInternal
#305
Comments
Looking into this now. From what I see, However because we have to differentiate destroying the in-memory instance on the on-disk state, then So having both However there is one issue with the This also means the there is a public interface to vaults, and this is returned to the caller of But as we have evolved the design of the vault manager, we also want vaults to be used within a with context, so that transactions can take place during mutation of the vaults. This is more controlled way of manipulating vaults. |
I've also moved in the new RWLock into #266. So that can be used for the vault map as well. |
Currently the The Where to load existing state or not is meant to be automatic, which is to say that The only issue is that during Moving to CDSS, would also mean that the deliberation of All of this means that isogit's functionality will be used in It is possible to move So we may have:
As 2 ways of constructing a vault internal, one is creating it from scratch, which equates it to |
This also means EFS state is considered a dependency for |
I have updated the spec here. any discussion of this aspect of the PR is done here. |
After moving the metadata inside of
So instead of accessing the Alternatively If we feel that the accessing the VaultInternals Metadata directly is needed. We can replicate how the js-encryptedfs works by using the sublevel prefixer method. I will need to explore this some more and test it. |
Because each If you want to know whether a "level" is filled our not. You can use This can return the number of fields in the level. You can use this to know whether a However the VM also needs to be able to look up |
Make sure you're locking these operations though! |
I have a small problem. We want to do all the state creation during
I think option 2 works better here. but can you think of a better option @CMCDragonkai ? |
Do we even need to clear the whole metadata when starting fresh? seems like we can just keep the vault name in the metadata while clearing everything else. |
If You do need to recreate state in Then with |
So we check for permissions when a node receives a pull or clone request. I think this means we should be checking the permissions in the I can see one problem with how the permissions are checked though. To confirm if we have permission for a vault, we provide our Seems like to prove that we can access a vault we only have to provide something akin to a username when we should be using some secret or token instead. Either some proof that we have the access or proof that we are the |
No the But remember you're not taking the |
I think the original idea was that the reverse proxy adds the However the reverse proxy doesn't "understand" GRPC frames atm, so I guess it's not able to do this. Instead, what we had to do to pass the reverse proxy |
Right now our We can create one for |
@tegefaulkes refer to this diagram https://excalidraw.com/#room=57543403694c95eba2e9,5qJFVQlpWc0vegUgEAQIpA which is regarding the session token usage and https://github.com/MatrixAI/js-polykey/wiki/network. It is implemented through the |
I just remembered that these are "client interceptors", they are not interceptors applied on the server side: #296 (comment). GRPC upstream has discussion about adding server interceptors: grpc/grpc-node#419. This is why the Then the solution is to adapt the type ConnectionInfo = {
nodeId: NodeId;
certificates: Array<Certificate>;
egressHost: Host;
egressPort: Port;
ingressHost: Host;
ingressPort: Port;
}; |
@tegefaulkes the discussion about this authentication problem though should be in different/new issue. |
I will create a new issue for this. |
New issue created here #342 |
Do we want to update the locking in |
The same RWLock instance can be shared between VaultManager and VaultInternal. |
If you're going to have 2 locks, then the duties must be separated here: VaultManager RWLock:
Vault RWLock (this is now dependent on the VaultManager RWLock read (these locks can only be held if the read lock is also held)):
This way, any GRPC service handlers or domain methods can still access the vault instance concurrently without blocking each other. And blocking only occurs when you are creating or destroying the vault. This means if any context is holding a |
This is mostly addressed now. Just blocked by #342 |
When checking the permissions for a vault. I think we don't want to reveal the existence of a vault, only that we don't have permissions for a vault that may exist or not. That is to say, when permissions are concerned we should only throw non-existing vault errors after checking and throwing any permission errors. So we should only ever see permission errors if the vault doesn't exist. This will hide the existence of vaults unless a node has permissions. This is assuming that if a vault doesn't exist then no permissions exist for it in the ACL. So I'll need to double check that the ACL/vaultManager is cleaning said permissions when we destroy or refresh vaults. |
Small problem I'll have to look into. It seems that there is no real locking when creating a new Vault. it checks if there is a vault that already exists with that name. However nothing will stop us from concurrently creating two vaults with the same name. That will be a problem. Adding a note to the spec. I think the |
What's what the object map pattern is for, it's supposed to prevent the situation where 2 vaults get created with the same name... etc. |
Problem is, the vaultId is only created during |
A solution to the concurrent vault creation for now is to have a I'll add this into the spec in a moment. |
I'm getting this very odd bug. When creating 3 or more vaults at a time we get an console.log('efs', this.efs[running])
this.efsVault = await this.efs.chroot(this.vaultDataDir);
console.log('efsvault', this.efsVault[running]) We end up with the log
Why is this happening? The efs is running just before we call |
The debugger might help in this case too. |
Currently we have an error called |
This is mostly done for now. Some of the remaining tests require functioning vault mutating and committing. |
Finished up the tests now. |
Specification
CDSS
Currently,
VaultInternal
utilizes the create-destroy pattern. We're considering instead refactoring this into a create-destroy-start-stop pattern. This would allow us to align function usage betweenVaultManager
andVaultInternal
as follows:VaultManager
VaultInternal
createVault
createVaultInternal
openVault
start
closeVault
stop
destroyVault
destroy
The meat of the logic should now be in 2 static methods of
VaultInternal
, representing "smart asynchronous creators" ofVaultInternal
. These should be:creating a
VaultInternal
instance with new or existing state should useVaultInternal.createVaultInternal
. First time cloning of a vault should useVaultInternal.cloneVaultInternal
. Get all the isogit related side-effects (client-side logic) into these static methods, theVaultManager
would only manage any additional metadata.The
start
method now has to setup internal state, specifically Git state, it needs to initialize the repository and also perform the initial commit, however it has to be idempotent, so if these actions are already done, it won't bother with it.The stop cannot
stop
efs, because the EFS lifecycle is handled outside by VaultManagerThe
destroy
should then destroy the Vault internal state, however additional destruction management would have to occur inside the VaultManager which might mean it has to construct (and thus load into-memory) the instance before it can destroy it.The cloning and pulling code should work using
withF
andwithG
as used byNodeConnectionManager
. The cloning and pulling will need to have access to the ACL domain to ensure that permissions are properly set. Because permission checking occurs insideVaultManager
and notVaultInternal
and occurs beforeVaultInternal
functions are executed, this would imply thatVaultManager
has access to the ACL and is bound to the ACL. Which would mean the meat of logic discussed above should be inVaultManager
.Metadata
The
VaultInternal
now needs to maintain its own DB domain to store vault related metadata. 2 new properties are relevant:dirty
- this is a Boolean that determines whether the vault is in a dirty state or notremote
- if this contains a stringnodeId:vaultId
, then this vault should be considered a "remote" vault and must be immutable - see Investigate usage of theremote
field for vault metadata optimisation #309 and No longer preserve vault ID oncloneVault
#253The internal domain is better than storing a POJO in the
VaultManager
. That logic should be removed in favor ofVaultInternal
having it's own internal domain, which is more efficient and more flexible.Additional metadata along with the
dirty
Boolean can be added to enable us to fix #252. This will be important to ensure internal consistency of our vaults in the presence of program crashes and also inadvertent OS shutdowns or just program killing.misc.
The implementations of the functions in
VaultManager
would internally call the respective function above inVaultInternal
. This would also allow us to add any extra functionality that needs to be separate from theVaultInternal
functions into theVaultManager
. For example, on creation of a vault, there's a few factors that need to be considered:VaultInternal
has no notion of the creation/destruction locks used in theObjectMap
structure, so this can be safely handled inVaultManager.createVault
/destroyVault
.Conversely, we should remove any instances where we perform similar logic between the two corresponding functions, and ensure it's centralized in a single place.
Locking will be handled via two
RWLock
locks. One lock for the object map inVaultManager
. The other lock for theVaultInternal
instance. TheVaultManager
RWLock
will handle the life cycle of theVaultInternal
Instance. Write locking will be used for the creation/destroy lifecycle. read locking will be used with theWithVaults
when accessing the vaults. TheVaultInternal
locking will be used for the respectivereadF/G
andwriteF/G
functions.Git repository: anything to do with git instantiation for the vault could also be centralised within
VaultInternal.createVaultInternal
To ensure the integrity of the vaultName information we need to apply locking when reading and writing to the
VaultName
->VaultId
mapping in the database. This is to ensure that when we check if a vaultName already exists in the mapping we can trust that this information is correct and avoid concurrency issues with vault creation and renaming.Additional context
git/utils.ts
for Serving Vault Git Repositories #298, the usage of isogit is mostly client-side behavior. But server side behaviour is facilitated byVaultManager
and functions found insrc/git/utils.ts
.VaultInternal
(fromcommit
to end), as well as some discussion of CDSS withVaultInternal
https://vimeo.com/manage/videos/652700328A note on usage of the CDSS pattern:
create...
: performs the dependency side-effects (i.e. creates any encapsulated dependencies before creating itself). That is, we can see this function as outside the instance of the classstart
: performs the side-effects on the created instance (with the created instance coming from the constructor)tasks
VaultInternal
to using the CDSS async-init pattern.createVaultInternal
constructor for creating aVaultInternal
instance on new or existing state.cloneVaultInternal
constructor for first time cloning of a vault.VaultManager
shouldn't touch isogit at all.start
method handles the creation of any state. This should be idempotent. this also handles anydb
domain creation.destroy
should destroy allVaultInternal
state.NodeConnectionManager
.VaultInternal
dirty
field for tracking if the git repo is in a dirty state.remote
containing stringnodeId:vaultId
for tracking remote node and vault. this is also used to check if the vault is immutable.VaultManager
andVaultInternal
to useRWLock
locks.VaultInternal
lifecycle.VaultInternal
contents.VaultInternal
write/read locking for the read/write functions.VaultManager
git handling functions should be using both read locks.VaultInternal.pullVault
should respect the write lock.vaultName
->vaultId
metadata.VaultManager
object map life-cycle.VaultManager
object map locking.VaultInternal
life-cycle.VaultInternal
locking.VaultInternal.pullVault
lockingThe text was updated successfully, but these errors were encountered: