Authentication#
The majority of ICE ClusterWare ™ API endpoints require that an authentication token is included in
the request. This authentication token usually comes from a call to the login or
token refresh endpoints. There are several authentication options for logging in:
Username / Password authentication. This leverages the operating system's login credentials.
SSH key authentication. This uses a public / private key pair. The private keys must be set inside the ClusterWare software.
Local-socket authentication service. This only works if a user is logged in to the head node where the request is made.
When the login is successful, two JSON Web Tokens (JWTs; see https://jwt.io/) are returned: an access token and a refresh token. The refresh token can be presented to the token-refresh endpoint to make a new access token.
Note
The ClusterWare command-line tools use the access token when possible and will automatically use the refresh token when the access token has expired. Admins writing their own tools will have to detect errors due to token expiration and manually initiate a refresh.
While there are ways to unpack and interpret the data inside a JWT, the tokens can be considered opaque. A client simply receives a JWT upon login and then sends that same JWT inside an authorization header on future requests:
Header: “Authorization: Bearer eyJhbGciOiJIUzI1Ni…”
The access token has an embedded expiration time, which is also sent by the ClusterWare platform during the login process. After that time, the token is rejected by the head node. The refresh token has its own expiration time, usually much longer than the access token. The expectation is that when the access token expires, the refresh token is still valid and can be used to make a new access token.
Note
The refresh token is ONLY usable for making a new access token. It cannot be used to interact with the other endpoints.
In a multi-head cluster, every head node may be configured to use different underlying “secrets” that are used when making new tokens. Thus, after authenticating to one head node, the tokens that are returned may not be usable on other head nodes. In the rare case that a client needs to interact with multiple head nodes, it should login to each one separately and ensure that future requests use the correct token with each corresponding head node.
Where authentication asserts that “this user is who they say they are”, the ClusterWare platform uses role-based access control (RBAC) to limit what specific actions a given user can take. For more information on ClusterWare’s RBAC roles, see Role-Based Access Controls and Role-Based Access Control System.
Caution
As with other token-based authentication systems, if anyone intercepts or acquires a copy of a token, they can fully impersonate the user who created it. Care must be taken to protect the tokens from other users. Consider using OS or file-system based access control mechanisms.
Username/Password Authentication#
The traditional username/password process is provided through a PAM connector. When a login request is made, the system is queried to see if the given username and password are valid. If they are, the ClusterWare platform makes a new token and returns it to the caller.
The data is sent as a JSON object with "user" and "pass" keys:
curl -X POST https://head1.cluster.local/api/v1/login --data '{"user":"admin1", \
"pass":"password"}'
Caution
These example curl commands are interacting with an HTTP endpoint, but they are also available using HTTPS. Further, the examples may show passwords on the command line, but putting a password on the command line is not recommended as it may be visible to other users via ps or similar commands.
The returned value includes the access and refresh tokens, as well as expiration values for both:
{"success": true, "data": {"user": "admin1", "token": {"access_token": \
"eyJhbGciOiJIUzI1Ni…", "expires_in": 1200, "refresh_token": \
"eyJhbGciOiJIUzI1Ni…", "refresh_expires_in": 2592000}}}
The expiration times are in seconds from when the server issued the token. For long-running actions or scripts, admins may want to err on the side of caution and refresh prior to the actual expiration of the access token.
Note
While the head nodes synchronize data amongst themselves, the underlying operating
systems do not synchronize unless configured to do so via some other mechanism.
The head nodes could have their /etc/passwd and /etc/shadow files
synchronized through scp or sftp, or through an external directory system
(LDAP, NIS), but that is outside the scope of this document.
Token Refresh#
The access token can be used in subsequent requests up until the expiration time. Once it has expired, the refresh token can be used to acquire a new access token through the token-refresh endpoint:
curl -X GET https://head1.cluster.local/api/v1/newtoken -H "Authorization: \
Bearer eyJhbGciOiJIUzI1Ni…"
Again, note that this should be the refresh token that is sent to this endpoint – sending an access token will result in a failure.
Upon success, a new set of tokens is returned:
{"success": true, "data": {"authorized_by": "admin1", "userid": "admin1", "uid": \
"735367a122664db8ae8ba3ec113f1643", "token": {"access_token": \
"eyJhbGciOiJIUzI1Ni…", "expires_in": 1200, "refresh_token": \
"eyJhbGciOiJIUzI1Ni…", "refresh_expires_in": 2592000}}}
If the authentication fails, the "success" field will be false and a "reason" field will contain
more information.
Note
The default access token duration is 20 minutes; the default refresh token duration is 30 days.
SSH Key Authentication#
SSH key authentication involves proving possession of the private part of a public/private SSH key pair where the public key has been added to the desired ClusterWare administrator in the usual way:
cw-adminctl -i <username> update keys=@/path/to/key/id_rsa.pub
To prove ownership of the private key, construct a message with the following structure:
{
"user": <username>,
"ssh_auth": {
"timestamp": <timestamp>,
"signatures": [
{
"signature": base64_encode(sign("<username><timestamp>", private_key)),
"key": base64_encode(public_key_bytes),
"key_type": <key_type>
}
]
}
}
Where:
<username> is the name of the administrator you want to authenticate as.
<timestamp> is the value received from an API call to
/cluster/timewithin the last 15 seconds."private_key" is the corresponding private portion of the public key added to the <username> administrator.
"key_type" is the SSH key type, such as
ssh-rsa,ssh-ed25519, or others."public_key_bytes" are the bytes portion of the public key.
The structure should be JSON-serialized and sent in a POST request to the /login API.
The /login API validates the signature and finds the supplied public key in the specified
administrator's key list. If successful, the /login API returns access and refresh tokens.
Note
The timestamp used in the construction of the ssh_auth message expires within 15 seconds
of being retrieved from the /cluster/time API. The message must be constructed and
transmitted before expiration, otherwise a new timestamp must be requested.
One-time Password (OTP)#
Since head nodes are assumed to be “locked down” and protected from end-user access, when a client
is running on the head node they can send an OTP to a known Unix socket and then re-send that OTP
during the login process. The same POST /login endpoint is used, but with “user” and “secret” keys.
If successful, the ClusterWare platform will return a set of access and refresh tokens.
Data Fields#
The /login fields are:
user
Required: The username for login
pass
Optional: The password for this user
ssh_auth
Optional: The ssh_auth token used for SSH-based login
Note
Either pass or ssh_auth must be given.