smartdc-auth
v2.6.0
Published
Triton Authentication Library
Downloads
1,621
Keywords
Readme
Triton Authentication Library
Utility functions to sign http requests to Triton and Manta services.
This library is meant to be used internally by other libraries and tools as in
the triton
and
Manta repositories.
If you only want to use one of these libraries to make requests to a Triton service, you should not need to use this library directly at all.
Its API can be used independently, though, to search for and list the available
SSH keys on the system (used by triton profile create
, for example):
var mod_sdcauth = require('smartdc-auth');
var keyRing = new mod_sdcauth.KeyRing();
keyRing.list(function (err, keyMap) {
if (err) {
/* ... handle err ... */
return;
}
/* The keyMap is an object that maps keyId => [keyPair] */
var keyIds = Object.keys(keyMap);
keyIds.forEach(function (keyId) {
var keys = keyMap[keyId];
console.log('%s:', keyId);
keys.forEach(function (keyPair) {
var key = keyPair.getPublicKey();
console.log(' %s (%d bit): %s',
key.type, key.size, key.comment);
if (keyPair.isLocked())
console.log(' !! password protected');
});
});
});
This might produce the output:
05:6c:c8:0c:83:6c:1e:9a:81:26:fb:52:8e:03:3c:33:
ecdsa (256 bit): [email protected]
!! password protected
2c:be:e8:b1:32:02:31:cd:10:89:f9:96:95:db:11:0c:
rsa (2048 bit): [email protected]
81:ad:d5:57:e5:6f:7d:a2:93:79:56:af:d7:c0:38:51:
ecdsa (256 bit): [email protected]
It can also be used to implement your own http-signature
HTTPS client that
uses the same logic that the triton
and manta
tools do to locate SSH keys:
var mod_sdcauth = require('smartdc-auth');
var mod_sshpk = require('sshpk');
var mod_https = require('https');
var fp = mod_sshpk.parseFingerprint(process.env.TRITON_KEY_ID);
var keyRing = new mod_sdcauth.KeyRing();
keyRing.findSigningKeyPair(fp, function (err, keyPair) {
var signer = keyPair.createRequestSigner({
user: process.env.TRITON_ACCOUNT
});
var opts = {
host: 'localhost',
port: 8443, path: '/', method: 'GET',
headers: {}
};
signer.writeTarget(opts.method, opts.path);
opts.headers.date = signer.writeDateHeader();
signer.sign(function (err, authz) {
opts.headers.authorization = authz;
var req = https.request(opts);
/* ... */
req.end();
});
});
Overview
Authentication to Triton CloudAPI and Manta is built on top of the
http-signature specification.
All requests to the APIs require an HTTP Authorization header where the scheme is
Signature
. Full details are available in the http-signature
specification,
but a simple form is:
Authorization: Signature keyId="/:login/keys/:md5_fingerprint",algorithm="rsa-sha256" $base64_signature
The keyId
field varies in structure when making requests with RBAC subusers,
particularly when doing so in requests made to Manta. In the API reference
below, the term keyId
generally refers specifically to the MD5 fingerprint of
the key in hex format, as used in the field.
Note that this MD5 fingerprint is used only to choose the existing full key on file at the server end out of the ones for the given user and is not used for authentication itself (so the weak hash is not a serious problem).
This library handles the complete process of finding SSH keys based on user
preferences or input, all the way to generating the contents of the
Authorization
header ready for you to use.
The general idea is to create a KeyRing
, then search it for the particular key
pair you want to use. Then you can call methods on the KeyPair
instance like
createRequestSigner()
to sign an HTTP request. You can also access metadata
about the key pair.
API: KeyRing
new mod_sdcauth.KeyRing([options])
Create a new SDC keyring. KeyRing instances use a list of plugins in order to locate keys on the local system - via the filesystem, via the SSH agent, or any other mechanism.
Parameters
options
: an Object containing properties:plugins
: an Array of Strings, names of plugins to enable
Any additional keys set in the options
object will be passed through to
plugins as options for their processing.
Available plugins:
agent
: Gets keys from the OpenSSH agent. Options:sshAgentOpts
: an Object, options to be passed tomod_sshpk_agent.Client
homedir
: Gets keys from a directory on the filesystem. Options:keyDir
: a String, path to look in for keys, defaults to$HOME/.ssh
file
: Gets a key from a particular path on disk. Options:keyPath
: a String, path to the private key file
KeyRing#addPlugin(pluginName[, options])
Adds a plugin to the KeyRing after construction. This is particularly useful
with the file
plugin.
Parameters
pluginName
: a String, name of the plugin to load. One ofagent
,homedir
orfile
options
: an optional Object, options to pass to the plugin. See the documentation above for the class constructor for details.
KeyRing#list(cb)
Lists all available keys in all plugins, organised by their Key ID.
Parameters
cb
: a Function(err, keyPairs)
with parameters:err
: an Error ornull
keyPairs
: an Object, keys: String key IDs, values: Array of instances ofKeyPair
KeyRing#find(fingerprint, cb)
Searches active plugins for an SSH key matching the given fingerprint. Calls
cb
with an array of KeyPair
instances that match, ordered arbitrarily.
Parameters:
fingerprint
: ansshpk.Fingerprint
cb
: a Function(err, keyPairs)
, with parameters:err
: an Error ornull
keyPairs
: an Array ofKeyPair
instances
KeyRing#findSigningKeyPair(fingerprint, cb)
Searches active plugins for an SSH key matching the given fingerprint. Chooses
the best available signing key of those available (preferably unlocked) and
calls cb
with this single KeyPair
instance.
Parameters:
fingerprint
: ansshpk.Fingerprint
cb
: a Function(err, keyPair)
, with parameters:err
: an Error ornull
keyPair
: aKeyPair
instance
KeyPair
KeyPair.fromPrivateKey(privKey)
Constructs a KeyPair unrelated to any keychain, based directly on a given private key. This is mostly useful for compatibility purposes.
Parameters:
privKey
: ansshpk.PrivateKey
KeyPair#plugin
String, name of the plugin through which this KeyPair was found.
KeyPair#source
String (may be undefined
), human-readable name of the source that the KeyPair
came from when discovered (e.g. for a plugin that searches the filesystem, this
could be the path to the key file).
KeyPair#comment
String, comment that was stored with the key, if any.
KeyPair#canSign()
Returns Boolean true
if this key pair is complete (has a private and public
key) and can be used for signing. Note that this returns true
for locked
keys.
KeyPair#isLocked()
Returns Boolean true
if this key pair is locked and may be unlocked using
the unlock()
method.
KeyPair#unlock(passphrase)
Unlocks an encrypted key pair, allowing it to be used for signing and the
getPrivateKey()
method to be called.
Parameters:
passphrase
: a String, passphrase for decryption
KeyPair#getKeyId()
Returns the String key ID for this key pair. This is specifically the key ID as used in HTTP signature auth for SDC and Manta. Currently this is a hex-format MD5 fingerprint of the key, but this may change in future.
KeyPair#getPublicKey()
Returns the sshpk.Key
object representing this pair's public key.
KeyPair#getPrivateKey()
Returns the sshpk.PrivateKey
object representing this pair's private key. If
unavailable, this method will throw an Error
.
KeyPair#createRequestSigner(options)
Creates an http-signature
RequestSigner
object for signing an HTTP request
using this key pair's private key.
Parameters:
options
, an Object with keys:user
, a String, the Triton or Manta account to authenticate as. Note that this field is nameduser
even though it normally refers to an account, for historical reasons.subuser
, an optional String, subuser of the account to authenticate asmantaSubUser
, an optional Boolean, iftrue
use Manta-style subuser syntax
KeyPair#createSign(options)
Creates a sign()
function (matching the legacy smartdc-auth
API) for
signing arbitrary data with this key pair's private key.
Parameters:
options
, an Object with keys:user
, a String, the Triton or Manta account to authenticate as. Note that this field is nameduser
even though it normally refers to an account, for historical reasons.subuser
, an optional String, subuser of the account to authenticate asmantaSubUser
, an optional Boolean, iftrue
use Manta-style subuser syntaxalgorithm
, an optional String, the signing algorithm to use
Legacy request signers
Older SDC and Manta client libraries expose a bit more of the innards of key location and management, and require direct use of this library.
The legacy signer function API is provided for compatibility with users of these
older client libraries. Note that you don't need to use this API for new
software that still wants to be able to use an older client library (you can
just use the createSign()
method on a KeyPair
, above).
These functions take options and return a "signer function" which is provided as
the sign
parameter to other libraries.
privateKeySigner(options);
A basic signer which signs using a given PEM (PKCS#1) format private key only. Ideal for simple use cases where the key is stored in a file on the filesystem ready for use.
options
: an Object containing properties:key
: a String, PEM-format (PKCS#1) private key, for any supported algorithmuser
: a String, SDC login name to be used in the full keyId, abovesubuser
: an optional String, SDC subuser login namekeyId
: optional String, the fingerprint of thekey
(not the same as the full keyId given to the server). Ignored unless it does not match the givenkey
, then an Error will be thrown.
sshAgentSigner(options);
Signs requests using a key that is stored in the OpenSSH agent. Opens and manages a connection to the current session's agent during operation.
options
: an Object containing properties:keyId
: a String, fingerprint of the key to retrieve from the agentuser
: a String, SDC login name to be usedsubuser
: an optional String, SDC subuser login namesshAgentOpts
: an optional Object, any additional options to pass through to the SSHAgent constructor (egtimeout
)
cliSigner(options);
Signs requests using a key located either in the OpenSSH agent, or found in
the filesystem under $HOME/.ssh
(or its equivalent on your platform).
This is generally intended for use with CLI utilities (eg the sdc-listmachines
tool and family), hence the name.
options
: an Object containing properties:keyId
: a String, fingerprint of the key to retrieve or finduser
: a String, SDC login name to be usedsubuser
: an optional String, SDC subuser login namesshAgentOpts
: an optional Object, any additional options to pass through to the SSHAgent constructor (egtimeout
)algorithm
: DEPRECATED, an optional String, the signing algorithm to use. If this does not match up with the algorithm of the key (once it is located), an Error will be thrown.
(The algorithm
option is deprecated as its backwards-compatible behaviour is
to apply only to keys that were found on disk, not in the SSH agent. If you have
a compelling use case for a replacement for this option in future, please open
an issue on this repo).
The keyId
fingerprint does not necessarily need to be the exact format
(hex MD5) as sent to the server -- it can be in any fingerprint format supported
by the sshpk
library.
As of version 2.0.0, an invalid fingerprint (one that can never match any key,
because, for example, it contains invalid characters) will produce an exception
immediately rather than returning a sign
function.
Note that the cliSigner
and sshAgentSigner
are not suitable for server
applications, or any other system where the performance degradation necessary
to interact with SSH is not acceptable; put another way, you should only use
it for interactive tooling, such as the CLI that ships with node-smartdc.
License
MIT.
Bugs
See https://github.com/TritonDataCenter/node-smartdc-auth/issues.