as --A- Become someone else =========================== The `as` command can be used to run commands as different users. It should not leak the existence/absence of a user, nor should it leak permissions from the calling user into the effective user. Verification of `as` in the simple case --------------------------------------- In the simple case, `as` is being called by someone who has permission to do so, on behalf of a user which exists and can be used. SCENARIO Default case for as GIVEN a standard instance AND testinstance has keys called other WHEN testinstance, using adminkey, adds user other, using testinstance other AND testinstance adminkey runs as other whoami THEN stdout contains other AND stdout does not contain gitano-admin Another trivial case is that a user without permission tries to run `as`. WHEN testinstance other, expecting failure, runs as other whoami THEN stdout is empty AND stderr contains Ruleset denied action AND stderr contains exit:1 The final trivial case is that a user which can run `as` cannot use it to run `as`. WHEN testinstance adminkey, expecting failure, runs as other as other whoami THEN stdout is empty AND stderr contains Cannot use 'as' to run 'as' AND stderr contains Validation of command line failed AND stderr contains exit:1 FINALLY the instance is torn down Security-related cases for `as` invocation ------------------------------------------ There are a number of security implications for the `as` command. In the simplest of cases it is only necessary to grant gitano-admin members the right to run commands `as` other users. In this way, only those who could otherwise alter the users in the first place can act on their behalf. There is, however, a potential information leak -- namely if someone who does not have the right to run commands 'as' another user runs an `as` with a user which does not exist. It is critical that this simply be reported as a lack of permission to run any command, and not leak that the target user does not exist in any way. SCENARIO Ensuring 'as' does not leak user presence GIVEN a standard instance AND testinstance has keys called other WHEN testinstance, using adminkey, adds user other, using testinstance other AND testinstance adminkey runs as other whoami THEN stderr is empty WHEN testinstance other, expecting failure, runs as badger sshkey list THEN stdout is empty AND stderr does not contain badger Finally we ensure that when a user who may run `as` commands does so, but manages to typo a username, they get a useful error message. WHEN testinstance adminkey, expecting failure, runs as badger whoami THEN stderr contains badger AND stderr contains does not exist AND stderr contains exit:1 AND stdout is empty FINALLY the instance is torn down As well as not leaking information, use of `as` must not thwart auditability, so a user with elevated permissions must not be able to frame another user. SCENARIO Ensuring 'as' does not thwart auditability GIVEN a standard instance AND testinstance has keys called other AND testinstance has keys called sneakybackdoor WHEN testinstance, using adminkey, adds user other, using testinstance other AND testinstance uses their ssh public key called sneakybackdoor as stdin AND testinstance adminkey runs as other sshkey add sneakybackdoor AND server-side gitano-admin reads git object HEAD^{commit} THEN stdout contains Added sneakybackdoor for other AND stdout contains committer Administrator FINALLY the instance is torn down Regression checks ================= When running `as` with commands which consider the keytag during `_prep()` it's essential that `as` resets it to the "<*>" token which is used during `_run()` too. This used not to be the case, making it hard to manage SSH keys of users whose sshkeys had the same names as the keys used by the admin trying to manage them. SCENARIO Ensuring 'as' replaces keytag during '_prep()' GIVEN a standard instance AND testinstance has keys called other AND testinstance has keys called spare WHEN testinstance, using adminkey, adds user other, using testinstance other AND testinstance adminkey runs as other whoami THEN stderr is empty WHEN testinstance uses their ssh public key called spare as stdin AND testinstance other runs sshkey add adminkey AND testinstance adminkey runs as other sshkey del adminkey THEN the output contains SSH authorised key file updated