akas

Crates.ioakas
lib.rsakas
version
sourcesrc
created_at2024-08-23 21:10:05.049673
updated_at2024-12-05 07:17:40.023795
descriptionAKAS: API Key Authorization Server
homepage
repositoryhttps://gitlab.com/op_so/projects/akas
max_upload_size
id1349629
Cargo.toml error:TOML parse error at line 18, column 1 | 18 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include`
size0
FX Soubirou (jfx)

documentation

https://docs.rs/akas

README

AKAS: API Key Authorization Server

Software License semantic-release: angular crates.io Pipeline Status

A simple and higth performance server to authorized HTTP requests by API key checks.

  • A hight performance server written in Rust.
  • In-memory keys storage.
  • Control authorization bearer with pre-checks.
Authorization: Bearer <key>

akas diagram

The file of the list of the keys to be used for authorization should contain one key per line in plain or SHA-256 format:

  • sha256 (default)
8b89600015b273c28f966f368456e45e01df239a36bf939ff72a16881f775679
fb22be500af1ef0479745bbbce847854da33f5e910361ad278e0282995b95f4d
...
  • plain
mykey-3532dceb-f38a-491b-814d-9607bc9a947a
mykey-c2d79a40-388e-4709-9e4b-903035b0e71e
...

akas internal

Usage

$ ./akas --help
A HTTP API key-Based Authorization Server

Usage: akas <COMMAND>

Commands:
  serve  Start the server
  load   Load keys from file
  help   Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

$./akas serve --help
Start the server

Usage: akas serve [OPTIONS]

Options:
      --admin-key <ADMIN_KEY>  Admin key for /load and /status URI [env: AKAS_ADMIN_KEY=] [default: ]
      --no-admin-key           No admin key flag
  -p, --port <PORT>            Port of the server [env: AKAS_PORT=] [default: 5001]
      --log-level <LOG_LEVEL>  Log level <error|warn|info|debug|trace> - default info [env: AKAS_LOG_LEVEL=] [default: info]
      --length <LENGTH>        Length of the key [optional] [env: AKAS_LENGTH=] [default: 0]
      --prefix <PREFIX>        Prefix of the key [optional] [env: AKAS_PREFIX=] [default: ]
  -h, --help                   Print help

Start akas server with the default port 5001

./akas serve --admin-key my-admin-key

Example of configuration of a Nginx server

server {
    listen     80;
    server_name _;

    location / {
      auth_request     /auth;
      auth_request_set $auth_status $upstream_status;
      root             /usr/share/nginx/html;
      index            index.html index.htm;
    }

    location = /auth {
      internal;
      proxy_pass              http://localhost:5001/auth;
      proxy_pass_request_body off;
      proxy_set_header        content-length         "";
      proxy_set_header        x-forwarded-for        $proxy_add_x_forwarded_for;
      proxy_set_header        x-original-host        $host;
      proxy_set_header        x-original-uri         $request_uri;
      proxy_set_header        x-original-remote-addr $remote_addr;
    }
}

More details of Nginx configuration can be found in the configuring subrequest authentication documentation

  • Authorized request: curl -H "Authorization: Bearer <key>" http://<host>/

Endpoints URIs

/auth: Authorization endpoint

If the API key is present in the hashset return 200 OK, otherwise return 401 Unauthorized.

/load

Load new plain/hash keys file and replace the current keys in HashSet. The access is protected by an optional admin key. Example of a curl request:

curl -v \
  -H "Authorization: Bearer my-admin-key" \
  --url http://localhost:5001/load \
  -F 'json={"format": "sha256", "hash_input_file": "43fcba0b3a ..."};type=application/json' \
  -F file=@./tests/files/sha256_key.txt
 Field Description Required Default
file File path of the keys file to upload Yes -
format Format of the keys <sha256|plain> No sha256
hash_input_file sha-256 of the uploaded file No -

If the server is started without an admin key (--no-admin-key), the header Authorization: Bearer is still required with a fake key.

/status

Return the application state in JSON format. The access is protected by an optional admin key. Example:

{
    "log_level": "INFO",
    "file_hash": "43fcba0b3a5ab1b302f9d13617ae4eec6ae623a7fd52437dd992d5dca115e68d",
    "file_date": "2024-11-09T14:07:23.416999558+00:00",
    "file_key_count": 150,
    "length": 42,
    "prefix": "mykey-"
}

Example of request:

curl -v  \
  -H "Authorization: Bearer my-admin-key" \
  http://localhost:5001/status

If the server is started without an admin key (--no-admin-key), the header Authorization: Bearer is still required with a fake key.

/auth-ok

Always return 200 OK without checking the key (mainly for testing purposes).

/auth-unauthorized

Always return 401 Unauthorized without checking the key (for testing purposes or disable access).

Features & Limitations

  • Authorization by HTTP Bearer key.
  • Configuration:
    • via command line arguments.
    • via environment variables.
  • Subcommand serve: Start server
  • Subcommand load: Load file
  • Subcommand status: Get Hash of input file, datetime of load, number of valid keys.
  • load plain keys file (plain text) by curl.
  • load hash keys file (hashed - sha256) by curl.
  • Plain or hashed keys loaded and saved in a Rust HashSet for a fast authorization check.
  • Check of the key format during the loading process of the file based keys storage:
    • prefix and length for plain keys file.
    • SHA-256 for hashed keys file.
  • Initial check of the input key format in the header (length and prefix) [optional].
  • Endpoints:
    • /auth: default endpoint.
    • /load: Load new plain/hash keys file.
    • /status: Get Hash of input file, datetime of load, number of valid keys.
    • /auth-ok: always return 200 OK without checking the key.
    • /auth-unauthorized: always return 401 Unauthorized without checking the key.
  • Admin key in header bearer for /load and /status.
  • Binaries compatibility for Linux with no dependencies:
    • x86-64 and arm64.
    • glibc (debian, ubuntu, fedora...) and musl libc (alpine ...).
  • Tests:
    • Unit tests (Rust).
    • Functional tests (Robot Framework).
  • Gitlab CI/CD Pipeline to auto-publish new versions.
  • Renovate Bot auto-update dependencies.
  • AKAS packaged in a distroless Docker image.
  • Log implemenations with https://crates.io/crates/tracing-actix-web
  • Log requests:
    • All requests: Level Info
    • Only unauthorized requests (401): Level Warn
  • Cache implementation for faster access to key authorization without SHA-256 operation (LRU Cache).

Installation

  • Binary file installation on Linux via the GitLab package registry of the project:

    • 2 architectures:
      • akas-x86_64-linux-<gnu|musl>.tar.gz : x86_64 (Intel, AMD).
      • akas-aarch64-linux-<gnu|musl>.tar.gz : arm64
    • 2 C standard library with no dependencies:
      • akas-<x86_64|aarch64>-linux-gnu.tar.gz : glibc for Debian, Ubuntu, Fedora...
      • akas-<x86_64|aarch64>-linux-musl.tar.gz : musl libc for Alpine
  • With a Rust environment, running this command will globally install the akas binary:

cargo install akas

Log

The level of log is set with the RUST_LOG environment variable:

  • error - Requests are not logged.
  • warn - Only unauthorized requests (401) are logged.
  • info (default) - all requests are logged.
  • debug
  • trace
  • off

Access log default format

2024-11-01T09:26:17.455655Z  WARN HTTP request{http.method=GET http.route=/auth http.flavor=1.1 http.scheme=http http.host=localhost:5001 http.client_ip=127.0.0.1 http.user_agent=curl/7.88.1 http.target=/auth otel.name=GET /auth otel.kind="server" request_id=f8cb807d-666d-457a-957b-26b36ccb1a0f}: akas: sha256_key: f0755926b82353d817f2ca1011fd98179472c2df0fed2225580714d8ad09e336 - unknown-host - unknown-uri - access unauthorized
2024-11-01T09Z:26:20.182590Z  INFO HTTP request{http.method=GET http.route=/auth http.flavor=1.1 http.scheme=http http.host=localhost:5001 http.client_ip=127.0.0.1 http.user_agent=curl/7.88.1 http.target=/auth otel.name=GET /auth otel.kind="server" request_id=97199511-7f08-4ee4-b4fa-71d7e669cfe2}: akas: sha256_key: 92c55f4d88b1 - unknown-host - unknown-uri - access authorized
 Value Description
2024-11-01T09:26:17.455655Z Date and time in ISO 8601 format
WARN Log level
HTTP request{ ... } Request information
akas: Start of the application log message
sha256_key: 92c55f4d1... sha256 key of the user, limited to 12 characters when authorized
unknown-host Extract of x-original-host set by nginx, if not set: unknown-host
unknown-uri Extract of x-original-uri set by nginx, if not set: unknown-uri
access authorized Message

More details:

Development

  • Clone the source repository: git clone https://gitlab.com/op_so/projects/akas.git

  • To format and lint:

cargo fmt  # cargo fmt -- --check
cargo clippy
  • To test:
cargo test
cargo tarpaulin --ignore-tests
cargo audit
  • To run: cargo run -- --file tests/files/plain_key.txt

  • To build:

cargo build            # Debug binary target/debug/akas
cargo build --release  # Release binary target/release/akas

Authors

License

This program is free software: you can redistribute it and/or modify it under the terms of the MIT License (MIT). See the LICENSE for details.

Commit count: 12

cargo fmt