Crates.io | restapi |
lib.rs | restapi |
version | 1.1.14 |
source | src |
created_at | 2022-03-01 07:54:22.501884 |
updated_at | 2022-09-23 20:18:52.171868 |
description | A secure-by-default rest api using hyper, tokio, bb8, kafka-threadpool, postgres, and prometheus for monitoring |
homepage | https://docs.rs/restapi/latest/restapi/ |
repository | https://github.com/jay-johnson/restapi |
max_upload_size | |
id | 541393 |
size | 527,773 |
A secure-by-default Rest API using hyper, tokio, bb8, kafka-threadpool, postgres, and prometheus for monitoring.
user.events
) and partition key (key default: user-{user.id}
)Component | Status |
---|---|
Rest API Server | Listening for encrypted client connections on tcp port 3000 |
Postgres | Listening for encrypted client connections on tcp port 5432 (tls Certificate Authority required) |
pgAdmin | Listening for encrypted HTTP client connections on tcp port 5433 |
git clone https://github.com/jay-johnson/restapi
cd restapi
Generate new tls assets under the ./tls
directory with these commands:
cd tls
./create-tls-assets.sh
cd ..
Please refer to the Generating TLS Assets with CFSSL for more information.
Generate new signing JWT keys under the ./jwt
directory with these commands:
cd jwt
./recreate-jwt.sh
cd ..
Please refer to the How to build JWT private and public keys for the jsonwebtokens crate doc for more information.
Please refer to the Build and Deploy a Secured Postgres backend doc for more information.
cargo build --example server
export RUST_BACKTRACE=1 && export RUST_LOG=info,kafka_threadpool=info && ./target/debug/examples/server
Environment Variable | Default |
---|---|
SERVER_NAME_API | api |
SERVER_NAME_LABEL | rust-restapi |
API_ENDPOINT | 0.0.0.0:3000 |
API_TLS_DIR | ./tls/api |
API_TLS_CA | ./tls/ca/ca.pem |
API_TLS_CERT | ./tls/api/server.pem |
API_TLS_KEY | ./tls/api/server-key.pem |
Environment Variable | Default |
---|---|
USER_EMAIL_VERIFICATION_REQUIRED | "0" |
USER_EMAIL_VERIFICATION_ENABLED | "1" |
USER_EMAIL_VERIFICATION_EXP_IN_SECONDS | "2592000" |
Environment Variable | Default |
---|---|
USER_OTP_EXP_IN_SECONDS | "2592000" |
Environment Variable | Default |
---|---|
POSTGRES_USERNAME | datawriter |
POSTGRES_PASSWORD | "123321" |
POSTGRES_ENDPOINT | 0.0.0.0:5432 |
POSTGRES_TLS_DIR | ./tls/postgres |
POSTGRES_TLS_CA | ./tls/ca/ca.pem |
POSTGRES_TLS_CERT | ./tls/postgres/client.pem |
POSTGRES_TLS_KEY | ./tls/postgres/client-key.pem |
POSTGRES_DB_CONN_TYPE | postgresql |
Please refer to the kafka_threadpool docs for more information.
Environment Variable | Purpose / Value |
---|---|
KAFKA_PUBLISH_EVENTS | if set to true or 1 publish all user events to kafka |
KAFKA_ENABLED | toggle the kafka_threadpool on with: true or 1 anything else disables the threadpool |
KAFKA_LOG_LABEL | tracking label that shows up in all crate logs |
KAFKA_BROKERS | comma-delimited list of brokers (host1:port,host2:port,host3:port ) |
KAFKA_TOPICS | comma-delimited list of supported topics |
KAFKA_PUBLISH_RETRY_INTERVAL_SEC | number of seconds to sleep before each publish retry |
KAFKA_PUBLISH_IDLE_INTERVAL_SEC | number of seconds to sleep if there are no message to process |
KAFKA_NUM_THREADS | number of threads for the threadpool |
KAFKA_TLS_CLIENT_KEY | optional - path to the kafka mTLS key (./tls/kafka-cluster-0/client-key.pem) |
KAFKA_TLS_CLIENT_CERT | optional - path to the kafka mTLS certificate (./tls/kafka-cluster-0/client.pem) |
KAFKA_TLS_CLIENT_CA | optional - path to the kafka mTLS certificate authority (CA) (./tls/ca/ca.pem) |
KAFKA_METADATA_COUNT_MSG_OFFSETS | optional - set to anything but true to bypass counting the offsets |
# enable the cluster
export KAFKA_ENABLED=1
export KAFKA_LOG_LABEL="ktp"
export KAFKA_BROKERS="host1:port,host2:port,host3:port"
export KAFKA_TOPICS="testing"
export KAFKA_PUBLISH_RETRY_INTERVAL_SEC="1.0"
export KAFKA_NUM_THREADS="5"
export KAFKA_TLS_CLIENT_CA="./tls/ca/ca.pem"
export KAFKA_TLS_CLIENT_CERT="./tls/kafka-cluster-0/client.pem"
export KAFKA_TLS_CLIENT_KEY="./tls/kafka-cluster-0/client-key.pem"
# the KafkaPublisher can count the offsets for each topic with "true" or "1"
export KAFKA_METADATA_COUNT_MSG_OFFSETS="true"
Environment Variable | Default |
---|---|
S3_DATA_BUCKET | YOUR_BUCKET |
S3_DATA_PREFIX | /rust-restapi/tests |
S3_STORAGE_CLASS | STANDARD |
S3_DATA_UPLOAD_TO_S3 | "0" |
Environment Variable | Default |
---|---|
TOKEN_EXPIRATION_SECONDS_INTO_FUTURE | "2592000" |
TOKEN_ORG | example.org |
TOKEN_HEADER | Bearer |
TOKEN_ALGO_PRIVATE_KEY | ./jwt/private-key-pkcs8.pem |
TOKEN_ALGO_PUBLIC_KEY | ./jwt/public-key.pem |
SERVER_PKI_DIR_JWT | ./jwt |
SERVER_PASSWORD_SALT | 78197b60-c950-4339-a52c-053165a04764 |
Environment Variable | Default |
---|---|
RUST_BACKTRACE | "1" |
RUST_LOG | info |
Environment Variable | Default |
---|---|
DEBUG | "1" |
This will build an initial base image using podman. Note: this base image will not work on a different cpu chipset because the openssl libraries are compiled within the image for this base image.
./build-base.sh
By reusing the base image, this derived image only needs to recompile the server. With minimal code changes, this is a much faster build than the base image build.
./build-derived.sh
If you do not have a running Kafka cluster, you can deploy your own with:
https://github.com/jay-johnson/rust-with-strimzi-kafka-and-tls
This command will deploy all jwt keys, tls assets and credentials into the dev
namespace:
./deploy-kubernetes-assets.sh -e dev
Please refer to the Deploying the Rust Rest API helm chart into kubernetes guide for deploying the example helm chart into a kubernetes cluster.
By default this uses the jayjohnson/rust-restapi
container image
helm upgrade --install -n dev dev-api ./charts/rust-restapi -f ./charts/rust-restapi/values.yaml
This section assumes you have a working prometheus instance already running inside kubernetes. Below is the Prometheus scrape_config
to monitor the rest api deployment replica(s) within kubernetes. Note this config also assumes the api chart is running in the dev
namespace:
scrape_configs:
- job_name: rust-restapi
scrape_interval: 10s
scrape_timeout: 5s
metrics_path: /metrics
scheme: https
tls_config:
insecure_skip_verify: true
static_configs:
- targets:
- dev-api.dev.svc.cluster.local:3000
Here are the supported json contracts for each Request
and Response
based off the url. Each client request is handled by the ./src/handle_requests.rs module and returned as a response back to the client (serialization using serde_json
)
Create a single users
record for the new user
/user
POST
Update supported users
fields (including change user email and password)
/user
PUT
Get a single user by users.id
- by default, a user can only get their own account details
/user/USERID
GET
Delete a single users
record (note: this does not delete the db record, just sets the users.state
to inactive 1
)
/user
DELETE
Search for matching users
records in the db
/user/search
POST
Create a one-time-use password reset token that allows a user to change their users.password
value by presenting the token
/user/password/reset
POST
Consume a one-time-use password and change the user's users.password
value to the new argon2-hashed password
/user/password/change
POST
Consume a one-time-use verification token and change the user's users.verified
value verified (1
)
/user/verify
GET
Upload a local file on disk to AWS S3 asynchronously and store a tracking record in the users_data
table. The documentation refers to this as a user data
or user data file
record.
/user/data
POST
Update the users_data
tracking record for a file that exists in AWS S3
/user/data
PUT
Search for matching records in the users_data
db based off the request's values
/user/data/search
POST
Log the user in and get a json web token (jwt) back for authentication on subsequent client requests
/login
POST
This project focused on integration tests for v1 instead of only rust tests (specifically everything has been tested with curl):
Please refer to the Integration Tests Using curl Guide
cur_tag=$(cat Cargo.toml | grep version | head -1 | sed -e 's/"//g' | awk '{print $NF}')
podman tag IMAGE_ID "docker://docker.io/jayjohnson/rust-restapi:${cur_tag}"
podman tag IMAGE_ID "docker://docker.io/jayjohnson/rust-restapi:latest"
podman push "docker.io/jayjohnson/rust-restapi:${cur_tag}"
podman push "docker.io/jayjohnson/rust-restapi:latest"
cargo doc --example server
source ./env/api.env && source ./env/kafka.env && source ./env/postgres.env && cargo build --example server && export RUST_BACKTRACE=1 && export RUST_LOG=info,kafka_threadpool=info,rdkafka=error && ./target/debug/examples/server