Is there any way I could setup my plugin to allow user's to connect to their servers from their Moodle account (or their instance of the plugin) via an ssh key? Maybe the user could specify through user input fields in the plugin where their server is? Subsequently connecting via an ssh key?
Re: Allow plugin users to connect to their personal servers via ssh keys
Hi Lloyd,
What exactly do you mean by "connect to their servers from their Moodle account"? Can you give an example use case?
Re: Allow plugin users to connect to their personal servers via ssh keys
Hi Mark, sorry for this slow reply. I've sort of managed to get what I wanted to work.. I created a keypair in the plugin and then displayed the public key under assignment settings for the user to copy over to their authorized_keys files on their server.. this then set up the connection between Moodle (my plugin) and their server. But the problem I have now is how can I only create this keypair once for each user? At the moment I have the keypair being created for each assignment the teacher creates... how can I only create the keypair once for each user? I don't want the teacher having to copy over a new public key over to their server each time they create a new assignment. Thanks, Lloyd.
Re: Allow plugin users to connect to their personal servers via ssh keys
Hi Lloyd,
It sounds like you need to store this keypair (perhaps using digest of each key as a unique ID rather than the full key) in a database table against the student's userid. The plugin can then check if it's already generated a keypair and use the existing one instead of generating a new one. That seems fairly straightforward though, so is there some complexity to the issue that I'm missing?
Re: Allow plugin users to connect to their personal servers via ssh keys
Sorry Mark, I'm quite bad at explaining things what I meant is that the teacher will connect to their server under the assignment settings, where they can copy the public key over to their authorized_keys file on their server to establish the connection. So a bit like you said, I'd like the keypair to be generated only once for each teacher. So for each assignment the teacher will create, they would have the same private and public keys. How can I set this up that each user (teacher) using the plugin will only be given a keypair once?
Re: Allow plugin users to connect to their personal servers via ssh keys
Re: Allow plugin users to connect to their personal servers via ssh keys
Ok that's great, but how would I set this up for each teacher that uses this plugin?
Re: Allow plugin users to connect to their personal servers via ssh keys
Re: Allow plugin users to connect to their personal servers via ssh keys
Re: Allow plugin users to connect to their personal servers via ssh keys
No, you'll want to create a new table that's part of your plugin, probably with the fields id, userid, publickey, privatekey (you might want to store a digest rather than the actual key). You can get the current user's ID from the $USER global.
If you've not created new database tables in Moodle before, you'll want to read up on XMLDB and the Data definition API.
Re: Allow plugin users to connect to their personal servers via ssh keys
Ah yes ok I see, I'll let you know how I get on. Thank you
Re: Allow plugin users to connect to their personal servers via ssh keys
Hi Mark, I followed your advice and documentation you provided and I've successfully created the database table. I'm a bit confused to how I can search the table to see if a record with a specific userid already exists? This is the code I have at the moment but could you advise me on how to search the table and also if the record doesn't exist how I'd correctly insert a new record? I realise the code I have at the moment is practically pseudocode but does the if statement have potential to work like the way I have it now?

Or is this more accurate, using the record_exists function?

Re: Allow plugin users to connect to their personal servers via ssh keys
I seem to have done it! Thanks so much for your guidance. Would you mind checking what I have is correct?
Here is my get_settings function:

Have I setup the if statement correctly? Do i need to specify an else statement also?
And here is my save_settings function:

What would I need to do if the record does exist? As you can see, at the moment I just have an echo statement but could I just if(exists == 0) ?
Re: Allow plugin users to connect to their personal servers via ssh keys
You can just do if ($exists) and if (!$exists) rather than using == 1 and == 0.
In fact, you could just stick the $DB->record_exists() call inside the if () condition to save creating a variable.
Unless there's something else you want to do when a keypair already exists in the save_settings, you don't need a branch for that.
Re: Allow plugin users to connect to their personal servers via ssh keys
Ok thanks for that Mark. Can I ask you.. so after the keys are saved to the database and I try and establish a connection by retrieving the private key from the new table I created like so:

How can I make sure I retrieve the userid of the teacher that created the assignment and not the student currently logged in? At the moment I have it hardcoded to user 2.
Re: Allow plugin users to connect to their personal servers via ssh keys
That's a bit trickier as the user who created an assignment isn't already stored from what I can tell.
I'd suggest having a second event listener that listens for an event like core\event\course_module_created, and have another table where you store the id of the assignment against the id of the corresponding keypair from your first table, if the course module created is as assignment that you're interested in.
Re: Allow plugin users to connect to their personal servers via ssh keys
Sorry Mark I'm quite confused by that. So there wouldn't be a way of doing something like assignment->get_teacher_id() ? Something along those lines....?
Re: Allow plugin users to connect to their personal servers via ssh keys
I had a quick look in the database and this doesn't seem to be stored anywhere. Bear in mind that as far as Moodle's concerned, a "teacher" isn't really a thing, it's just a user who has a certain set of capabilities. You could have several users who can edit a given assignment, and they could have different roles, so calling one the "teacher" for the assignment doesn't make a lot of sense in Moodle terms.
Re: Allow plugin users to connect to their personal servers via ssh keys
Ah yeah you're right, I forgotten about that. Do you think there is a simpler way of achieving this rather than listening for an event etc? Is there a sufficient work around I could do?
Re: Allow plugin users to connect to their personal servers via ssh keys
I wouldn't have suggested you do the event listener if I knew of a simpler way
Re: Allow plugin users to connect to their personal servers via ssh keys
Fair enough Can I ask how will the listening for the event course_module_created be useful? What I mean is how will it give information that will be used to find the user that created the assignment?
Re: Allow plugin users to connect to their personal servers via ssh keys
I'm assuming (I haven't checked) that the event will report the ID of the user who triggered it (i.e. the user who created the assignment), and the ID of the course module that was created. You can then check that the course module is an instance of the assignment module, and do any other checks to make sure it's an assignment that's relevant to this case.
Re: Allow plugin users to connect to their personal servers via ssh keys
Ok I see, so when then the event is triggered the ID of the user that created the assignment would be saved somewhere to be then used in my code that connects to the remote server? Wouldn't the event trigger before the student will make a submission? The event will trigger when the assignment is first created? So how will I be able to use the id in my code that connects to the server?
Re: Allow plugin users to connect to their personal servers via ssh keys
The course_module_created event will be triggered when the assignment (or any other module instance) is created, so you can store the assignment ID against the generated keypair at that point. A different event would be triggered when a user submits an assignment.
Re: Allow plugin users to connect to their personal servers via ssh keys

Re: Allow plugin users to connect to their personal servers via ssh keys
I've just thought of something too... would this event trigger and store details to the database regardless if my plugin was used or not? If the user saves an assignment which doesn't make use of my plugin, a record would be added to the table of the plugin? Would this be avoidable?
Re: Allow plugin users to connect to their personal servers via ssh keys
Those tables look right to me. The moodle convention is to have the primary key field just called "id" rather than e.g. "keypairID", but I don't think that's a hard-and-fast requirement if you prefer not to.
In terms of your other question, if you can determine programmatically whether an assignment that's just been created makes use of your plugin, then you could do this in the event observer to decide whether to record the assignment ID.
One other possibility - in your save_settings function above, you should be able to do $this->assignment to get the assignment that your plugin is being used for. You could create the record in your assignment-keypair linking table with this assignment ID and a null keypair ID, then in your event observer you can check for the existence of the assignment ID in this table to know if it's using your plugin, and fill in the keypair ID if it is.
Re: Allow plugin users to connect to their personal servers via ssh keys
Thanks for all the guidance you gave me, looks like I've done it although possibly in a slightly different way? Basically, when the user (teacher) saves their assignment I firstly save the keys and their userid to the keys table. Then immediately after I retrieve the id (primary key) of the record in the keys table and insert it along with the current assignment ID to the linking table.. Then when the student submits their submission I retrieve the private key of the teacher from the keys table by performing this query:

Does this look correct to you? It seems to work anyway..?
Only thing is though.. when I delete an assignment the record in the linking table remains.. Is there any way I can enforce referential integrity? i.e. when the assignment is deleted the corresponding record in the linking table is also deleted?
Re: Allow plugin users to connect to their personal servers via ssh keys
That seems to make sense. I'm not sure about your second question, you'll have to look if there's some code in submission plugins that runs when the assignment they're linked to is deleted.
Re: Allow plugin users to connect to their personal servers via ssh keys
Ok will do, thanks for that advice Mark. I wanted to ask you too, you said before that I should store a digest of the ssh keypair in the database? what did you mean by that? sorry my knowledge of these things is quite limited. I've read online that maybe I could protect the keys by enabling them to be only usable for certain IP addresses? i.e. if another host tries to connect then it would be denied as it's not on the list of the 'authorised' machines? I don't know if you have any experience on that?
Re: Allow plugin users to connect to their personal servers via ssh keys
What I meant was, assuming that you've got the key stored in a file on the filesystem, you might not want a duplicate of it in the database as that's another place for it to be compromised. However, you could store it's digest (a 1-way hash of the key, Google will tell you more if you're not familiar with this concept) in the database which would give you a unique identifier without storing the key itself.
Re: Allow plugin users to connect to their personal servers via ssh keys
Ahh ok I see, I'm storing the key straight to the database so I guess that reduces the security risk.. I'll look into the hashing now
Re: Allow plugin users to connect to their personal servers via ssh keys
I understand your plan as: Students get assignments for which they need to login to a Unix computer through SSH. The question is how to distribute individual login credentials, which ideally should be the same as their Moodle login. Your Moodle uses its built-in authentication. Am I right?
IMHO the most sustainable solution is to use the same external authentication method https://docs.moodle.org/en/Category:Authentication for both. I know, it is too late for that.
Last time we needed the same thing, we found a very simple solution. The students have "pretty" registration numbers like dnnnnnn (d a letter, n all digits) and use them for login to Moodle. We created shell accounts with the same login and a easy password, which they had to change in their very first assignment. We could have generated a random password and made the script mail it the the student but spared the complications. It was a fast moving course, we just blocked the logins after a certain dead-line.
Re: Allow plugin users to connect to their personal servers via ssh keys
Hi Visvanath, thank you for your comment. Could you see the reply I've given Mark, I've clarified what I meant in the question.