I thought it would be nice to have the process of updates, ones manipulating data on the GRIDNET OS decentralized state-machine described in one coherent place.
The trigger for me to describe these mechanics was an update implemented and then broadcasted throughout the network as a result to one of the points (bug-reports by @Alpacalypse ) described in this bug report.
Indeed, let the above referenced case serve us, as an example.
Even though later on it turned out the security never was actually compromised (as explained within the other thread) it is good that we’ve taken care of the matter by assigning explicit security descriptors to all of these files and folder(s).
These are permissions associated with the ‘token_pools’ directory before the update:
In short, the permissions should look the ones associated with the ‘idenity_tokens’ folder, which indicate system-only write access.
Now, let us go through all of the steps comprising the actual ‘update’.
- First, Wizards sit down and implement what is needed. Then, once ready, an update to the GRIDNET Core software is announced through the update-utility. The update is signed and information about it is broadcasted autonomously (through a variance of Kademlia protocol which GRIDNET Core uses for peer-discoveries).
- Nodes download and verify integrity of the update-package. Signature is validated against a public key hard-coded into the software.
- If everything looks good, nodes update and reboot. Those with auto-update turned on.
That would be all for most of the updates.
Updates to the decentralized user interface are to be covered in another post. I shall leave that up to @PauliX . These most-often not even require nodes to be rebooted.
The update at hand it was different though, as it required modification of data residing on the decentralized file-system.
Such updates need be carried out from within of an authenticated code package, signed through a multi-peer-signature. We call this The Overwatch functionality.
- So, new #GridScript word was added to the VM, named ‘update2’. Its source code follows:
/// <summary>
/// File-system security related updated 2.
/// Applies appropriate security descriptors to
/// </summary>
void SE::CScriptEngine::update2()
{
//Local Variables - BEGIN
std::string tokenPoolSysFolderName = "token_pools";
std::string path = "/" + tokenPoolSysFolderName;
std::string domainName = CGlobalSecSettings::getVMSystemDirName();
CStateDomain* systemDomain = nullptr;
CTrieNode* tokenPoolsFolder = nullptr;
std::vector<uint8_t> perspective;
CTrieNode* stub = nullptr;
uint64_t cost;
bool saved = false;
std::shared_ptr<CRightsToken> token = CRightsToken::genSysOnlyDescriptor();
//Local Variables - END
//retrieve the System domain.
//Operational Logic - BEGIN
writeLine(mTools->getColoredString("Comming with an update.. ", eColor::orange));
writeLine(mTools->getColoredString("Looking for '" + path+"'..", eColor::lightWhite));
systemDomain = getStateDomainManager()->findByID(mTools->stringToBytes(domainName));
//check for the presence of the 'Token Pools' directory.
RUNTIME_ERROR_IF(!systemDomain->goToPath(("/"+tokenPoolSysFolderName), &tokenPoolsFolder, nullptr, false), "The "+ tokenPoolSysFolderName+ " was not present. Aborting.");
//apply a proper security descriptor to the very folder.
stub = tokenPoolsFolder->copy();
stub->setParent(nullptr);
stub->setPointerToPointerFromParent(nullptr);
writeLine(mTools->getColoredString("Setting a System-Only security descriptor..", eColor::lightWhite));
RUNTIME_ERROR_IF(!stub->setPermToken(token), "Unable to set the security descriptor for "+ tokenPoolSysFolderName);
saved = systemDomain->saveValueDB(mTools->stringToBytes(stub->getName()), *stub
, eDataType::bytes, perspective, cost, mInSandBoxMode,
false, path, "", false, false, true, true, token, CAccessToken::genSysToken());
delete stub;
RUNTIME_ERROR_IF(!systemDomain->goToPath(("/"+tokenPoolSysFolderName), &tokenPoolsFolder, nullptr, false), "The "+ tokenPoolSysFolderName+ " was not present. Aborting.");
token = tokenPoolsFolder->getPermToken();
RUNTIME_ERROR_IF(!token || !token->getIsSysOnly(), "Updating security descriptor failed!");
writeLine(mTools->getColoredString("Retrieving individual token-pools.. ", eColor::lightWhite));
std::vector<CTrieNode*> members = static_cast<CTrieDB*>(tokenPoolsFolder)->getAllSubLeafNodes();
writeLine(mTools->getColoredString("Altering their security descriptors.. " + path, eColor::lightWhite));
for (int i = 0; i < members.size(); i++)
{
token=CRightsToken::genSysOnlyDescriptor();
stub = members[i]->copy();
stub->setParent(nullptr);
stub->setPointerToPointerFromParent(nullptr);
RUNTIME_ERROR_IF(!stub->setPermToken(token), "Unable to set security descriptor for an internal element. Aborting.");
saved = systemDomain->saveValueDB(mTools->stringToBytes(stub->getName()), *stub
, eDataType::bytes, perspective, cost, mInSandBoxMode,
false, path+"/", "", false, false, true, true, token, CAccessToken::genSysToken());
delete stub;
}
//Operational Logic - END
writeLine("Update maneuvers " + mTools->getColoredString("SUCCEEDED.", eColor::lightGreen));
}
The new #GridScript word was marked as executable only once having acquired Overwatch privileges.
That is indicated by the 14th flag set to ‘true’ above.
Who can acquire Overwatch privileges? Locally, any GRIDNET Operator.
Globally? Only Wizards, after having the matter voted through.
The functionality was introduced to cover for a variety of possible bugs that could be occurring within Test-Net and to mitigate these ASAP once recognized.
Overwatch privileges are checked only once the system executed code in LIVE-mode, so feel free to execute ‘update2’ from the terminal. It would execute but would never affect the storage.
- Then one of us proceeded (ok it was me!
) logged on over SSH as usual, Began a new Thread (BT), executed the ‘update2’ #GridScript code-word and saw the update going through (for now only on the very remote node I was connected to! and in sandbox mode!)
So I typed ‘ct’ (Commit Thread) and the system ask for the usual authorization through a QR-Code.
After a sec, Logs within the Remote Terminal session (press CTRL+W over SSH) clearly indicated that the ‘transaction’ successfully went through.
Yay!
Let us now check the updated security descriptors assigned to the ‘token_pools’ directory:
and to the internal files:
Looking Good!