#user-password #api-server #hyper #env-var #user-login #tls-client #user-events

restapi

默认安全的rest api,使用hyper、tokio、bb8、kafka-threadpool、postgres和prometheus进行监控

26个稳定版本

1.1.14 2022年9月23日
1.1.12 2022年9月22日
1.1.5 2022年8月25日
1.1.3 2022年3月23日

#162 in HTTP服务器

Download history 6/week @ 2024-03-29

71 每月下载次数

MIT 许可证

455KB
8K SLoC

具有用户管理、Kafka消息发布、S3上传/下载和Prometheus监控的Rust Rest API堆栈

默认安全的Rest API,使用hypertokiobb8kafka-threadpool、postgres和prometheus进行监控。

特性

  1. 用户管理和认证存储在postgres
  2. 异步s3上传和下载(从/到本地文件或从/到内存)
  3. 解耦的、异步的kafka线程池,使用环境变量连接到kafka集群,客户端mtls用于身份验证和传输加密
  4. 异步将所有成功用户事件发布到kafka主题(默认主题:user.events)和分区键(默认键:user-{user.id}
  5. 使用自定义kafka主题、分区键和自定义头部的异步kafka消息传递,用于一次性消息。

概述

用户

  • 支持使用存储在postgres中的一次性使用令牌重置用户密码和更改用户电子邮件。
  • 用户可以上传和管理存储在AWS S3上的文件(假设在此Rust项目外部加载了有效的凭证)。
  • 用户密码使用argon2进行散列。

认证

  • 默认启用用户认证
  • 包括在文档中的默认JWT签名密钥,用于根据需要构建新密钥。

数据库

  • rest api服务器使用postgres和bb8客户端线程池
  • postgres数据库要求每个客户端连接包含postgres tls证书授权文件,以加密传输中的数据。
  • 包含用于浏览器中数据库管理的 pgadmin (与 podman compose 部署)。

TLS 加密

  • 包含一个用于构建自签名 TLS 资产的工具(包括您自己的私有证书颁发机构(CA))的 tls 资产生成器工具(./tls/create-tls-assets.sh)。

Ingress

组件 状态
Rest API 服务器 监听tcp端口 3000 上的加密客户端连接
Postgres 监听tcp端口 5432 上的加密客户端连接(需要 TLS 证书颁发机构)
pgAdmin 监听tcp端口 5433 上的加密 HTTP 客户端连接

入门

克隆存储库

git clone https://github.com/jay-johnson/restapi
cd restapi

使用 CFSSL 生成 TLS 资产和私有证书颁发机构(CA)

使用以下命令在 ./tls 目录下生成新的 TLS 资产

cd tls
./create-tls-assets.sh
cd ..

有关更多信息,请参阅 使用 CFSSL 生成 TLS 资产

生成 JWT 私钥和公钥

使用以下命令在 ./jwt 目录下生成新的签名 JWT 键

cd jwt
./recreate-jwt.sh
cd ..

有关更多信息,请参阅 如何为 jsonwebtokens crate 构建JWT私钥和公钥

使用 Podman 部署 Postgres 和 pgAdmin

有关更多信息,请参阅 构建和部署安全 Postgres 后端文档

构建 API 服务器

cargo build --example server

运行 API 服务器

export RUST_BACKTRACE=1 && export RUST_LOG=info,kafka_threadpool=info && ./target/debug/examples/server

环境变量

Rest API

环境变量 默认值
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

用户电子邮件验证

环境变量 默认值
USER_EMAIL_VERIFICATION_REQUIRED "0"
USER_EMAIL_VERIFICATION_ENABLED "1"
USER_EMAIL_VERIFICATION_EXP_IN_SECONDS "2592000"

用户一次性密码验证码过期时间用于密码恢复

环境变量 默认值
USER_OTP_EXP_IN_SECONDS "2592000"

Postgres 数据库

环境变量 默认值
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

Kafka 集群

有关更多信息,请参阅 kafka_threadpool 文档

环境变量 目的 / 价值
KAFKA_PUBLISH_EVENTS 如果设置为 true1 则将所有用户事件发布到 Kafka
KAFKA_ENABLED 使用: true1 切换 kafka_threadpool 开启,否则禁用 threadpool
KAFKA_LOG_LABEL 出现在所有 crate 日志中的跟踪标签
KAFKA_BROKERS 由逗号分隔的代理列表(host1:port,host2:port,host3:port
KAFKA_TOPICS 由逗号分隔的支持主题列表
KAFKA_PUBLISH_RETRY_INTERVAL_SEC 在每次发布重试前休眠的秒数
KAFKA_PUBLISH_IDLE_INTERVAL_SEC 如果没有消息要处理,休眠的秒数
KAFKA_NUM_THREADS threadpool 的线程数
KAFKA_TLS_CLIENT_KEY 可选 - Kafka mTLS密钥的路径(./tls/kafka-cluster-0/client-key.pem)
KAFKA_TLS_CLIENT_CERT 可选 - Kafka mTLS证书的路径(./tls/kafka-cluster-0/client.pem)
KAFKA_TLS_CLIENT_CA 可选 - Kafka mTLS证书颁发机构(CA)的路径(./tls/ca/ca.pem)
KAFKA_METADATA_COUNT_MSG_OFFSETS 可选 - 设置为除true以外的任何值以跳过偏移量的计数

示例kafka.env文件

# 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"

S3

环境变量 默认值
S3_DATA_BUCKET YOUR_BUCKET
S3_DATA_PREFIX /rust-restapi/tests
S3_STORAGE_CLASS STANDARD
S3_DATA_UPLOAD_TO_S3 "0"

JWT

环境变量 默认值
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

Rust

环境变量 默认值
RUST_BACKTRACE "1"
RUST_LOG info

Debug

环境变量 默认值
DEBUG "1"

Docker构建

构建基础镜像

这将使用podman构建一个初始基础镜像。注意:此基础镜像在不同的CPU芯片组上无法工作,因为openssl库是为此基础镜像在镜像内部编译的。

./build-base.sh

构建衍生镜像

通过重用基础镜像,此衍生镜像只需要重新编译服务器。通过最小程度的代码更改,这比基础镜像构建快得多。

./build-derived.sh

Kubernetes

启动Kafka

如果您没有运行的Kafka集群,您可以使用以下方法部署自己的集群

https://github.com/jay-johnson/rust-with-strimzi-kafka-and-tls

Helm图表

将TLS资产部署到Kubernetes

此命令将部署所有jwt密钥、tls资产和凭证到dev命名空间

./deploy-kubernetes-assets.sh -e dev

将Rust Rest API部署到Kubernetes

有关将示例helm图表部署到kubernetes集群的说明,请参阅部署Rust Rest API helm图表到kubernetes指南

默认情况下,这使用jayjohnson/rust-restapi容器镜像

helm upgrade --install -n dev dev-api ./charts/rust-restapi -f ./charts/rust-restapi/values.yaml

监控

Prometheus

本节假设您已经在kubernetes内部运行了一个有效的Prometheus实例。以下是用于监控kubernetes内部rest api部署副本的Prometheus scrape_config。注意,此配置还假设api图表在dev命名空间中运行。

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

支持的API

以下是每个基于url的RequestResponse支持的json合约。每个客户端请求都由./src/handle_requests.rs模块处理,并作为响应返回给客户端(使用serde_json进行序列化)。

用户API

创建用户

为新用户创建单个users记录

更新用户

更新支持的users字段(包括更改用户电子邮件和密码)

获取用户

通过 users.id 获取单个用户 - 默认情况下,用户只能获取自己的账户详情

删除用户

删除单个 users 记录(注意:这不会删除数据库记录,只是将 users.state 设置为非活动状态 1

在数据库中搜索用户

在数据库中搜索匹配的 users 记录

创建一次性密码重置令牌(OTP)

创建一个一次性使用的密码重置令牌,允许用户通过出示令牌来更改其 users.password

消耗一次性密码重置令牌(OTP)

消耗一次性密码并更改用户的 users.password 值为新 argon2-hashed 密码

验证用户的电子邮件

消耗一次性验证令牌并更改用户的 users.verified 值为已验证(1

用户S3 API

将文件异步上传到AWS S3并在数据库中存储跟踪记录

将磁盘上的本地文件异步上传到AWS S3并在 users_data 表中存储跟踪记录。文档称这为 user datauser data file 记录。

更新存储在AWS S3中的现有用户数据文件记录

更新存在于AWS S3中的文件的users_data跟踪记录

从数据库中搜索现有用户数据文件

根据请求的值在users_data数据库中搜索匹配的记录

用户身份验证API

用户登录

登录用户并获取用于后续客户端请求身份验证的JSON Web Token (JWT)

集成测试

本项目专注于v1版本的集成测试,而不是仅限于Rust测试(具体来说,所有内容都使用curl进行了测试)

请参阅使用curl进行集成测试指南

Podman镜像推送

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

依赖项

~40–58MB
~1M SLoC