Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

quote handling #6

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ teleport.env
exex.manifest.sgx
exex.manifest
exex.sig
*.csr
*.pem
*.tmp
certbot
9 changes: 8 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ http = "1.1.0"
axum-server = {version = "0.6.0", features = ["tls-rustls"]}
bincode = "1.3.3"
getrandom = "0.2.15"
acme-lib = "0.9.1"
openssl = "0.10.63"
sha2 = "0.10.8"
tokio-postgres = "0.7.2"
rustls = "0.19.0"
webpki-roots = "0.21.0"
tokio-postgres-rustls = "0.8.0"
tokio-postgres-rustls = "0.8.0"

[features]
default = ["https"]
https = []
Empty file added data/.ignore
Empty file.
2 changes: 0 additions & 2 deletions env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ DB_PATH=
WS_RPC_URL=
RPC_URL=
NFT_MINTER_MNEMONIC=
TLS_CERT_PATH=
TLS_KEY_PATH=
APP_URL=
TEE_URL=
NFT_ADDRESS=
21 changes: 0 additions & 21 deletions self_signed_certs/cert.pem

This file was deleted.

28 changes: 0 additions & 28 deletions self_signed_certs/key.pem

This file was deleted.

3 changes: 1 addition & 2 deletions src/actions/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ pub async fn subscribe_to_nft_events<A: TeleportDB>(
drop(db_lock);
if let Some(user) = user {
let tweet_id = send_tweet(
user.access_token,
user.access_secret,
user.access_tokens.unwrap(),
redeem.content.to_string(),
)
.await?;
Expand Down
41 changes: 41 additions & 0 deletions src/cert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use openssl::{
hash::MessageDigest,
pkey::{self, PKey},
stack::Stack,
x509::{extension::SubjectAlternativeName, X509Req, X509ReqBuilder},
};

// from https://github.com/flashbots/gramine-andromeda-revm/blob/amiller-frame/src/main.rs
pub fn create_csr(domain: &str, pkey: &PKey<pkey::Private>) -> eyre::Result<X509Req> {
//
// the csr builder
let mut req_bld = X509ReqBuilder::new().expect("X509ReqBuilder");

let mut x509_name = openssl::x509::X509NameBuilder::new().unwrap();
x509_name.append_entry_by_text("C", "US").unwrap();
x509_name.append_entry_by_text("ST", "IL").unwrap();
x509_name.append_entry_by_text("O", "n/a").unwrap();
x509_name.append_entry_by_text("CN", domain).unwrap();
let x509_name = x509_name.build();

req_bld.set_subject_name(&x509_name).unwrap();

// set private/public key in builder
req_bld.set_pubkey(pkey).expect("set_pubkey");

// set all domains as alt names
let mut stack = Stack::new().expect("Stack::new");
let ctx = req_bld.x509v3_context(None);
let mut an = SubjectAlternativeName::new();
an.dns(domain);

let ext = an.build(&ctx).expect("SubjectAlternativeName::build");
stack.push(ext).expect("Stack::push");
req_bld.add_extensions(&stack).expect("add_extensions");

// sign it
req_bld.sign(pkey, MessageDigest::sha256()).expect("csr_sign");

// the csr
Ok(req_bld.build())
}
15 changes: 9 additions & 6 deletions src/db/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,30 +88,33 @@ impl TeleportDB for InMemoryDB {

#[cfg(test)]
mod tests {
use crate::db::AccessTokens;

use super::*;

#[tokio::test]
async fn db_test_write() -> eyre::Result<()> {
let mut db = InMemoryDB::new();
let access_tokens = AccessTokens { token: "access token".to_string(), secret: "access secret".to_string() };
let user = User {
x_id: None,
access_token: "access token".to_string(),
access_secret: "access secret".to_string(),
access_tokens: Some(access_tokens.clone()),
oauth_tokens: access_tokens.clone(),
};
db.add_user("2".to_string(), user.clone()).await.expect("Failed to add user tokens");
let user = db.get_user_by_address("2".to_string()).await?;
assert_eq!(user.access_token, "access token");
assert_eq!(user.access_secret, "access secret");
assert_eq!(user.access_tokens.unwrap(), access_tokens);
Ok(())
}

#[tokio::test]
async fn db_test_overwrite() -> eyre::Result<()> {
let mut db = InMemoryDB::new();
let access_tokens = AccessTokens { token: "access token".to_string(), secret: "access secret".to_string() };
let mut user = User {
x_id: None,
access_token: "access token".to_string(),
access_secret: "access secret".to_string(),
access_tokens: Some(access_tokens.clone()),
oauth_tokens: access_tokens.clone(),
};
db.add_user("2".to_string(), user.clone()).await.expect("Failed to add user tokens");
user.x_id = Some("1".to_string());
Expand Down
13 changes: 10 additions & 3 deletions src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ use serde::{Deserialize, Serialize};
pub mod in_memory;
// pub mod sqlite;

#[derive(Debug, Serialize, Deserialize, Clone, FromRow, PartialEq, Eq)]

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default)]
pub struct AccessTokens {
pub token: String,
pub secret: String,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default)]
pub struct User {
pub x_id: Option<String>,
pub access_token: String,
pub access_secret: String,
pub access_tokens: Option<AccessTokens>,
pub oauth_tokens: AccessTokens,
}

#[derive(Debug, Serialize, Deserialize, Clone, FromRow, PartialEq, Eq)]
Expand Down
93 changes: 48 additions & 45 deletions src/endpoints.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use alloy::primitives::Address;
use alloy::{
primitives::Address,
signers::{k256::ecdsa::SigningKey, local::LocalSigner},
};
use std::{str::FromStr, sync::Arc};
use tokio::fs;

use axum::{
extract::{Query, State},
Expand All @@ -15,21 +17,25 @@ use crate::{
nft::{mint_nft, redeem_nft},
wallet::WalletProvider,
},
db::{PendingNFT, TeleportDB, User},
db::{AccessTokens, PendingNFT, TeleportDB},
oai,
twitter::{authorize_token, get_user_x_info, request_oauth_token},
twitter::{authorize_token, get_callback_url, get_user_x_info, request_oauth_token},
};

use alloy::signers::Signer;

#[derive(Deserialize)]
pub struct NewUserQuery {
address: String,
frontend_nonce: String,
}

#[derive(Deserialize)]
pub struct CallbackQuery {
oauth_token: String,
oauth_verifier: String,
address: String,
frontend_nonce: String,
}

#[derive(Deserialize)]
Expand Down Expand Up @@ -80,43 +86,33 @@ pub struct CheckRedeemResponse {
pub struct SharedState<A: TeleportDB> {
pub db: Arc<Mutex<A>>,
pub provider: WalletProvider,
pub signer: LocalSigner<SigningKey>,
pub app_url: String,
pub tee_url: String,
}

pub async fn new_user<A: TeleportDB>(
pub async fn register_or_login<A: TeleportDB>(
State(shared_state): State<SharedState<A>>,
Query(query): Query<NewUserQuery>,
) -> Redirect {
let address = query.address;
let frontend_nonce = query.frontend_nonce;

let db_lock = shared_state.db.lock().await;
let existing_user = db_lock.get_user_by_address(address.clone()).await.ok();
if let Some(user) = existing_user {
if user.x_id.is_some() {
let x_info = get_user_x_info(user.access_token, user.access_secret).await;
let encoded_x_info = serde_urlencoded::to_string(&x_info)
.expect("Failed to encode x_info as query params");
let url_with_params = format!(
"{}/create?already_created=true&success=true&{}",
shared_state.app_url, encoded_x_info
);
return Redirect::temporary(&url_with_params);
}
}
drop(db_lock);
let callback_url =
get_callback_url(shared_state.tee_url.clone(), address.clone(), frontend_nonce);

let oauth_tokens =
request_oauth_token(callback_url).await.expect("Failed to request oauth token");

let (oauth_token, oauth_token_secret) =
request_oauth_token(address.clone(), shared_state.tee_url)
.await
.expect("Failed to request oauth token");
let user =
User { x_id: None, access_token: oauth_token.clone(), access_secret: oauth_token_secret };
let mut db = shared_state.db.lock().await;
db.add_user(address.clone(), user).await.expect("Failed to add oauth tokens to database");
drop(db);
let mut existing_user = db.get_user_by_address(address.clone()).await.ok().unwrap_or_default();
existing_user.oauth_tokens = oauth_tokens.clone();
db.add_user(address.clone(), existing_user)
.await
.expect("Failed to add oauth tokens to database");

let url = format!("https://api.twitter.com/oauth/authenticate?oauth_token={}", oauth_token);
let url =
format!("https://api.twitter.com/oauth/authenticate?oauth_token={}", oauth_tokens.token);

Redirect::temporary(&url)
}
Expand All @@ -128,23 +124,34 @@ pub async fn callback<A: TeleportDB>(
let oauth_token = query.oauth_token;
let oauth_verifier = query.oauth_verifier;
let address = query.address;
let frontend_nonce = query.frontend_nonce;

let mut db = shared_state.db.lock().await;
let oauth_user =
let mut oauth_user =
db.get_user_by_address(address.clone()).await.expect("Failed to get oauth tokens");
assert_eq!(oauth_token, oauth_user.access_token);
assert_eq!(oauth_token, oauth_user.oauth_tokens.token);

let (access_token, access_secret) =
authorize_token(oauth_token, oauth_user.access_secret, oauth_verifier).await.unwrap();
let x_info = get_user_x_info(access_token.clone(), access_secret.clone()).await;
let user = User { x_id: Some(x_info.id.clone()), access_token, access_secret };
db.add_user(address, user.clone()).await.expect("Failed to add user to database");
drop(db);
authorize_token(oauth_user.oauth_tokens.clone(), oauth_verifier).await.unwrap();

let access_tokens = AccessTokens { token: access_token, secret: access_secret };

let x_info = get_user_x_info(access_tokens.clone()).await;

if oauth_user.x_id.is_none() {
oauth_user.x_id = Some(x_info.id.clone());
oauth_user.access_tokens = Some(access_tokens.clone());
db.add_user(address, oauth_user.clone()).await.expect("Failed to add user to database");
drop(db);
}

let msg = format!("nonce={}&x_id={}", frontend_nonce, x_info.id);
let sig = shared_state.signer.sign_message(msg.as_bytes()).await.unwrap();

let encoded_x_info =
serde_urlencoded::to_string(&x_info).expect("Failed to encode x_info as query params");
let url_with_params =
format!("{}/create?success=true&{}", shared_state.app_url, encoded_x_info);
format!("{}/create?sig={:?}&success=true&{}", shared_state.app_url, sig, encoded_x_info);

Redirect::temporary(&url_with_params)
}
Expand Down Expand Up @@ -184,7 +191,10 @@ pub async fn redeem<A: TeleportDB>(
Json(query): Json<RedeemQuery>,
) -> Json<TxHashResponse> {
let db = shared_state.db.lock().await;
let nft = db.get_nft(query.nft_id.clone()).await.unwrap_or_else(|_| panic!("Failed to get NFT by id {}", query.nft_id.to_string()));
let nft = db
.get_nft(query.nft_id.clone())
.await
.unwrap_or_else(|_| panic!("Failed to get NFT by id {}", query.nft_id.to_string()));
drop(db);

let tx_hash = redeem_nft(shared_state.provider, nft.token_id.clone(), query.content)
Expand Down Expand Up @@ -212,13 +222,6 @@ pub async fn get_tweet_id<A: TeleportDB>(
Json(TweetIdResponse { tweet_id })
}

pub async fn get_ratls_cert() -> Json<AttestationResponse> {
let cert = fs::read_to_string(std::env::var("TLS_CERT_PATH").expect("TLS_CERT_PATH not set"))
.await
.expect("gramine ratls rootCA.crt not found");
Json(AttestationResponse { cert })
}

pub async fn hello_world() -> &'static str {
log::info!("Hello, World!");
"Hello, World!"
Expand Down
Loading
Loading