geofront.server — Key management service¶
Although Geofront provides geofront-server, a CLI to run the server, it also provides an interface as a WSGI application as well. Note that there might some limitations like lack of periodical master key renewal.
First of all, the server need a configuration, there are several ways to configure it.
- app.config.from_pyfile()
If you can freely execute arbitrary Python code before start the server, the method is the most straightforward way to configure the server. Note that the argument should be an absolute path, because it interprets paths relative to the path of Geofront program, not the current working directory (CWD).
There also are other methods as well:
- GEOFRONT_CONFIG
If you can’t execute any arbitrary Python code, set the GEOFRONT_CONFIG environment variable. It’s useful when to use a CLI frontend of the WSGI server e.g. gunicorn, waitress-serve.
$ GEOFRONT_CONFIG="/etc/geofront.cfg.py" gunicorn geofront.server:app
Then you can run a Geofront server using your favorite WSGI server. Pass the following WSGI application object to the server. It’s a documented endpoint for WSGI:
- geofront.server.AUTHORIZATION_TIMEOUT = datetime.timedelta(0, 60)¶
(datetime.timedelta) How long does each temporary authorization keep alive after it’s issued. A minute.
- class geofront.server.FingerprintConverter(*args, **kwargs)¶
Werkzeug custom converter which accepts valid public key fingerprints.
- class geofront.server.Token¶
(type) The named tuple type that stores a token.
- expires_at¶
Alias for field number 1
- identity¶
Alias for field number 0
- class geofront.server.TokenIdConverter(*args, **kwargs)¶
Werkzeug custom converter which accepts valid token ids.
- geofront.server.add_public_key(token_id: str)¶
Register a public key to the token. It takes an OpenSSH public key line through the request content body.
POST /tokens/0123456789abcdef/keys/ HTTPS/1.1 Accept: application/json Content-Type: text/plain ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAEMUvjBcX.../MuLLzC/m8Q==
HTTPS/1.1 201 Created Content-Type: text/plain Location: /tokens/0123456789abcdef/keys/50:5a:9a:12:75:8b:b0:88:7d:7a:8d:66:29:63:d0:47 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAEMUvjBcX.../MuLLzC/m8Q==
Parameters: token_id (str) – the token id that holds the identity Status 201: when key registration is successful Status 400: (unsupported-key-type) when the key type is unsupported, or (invalid-key) the key format is invalid, or (deuplicate-key) the key is already used Status 415: (unsupported-content-type) when the Content-Type is not text/plain
- geofront.server.app = <Flask 'geofront.server'>¶
(flask.Flask) The WSGI application of the server.
- geofront.server.authenticate(token_id: str)¶
Finalize the authentication process. It will be shown on web browser.
Parameters: token_id (str) – token id created by create_access_token() Status 400: when authentication is failed Status 404: when the given token_id doesn’t exist Status 403: when the token_id is already finalized Status 200: when authentication is successfully done
Temporarily authorize the token owner to access a remote. A made authorization keeps alive in a minute, and then will be expired.
POST /tokens/0123456789abcdef/remotes/web-1/ HTTPS/1.1 Accept: application/json Content-Length: 0
HTTPS/1.1 200 OK Content-Type: application/json { "success": "authorized", "remote": {"user": "ubuntu", "host": "192.168.0.5", "port": 22}, "expires_at": "2014-04-14T14:57:49.822844+00:00" }
Parameters: Status 200: when successfully granted a temporary authorization
Status 404: (not-found) when there’s no such remote
- geofront.server.create_access_token(token_id: str)¶
Create a new access token.
PUT /tokens/0123456789abcdef/ HTTPS/1.1 Accept: application/json Content-Length: 0
HTTPS/1.1 202 Accepted Content-Type: application/json Date: Tue, 15 Apr 2014 03:44:43 GMT Expires: Tue, 15 Apr 2014 04:14:43 GMT Link: <https://example.com/login/page/?redirect_uri=...>; rel=next { "next_url": "https://example.com/login/page/?redirect_uri=..." }
Parameters: token_id (str) – an arbitrary token id to create. it should be enough random to avoid duplication Status 202: when the access token is prepared Resheader Link: the link owner’s browser should redirect to
- geofront.server.delete_public_key(token_id: str, fingerprint: bytes)¶
Delete a public key.
DELETE /tokens/0123456789abcdef/keys/50:5a:9a:12:75:8b:b0:88:7d:7a:8d:66:29:63:d0:47/ HTTPS/1.1 Accept: application/json
HTTPS/1.1 200 OK Content-Type: application/json { "72:00:60:24:66:e8:2d:4d:2a:2a:a2:0e:7b:7f:fc:af": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCom2CDLekY...5CeYsvSdrTWA5 ", "78:8a:09:c8:c1:24:5c:89:76:92:b0:1e:93:95:5d:48": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA16iSKKjFHOgj...kD62SYXNKY9c= ", "ab:3a:fb:30:44:e3:5e:1e:10:a0:c9:9a:86:f4:67:59": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzzF8c07pzgKk...r+b6Q9VnWWQ== " }
Parameters: - token_id (str) – the token id that holds the identity
- fingerprint (bytes) – the fingerprint of a public key to delete
Status 200: when the public key is successfully deleted
Status 404: (not-found) when there’s no such public key
- geofront.server.get_identity(token_id: str) → geofront.identity.Identity¶
Get the identity object from the given token_id.
Parameters: token_id (str) – the token id to get the identity it holds Returns: the identity the token holds Return type: Identity Raises werkzeug.exceptions.HTTPException: 404 Not Found (token-not-found) when the token does not exist. 412 Precondition Failed (unfinished-authentication) when the authentication process is not finished yet. 410 Gone (expired-token) when the token was expired. 403 Forbidden (not-authorized) when the token is not unauthorized.
- geofront.server.get_key_store() → geofront.keystore.KeyStore¶
Get the configured key store implementation.
Returns: the configured key store Return type: KeyStore Raises RuntimeError: when 'KEY_STORE' is not configured, or it’s not an instance of KeyStore
- geofront.server.get_master_key_store() → geofront.masterkey.MasterKeyStore¶
Get the configured master key store implementation.
Returns: the configured master key store Return type: MasterKeyStore Raises RuntimeError: when 'MASTER_KEY_STORE' is not configured, or it’s not an instance of MasterKeyStore
- geofront.server.get_public_key(token_id: str, fingerprint: bytes) → paramiko.pkey.PKey¶
Internal function to find the public key by its fingerprint.
Parameters: - token_id (str) – the token id that holds the identity
- fingerprint (bytes) – the fingerprint of a public key to find
Returns: the found public key
Return type: Raises werkzeug.exceptions.HTTPException: (not-found) when there’s no such public key
- geofront.server.get_remote_set() → collections.abc.Mapping¶
Get the configured remote set.
Returns: the configured remote set Return type: collections.abc.Mapping Raises RuntimeError: if 'REMOTE_SET' is not configured, or it’s not a mapping object
- geofront.server.get_team() → geofront.team.Team¶
Get the configured team implementation, an instance of team.Team.
It raises RuntimeError if 'TEAM' is not configured.
- geofront.server.get_token_store() → werkzeug.contrib.cache.BaseCache¶
Get the configured token store, an instance of werkzeug.contrib.cache.BaseCache.
It raises RuntimeError if 'TOKEN_STORE' is not configured, but it just warns RuntimeWarning when it comes to debug mode.
Returns: the configured session store Return type: werkzeug.contrib.cache.BaseCache Raises RuntimeError: when 'TOKEN_STORE' is not configured, or the value is not an instance of werkzeug.contrib.cache.BaseCache
- geofront.server.list_public_keys(token_id: str)¶
List registered keys to the token owner.
GET /tokens/0123456789abcdef/keys/ HTTPS/1.1 Accept: application/json
HTTPS/1.1 200 OK Content-Type: application/json { "50:5a:9a:12:75:8b:b0:88:7d:7a:8d:66:29:63:d0:47": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAEMUvjBcX.../MuLLzC/m8Q== ", "72:00:60:24:66:e8:2d:4d:2a:2a:a2:0e:7b:7f:fc:af": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCom2CDLekY...5CeYsvSdrTWA5 ", "78:8a:09:c8:c1:24:5c:89:76:92:b0:1e:93:95:5d:48": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA16iSKKjFHOgj...kD62SYXNKY9c= ", "ab:3a:fb:30:44:e3:5e:1e:10:a0:c9:9a:86:f4:67:59": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzzF8c07pzgKk...r+b6Q9VnWWQ== " }
Parameters: token_id (str) – the token id that holds the identity Status 200: when listing is successful, even if there are no keys
- geofront.server.main()¶
The main function for geofront-server CLI program.
- geofront.server.main_parser() → argparse.ArgumentParser¶
Create an ArgumentParser object for geofront-server CLI program.
Returns: a properly configured ArgumentParser Return type: argparse.ArgumentParser
- geofront.server.master_key(token_id: str)¶
Public part of the master key in OpenSSH authorized_keys (public key) format.
GET /tokens/0123456789abcdef/masterkey/ HTTPS/1.1 Accept: text/plain
HTTPS/1.1 200 OK Content-Type: text/plain ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAEMUvjBcX.../MuLLzC/m8Q==
Parameters: token_id (str) – the token id that holds the identity Status 200: when the master key is available Status 500: when the master key is unavailable
- geofront.server.public_key(token_id: str, fingerprint: bytes)¶
Find the public key by its fingerprint if it’s registered.
GET /tokens/0123456789abcdef/keys/50:5a:9a:12:75:8b:b0:88:7d:7a:8d:66:29:63:d0:47/ HTTPS/1.1 Accept: text/plain
HTTPS/1.1 200 OK Content-Type: text/plain ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAEMUvjBcX.../MuLLzC/m8Q==
Parameters: - token_id (str) – the token id that holds the identity
- fingerprint (bytes) – the fingerprint of a public key to find
Status 200: when the public key is registered
Status 404: (not-found) when there’s no such public key
- geofront.server.remote_dict(remote: geofront.remote.Remote) → collections.abc.Mapping¶
Convert a remote to a simple dictionary that can be serialized to JSON.
Parameters: remote (Remote) – a remote instance to serialize Returns: the converted dictionary Return type: collections.abc.Mapping
- geofront.server.server_version(response: flask.wrappers.Response) → flask.wrappers.Response¶
Indicate the version of Geofront server using Server and X-Geofront-Version headers.
- geofront.server.token(token_id: str)¶
The owner identity that the given token holds if the token is authenticated. Otherwise it responds 403 Forbidden, 404 Not Found, 410 Gone, or 412 Precondition Failed. See also get_identity().
GET /tokens/0123456789abcdef/ HTTPS/1.1 Accept: application/json
HTTPS/1.0 200 OK Content-Type: application/json { "identifier": "dahlia", "team_type": "geofront.backends.github.GitHubOrganization" }
Parameters: token_id (str) – the token id that holds the identity Status 200: when the token is authenticated