Add authentication #1

Merged
hannaeko merged 11 commits from feature/auth into master 2021-04-03 17:54:16 +02:00
15 changed files with 324 additions and 2 deletions
Showing only changes of commit 84b1ce0823 - Show all commits

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/target
config.toml
db.sqlite

154
Cargo.lock generated
View File

@ -244,6 +244,41 @@ dependencies = [
"syn 0.15.44",
]
[[package]]
name = "diesel"
version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "047bfc4d5c3bd2ef6ca6f981941046113524b9a9f9a7cbdfdd7ff40f58e6f542"
dependencies = [
"byteorder",
"diesel_derives",
"libsqlite3-sys",
"r2d2",
]
[[package]]
name = "diesel-derive-enum"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703e71c268ea2d8da9c0ab0b40d8b217179ee622209c170875d24443193a0dfb"
dependencies = [
"heck",
"proc-macro2 1.0.24",
"quote 1.0.9",
"syn 1.0.64",
]
[[package]]
name = "diesel_derives"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.9",
"syn 1.0.64",
]
[[package]]
name = "digest"
version = "0.9.0"
@ -526,6 +561,15 @@ dependencies = [
"libc",
]
[[package]]
name = "instant"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "iovec"
version = "0.1.4"
@ -581,6 +625,25 @@ version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae"
[[package]]
name = "libsqlite3-sys"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64d31059f22935e6c31830db5249ba2b7ecd54fd73a9909286f0a67aa55c2fbd"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]]
name = "lock_api"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.3.9"
@ -711,6 +774,8 @@ name = "nomilo"
version = "0.1.0-dev"
dependencies = [
"base64 0.13.0",
"diesel",
"diesel-derive-enum",
"rocket",
"rocket_contrib",
"serde",
@ -718,6 +783,7 @@ dependencies = [
"toml 0.5.8",
"trust-dns-client",
"trust-dns-proto",
"uuid",
]
[[package]]
@ -782,6 +848,31 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "parking_lot"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
dependencies = [
"cfg-if 1.0.0",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi 0.3.9",
]
[[package]]
name = "pear"
version = "0.1.4"
@ -828,6 +919,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "polyval"
version = "0.4.5"
@ -881,6 +978,17 @@ dependencies = [
"proc-macro2 1.0.24",
]
[[package]]
name = "r2d2"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f"
dependencies = [
"log 0.4.14",
"parking_lot",
"scheduled-thread-pool",
]
[[package]]
name = "radix_trie"
version = "0.2.1"
@ -982,13 +1090,28 @@ version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7954a707f9ca18aa74ca8c1f5d1f900f52a4dceb68e96e3112143f759cfd20e"
dependencies = [
"diesel",
"log 0.4.14",
"notify",
"r2d2",
"rocket",
"rocket_contrib_codegen",
"serde",
"serde_json",
]
[[package]]
name = "rocket_contrib_codegen"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30deb6dec53b91fac3538a2a3935cf13e0f462745f9f33bf27bedffbe7265b5d"
dependencies = [
"devise",
"quote 0.6.13",
"version_check 0.9.3",
"yansi",
]
[[package]]
name = "rocket_http"
version = "0.4.7"
@ -1027,6 +1150,21 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scheduled-thread-pool"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7"
dependencies = [
"parking_lot",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.124"
@ -1345,6 +1483,22 @@ dependencies = [
"percent-encoding 2.1.0",
]
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom",
"serde",
]
[[package]]
name = "vcpkg"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
[[package]]
name = "version_check"
version = "0.1.5"

View File

@ -12,6 +12,9 @@ trust-dns-proto = "0.20.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rocket = "0.4.7"
rocket_contrib = { version = "0.4", default-features = false, features = ["json"]}
rocket_contrib = { version = "0.4", default-features = false, features = ["json", "diesel_sqlite_pool"]}
toml = "0.5"
base64 = "0.13.0"
uuid = { version = "0.8.2", features = ["v4", "serde"] }
diesel = { version = "1.4", features = ["sqlite"] }
diesel-derive-enum = { version = "1", features = ["sqlite"] }

2
Rocket.toml Normal file
View File

@ -0,0 +1,2 @@
[global.databases]
db = { url = "db.sqlite" }

5
diesel.toml Normal file
View File

@ -0,0 +1,5 @@
# For documentation on how to configure this file,
# see diesel.rs/guides/configuring-diesel-cli
[print_schema]
file = "src/schema.rs"

0
migrations/.gitkeep Normal file
View File

View File

@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
DROP TABLE localuser;
DROP TABLE user;

View File

@ -0,0 +1,12 @@
-- Your SQL goes here
CREATE TABLE localuser (
user_id VARCHAR NOT NULL PRIMARY KEY,
username VARCHAR NOT NULL,
password VARCHAR NOT NULL,
FOREIGN KEY(user_id) REFERENCES user(id)
);
CREATE TABLE user (
id VARCHAR NOT NULL PRIMARY KEY,
role VARCHAR NOT NULL
);

2
src/auth/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod providers;
pub mod routes;

12
src/auth/providers.rs Normal file
View File

@ -0,0 +1,12 @@
// enum Providers {
// Ldap(LdapProvider),
// Local(LocalProvider),
// }
// struct LdapProvider {
// user_filter: String,
// group_filter: String,
// // ...
// }
// struct LocalProvider;

44
src/auth/routes.rs Normal file
View File

@ -0,0 +1,44 @@
use serde::{Serialize, Deserialize};
use rocket_contrib::json::Json;
use diesel::prelude::*;
use crate::DbConn;
use crate::models::users::{UserInfo, LocalUser, User};
#[derive(Debug, Serialize, Deserialize)]
struct AuthClaims {
jti: String,
sub: String,
exp: usize,
iat: usize,
}
#[derive(Debug, Serialize)]
pub struct AuthTokenResponse {
token: String
}
#[derive(Debug, Deserialize)]
pub struct AuthTokenRequest {
user: String,
password: String,
}
#[post("/users/me/token", data = "<auth_request>")]
pub fn create_auth_token(conn: DbConn, auth_request: Json<AuthTokenRequest>) -> Json<AuthTokenResponse> {
use crate::schema::localuser::dsl::*;
use crate::schema::user::dsl::*;
let client_user: Result<(User, LocalUser), _> = user.inner_join(localuser).filter(username.eq(&auth_request.user)).get_result(&*conn);
println!("{:?}", client_user);
Json(AuthTokenResponse { token: "".into() })
}
/*
GET /users -> list all users
POST /users
{
provider: local
...
}
/users/<uuid or me>/
*/

View File

@ -1,9 +1,16 @@
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] extern crate rocket;
#[macro_use] extern crate rocket_contrib;
#[macro_use] extern crate diesel;
use rocket::State;
use rocket::http::Status;
use rocket_contrib::json::Json;
use rocket_contrib::databases::diesel as rocket_diesel;
use diesel::prelude::*;
use trust_dns_client::client::{Client, SyncClient};
use trust_dns_client::tcp::TcpClientConnection;
@ -12,10 +19,16 @@ use trust_dns_client::rr::{DNSClass, Name, RecordType};
mod models;
mod config;
mod auth;
mod schema;
use models::errors::ErrorResponse;
use auth::routes::*;
#[database("db")]
pub struct DbConn(diesel::SqliteConnection);
#[get("/zones/<zone>/records")]
fn get_zone_records(client: State<SyncClient<TcpClientConnection>>, zone: String) -> Result<Json<Vec<models::dns::Record>>, ErrorResponse<()>> {
// TODO: Implement FromParam for Name
@ -52,5 +65,6 @@ fn main() {
rocket::ignite()
.manage(client)
.mount("/api/v1", routes![get_zone_records]).launch();
.attach(DbConn::fairing())
.mount("/api/v1", routes![get_zone_records, create_auth_token]).launch();
}

View File

@ -1,5 +1,6 @@
pub mod dns;
pub mod errors;
pub mod users;
pub mod trust_dns_types {
pub use trust_dns_client::rr::rdata::{

48
src/models/users.rs Normal file
View File

@ -0,0 +1,48 @@
use uuid::Uuid;
use diesel::prelude::*;
use diesel::associations::HasTable;
use rocket::request::{FromRequest, Request, Outcome};
use diesel_derive_enum::DbEnum;
use crate::schema::*;
#[derive(Debug, DbEnum)]
pub enum Role {
Admin,
ZoneAdmin,
}
#[derive(Debug, Queryable, Identifiable)]
#[table_name = "user"]
pub struct User {
pub id: String,
pub role: String,
}
#[derive(Debug, Queryable, Identifiable)]
#[table_name = "localuser"]
#[primary_key(user_id)]
pub struct LocalUser {
pub user_id: String,
pub username: String,
pub password: String,
}
// pub struct LdapUserAssociation {
// user_id: Uuid,
// ldap_id: String
// }
pub struct UserInfo {
id: Uuid,
role: Role,
username: String,
}
impl<'a, 'r> FromRequest<'a, 'r> for UserInfo {
type Error = ();
fn from_request(request: &'a Request<'r>) -> Outcome<UserInfo, ()> {
Outcome::Forward(())
}
}

21
src/schema.rs Normal file
View File

@ -0,0 +1,21 @@
table! {
localuser (user_id) {
user_id -> Text,
username -> Text,
password -> Text,
}
}
table! {
user (id) {
id -> Text,
role -> Text,
}
}
joinable!(localuser -> user (user_id));
allow_tables_to_appear_in_same_query!(
localuser,
user,
);