Module watts_jwt_keys

The purpose of this module is to ensure that the JWT keys are rotated and availeable.

Behaviours: gen_server.

Description

The purpose of this module is to ensure that the JWT keys are rotated and availeable.

The module does

Data Types

key()

key() = #{kty => binary(), n => binary(), e => binary(), d => binary()}

state()

state() = #state{next_key_rotation = integer(), next_key_delete = undefined | pos_integer(), key_file = binary(), key_bits = binary(), info_file = binary()}

Function Index

add_new_key/1*add a new key to the list of keys.
code_change/3code change does nothing.
create_files/1*create the key and the info.
create_or_read_files/2*either create the files or read them.
current_time/0*get the current time in seconds.
delete_oldest_key/0*drop the tail of the list of keys in use, the oldest one.
delete_oldest_key/1*ensure that at least one key is left.
encode_key_value/1*convert an unsigned integer in base64 encoded value.
generate_jwt_key/2*generate a new rsa private key for jwt signing.
handle_call/3handle the calls, only one is supported to perform the inital read.
handle_cast/2handle the casts.
handle_info/2handle the info.
handle_jwt_info_file/1*handle the result of creating the info file.
handle_key_generation_result/2*handle the result of creating the key file and generate info.
handle_read_result/3*handle the results of the reading of the key/info.
init/1initialize the gen_server.
initial_read/0trigger the initial read or generation of the jwt signing key.
initial_read/1*perform the initale read and maybe generation of keys.
maybe_trigger_direct_rotation/1*this triggers a direct rotation after a crash.
maybe_update/1*maybe update the current key setting.
next_key_del/0*calculate the times in seconds of the next key dropping.
next_key_rot/0*calculate the times in seconds of the next key rotation.
perform_update/4*perform the needed updates.
read_files/1*read the key files (key itself and info).
read_jwt_key/1*read the jwt key file.
read_key_info/1*read the info file.
regenerate_or_use_key/3*use the key or regeneratae one:w.
run_openssl/2*run the openssl command to create the key file.
start_link/0start the gen_server linked to the current process.
stop/0stop the gen_server.
terminate/2terminate logs an error on crash.
too_old/1*check if the creation time of the key is too old.
trigger_direct_rotation_if_started/2*this triggers a direct rotation after a crash.
update_delete/1*update the time of next key deletion in the state.
update_rot_del/1*update both, key delete and rotation time.
update_rotation/1*update the time of next key rotation in the state.

Function Details

add_new_key/1 *

add_new_key(NewKey::key()) -> ok

add a new key to the list of keys.

code_change/3

code_change(X1::any(), X2::any(), State::state()) -> {ok, state()}

code change does nothing

create_files/1 *

create_files(State::state()) -> {ok, state()} | {error, state()}

create the key and the info

create_or_read_files/2 *

create_or_read_files(X1::boolean(), State::state()) -> {ok, state()} | {error, state()}

either create the files or read them.

current_time/0 *

current_time() -> integer()

get the current time in seconds.

delete_oldest_key/0 *

delete_oldest_key() -> ok

drop the tail of the list of keys in use, the oldest one.

delete_oldest_key/1 *

delete_oldest_key(Keys::[key()]) -> [key()]

ensure that at least one key is left.

encode_key_value/1 *

encode_key_value(Value::pos_integer()) -> binary()

convert an unsigned integer in base64 encoded value

generate_jwt_key/2 *

generate_jwt_key(KeyFile::binary(), Bits::binary()) -> ok | error

generate a new rsa private key for jwt signing

handle_call/3

handle_call(Request::read_key | any(), From::any(), State::state()) -> {reply, any(), state(), pos_integer()}

handle the calls, only one is supported to perform the inital read. This must always return a timeout to trigger the check.

handle_cast/2

handle_cast(Request::any(), State::state()) -> {noreply, state(), pos_integer()} | {noreply, state()} | {stop, normal, state()}

handle the casts. This is only stopping. This must always return a timeout to trigger the check.

handle_info/2

handle_info(Request::timeout | any(), State::state()) -> {noreply, state(), pos_integer()}

handle the info. This can only be the update check. This must always return a timeout to trigger the check.

handle_jwt_info_file/1 *

handle_jwt_info_file(X1::{ok, binary()} | any()) -> {ok, map()} | {error, atom()}

handle the result of creating the info file.

handle_key_generation_result/2 *

handle_key_generation_result(X1::ok | error, State::state()) -> {ok, state()} | {error, state()}

handle the result of creating the key file and generate info.

handle_read_result/3 *

handle_read_result(X1::{ok, Key::key()} | any(), X2::{ok, #{bits => binary(), generated => integer()}} | any(), State::state()) -> ok | error

handle the results of the reading of the key/info

init/1

init(X1::noparams) -> {ok, state()} | {ok, state(), pos_integer()}

initialize the gen_server. This waits if it has not yet started before, if it has started before it triggers a direct rotation as it has crashed and lost track of time.

initial_read/0

initial_read() -> ok | error

trigger the initial read or generation of the jwt signing key

initial_read/1 *

initial_read(State::state()) -> {ok, state()} | {error, state()}

perform the initale read and maybe generation of keys.

maybe_trigger_direct_rotation/1 *

maybe_trigger_direct_rotation(State::state()) -> {ok, state()} | {ok, state(), pos_integer()}

this triggers a direct rotation after a crash. as through a crash the tack of time is lost, we just assume it is now. so setting the key rotation time to now and setting timeout to 1 ms.

maybe_update/1 *

maybe_update(State::state()) -> {ok, state()}

maybe update the current key setting. Either delete old, unused keys or rotate.

next_key_del/0 *

next_key_del() -> integer()

calculate the times in seconds of the next key dropping.

next_key_rot/0 *

next_key_rot() -> integer()

calculate the times in seconds of the next key rotation.

perform_update/4 *

perform_update(NextDelete::undefined | integer(), NextRotation::undefined | integer(), Now::integer(), State::state()) -> {ok, state()}

perform the needed updates

read_files/1 *

read_files(State::state()) -> {ok, state()} | {error, state()}

read the key files (key itself and info).

read_jwt_key/1 *

read_jwt_key(Path::binary()) -> {ok, key()} | {error, atom()}

read the jwt key file

read_key_info/1 *

read_key_info(Path::binary()) -> {ok, map()} | {error, atom()}

read the info file

regenerate_or_use_key/3 *

regenerate_or_use_key(X1::boolean(), Key::key(), State::state()) -> ok | error | {ok, state()} | {error, state()}

use the key or regeneratae one:w

run_openssl/2 *

run_openssl(KeyFile::binary(), Bits::binary()) -> {ok, any()} | {error, any()}

run the openssl command to create the key file

start_link/0

start_link() -> {ok, pid()}

start the gen_server linked to the current process

stop/0

stop() -> ok

stop the gen_server

terminate/2

terminate(Reason::any(), State::state()) -> ok

terminate logs an error on crash.

too_old/1 *

too_old(GenTime::integer()) -> boolean()

check if the creation time of the key is too old.

trigger_direct_rotation_if_started/2 *

trigger_direct_rotation_if_started(X1::boolean(), BaseState::state()) -> {ok, state()} | {ok, state(), pos_integer()}

this triggers a direct rotation after a crash. as through a crash the tack of time is lost, we just assume it is now. so setting the key rotation time to now and setting timeout to 1 ms.

update_delete/1 *

update_delete(State::state()) -> state()

update the time of next key deletion in the state

update_rot_del/1 *

update_rot_del(State::state()) -> state()

update both, key delete and rotation time.

update_rotation/1 *

update_rotation(State::state()) -> state()

update the time of next key rotation in the state


Generated by EDoc