-
Notifications
You must be signed in to change notification settings - Fork 3
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
Slim down slack #10
Open
fiji-flo
wants to merge
16
commits into
mozilla-iam:master
Choose a base branch
from
fiji-flo:slim-down-slack
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Slim down slack #10
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
bcd5923
feat(IAM-170): adding slack to whoami
andrew-sunada 8d49004
fix(IAM-170): replacing urls
andrew-sunada ade98a4
feat(IAM-170): updating url with direct message link
andrew-sunada 3983e86
fix(IAM-170): fixing domain
andrew-sunada b1eee45
feat(IAM-170): enabling slack to add web app direct message storage
andrew-sunada 4aa692c
chore(IAM-170): code cleanups
andrew-sunada 858666e
feat(IAM-170): updating update_slack to include previous value
andrew-sunada dace62a
chore(IAM-170): adding changes for clippy
andrew-sunada dde3d51
chore(IAM-170): moving reponses to helper functions
andrew-sunada 103f820
chore(IAM-170): updating send_response
andrew-sunada 806ae69
fix(IAM-170): removing mistake
andrew-sunada 8bfda97
fix(IAM-170): updating slack for bot scope
andrew-sunada 77090b6
use only identity information for slack
fiji-flo 22f0a6e
enforce slack team_id
fiji-flo 673112c
error if team_id mismatches
fiji-flo 992a295
rm println
fiji-flo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,18 @@ | ||
const fs = require('fs'); | ||
const fs = require('fs'); | ||
const httpProxy = require('http-proxy'); | ||
|
||
// | ||
// Create the HTTPS proxy server listening on port 8000 | ||
// | ||
httpProxy.createServer({ | ||
target: { | ||
host: '127.0.0.1', | ||
port: 8084, | ||
}, | ||
ssl: { | ||
key: fs.readFileSync(process.env["DP_HTTPS_KEY"], 'utf8'), | ||
cert: fs.readFileSync(process.env["DP_HTTPS_CERT"], 'utf8') | ||
} | ||
}).listen(443); | ||
httpProxy | ||
.createServer({ | ||
target: { | ||
host: '127.0.0.1', | ||
port: 8084, | ||
}, | ||
ssl: { | ||
key: fs.readFileSync(process.env['DP_HTTPS_KEY'], 'utf8'), | ||
cert: fs.readFileSync(process.env['DP_HTTPS_CERT'], 'utf8'), | ||
}, | ||
}) | ||
.listen(443); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
use crate::settings::Slack; | ||
use crate::settings::WhoAmI; | ||
use crate::update::update_slack; | ||
use crate::userid::UserId; | ||
use actix_cors::Cors; | ||
use actix_session::CookieSession; | ||
use actix_session::Session; | ||
use actix_web::client::Client; | ||
use actix_web::cookie::SameSite; | ||
use actix_web::dev::HttpServiceFactory; | ||
use actix_web::http; | ||
use actix_web::web; | ||
use actix_web::Error; | ||
use actix_web::HttpResponse; | ||
use actix_web::Responder; | ||
use cis_client::getby::GetBy; | ||
use cis_client::AsyncCisClientTrait; | ||
use cis_profile::schema::Profile; | ||
use failure::format_err; | ||
use futures::future; | ||
use futures::Future; | ||
use futures::IntoFuture; | ||
use log::error; | ||
use oauth2::basic::BasicClient; | ||
use oauth2::prelude::*; | ||
use oauth2::AuthUrl; | ||
use oauth2::ClientId; | ||
use oauth2::ClientSecret; | ||
use oauth2::CsrfToken; | ||
use oauth2::RedirectUrl; | ||
use oauth2::Scope; | ||
use oauth2::TokenUrl; | ||
use std::sync::Arc; | ||
use url::Url; | ||
|
||
const AUTH_URL: &str = "https://slack.com/oauth/authorize"; | ||
const TOKEN_URL: &str = "https://slack.com/api/oauth.access"; | ||
|
||
#[derive(Deserialize)] | ||
pub struct Auth { | ||
code: String, | ||
state: String, | ||
} | ||
|
||
#[derive(Deserialize, Serialize, Debug, Clone)] | ||
pub struct SlackUser { | ||
name: String, | ||
id: String, | ||
} | ||
|
||
#[derive(Deserialize, Serialize, Debug)] | ||
pub struct SlackUriData { | ||
identity_slack_auth_params: String, | ||
direct_message_uri: String, | ||
team_id: String, | ||
} | ||
|
||
#[derive(Deserialize, Debug, Clone)] | ||
pub struct SlackUserTokenResponse { | ||
ok: bool, | ||
access_token: String, | ||
scope: String, | ||
user_id: String, | ||
team_id: String, | ||
user: SlackUser, | ||
} | ||
|
||
fn send_response(url: &str) -> HttpResponse { | ||
HttpResponse::Found() | ||
.header(http::header::LOCATION, url) | ||
.finish() | ||
} | ||
|
||
fn send_error_response() -> HttpResponse { | ||
send_response("/e?identityAdded=error") | ||
} | ||
|
||
/** | ||
* First redirect that handles getting authorization for identity scopes | ||
*/ | ||
fn redirect_identity(client: web::Data<Arc<BasicClient>>, session: Session) -> impl Responder { | ||
let (authorize_url, csrf_state) = client.authorize_url(CsrfToken::new_random); | ||
session | ||
.set("identity_csrf_state", csrf_state.secret().clone()) | ||
.map(|_| send_response(&authorize_url.to_string())) | ||
} | ||
|
||
fn auth_identity<T: AsyncCisClientTrait + 'static>( | ||
cis_client: web::Data<T>, | ||
user_id: UserId, | ||
query: web::Query<Auth>, | ||
slack_uri_data: web::Data<SlackUriData>, | ||
session: Session, | ||
) -> Box<dyn Future<Item = HttpResponse, Error = Error>> { | ||
let state = CsrfToken::new(query.state.clone()); | ||
let slack_token_url = format!( | ||
"{}{}&code={}&team={}", | ||
TOKEN_URL, | ||
slack_uri_data.identity_slack_auth_params, | ||
query.code.clone(), | ||
slack_uri_data.team_id | ||
); | ||
// Check state token from im_crsf_state | ||
if let Some(ref must_state) = session.get::<String>("identity_csrf_state").unwrap() { | ||
if must_state != state.secret() { | ||
error!("Error: Identity csrf state mismatch"); | ||
return Box::new(future::ok(send_error_response())); | ||
} | ||
} else { | ||
error!("Error: Missing identity csrf state"); | ||
return Box::new(future::ok(send_error_response())); | ||
} | ||
|
||
let get = cis_client.clone(); | ||
let get_uid = user_id.user_id.clone(); | ||
let enforced_team_id = slack_uri_data.team_id.clone(); | ||
// Begin slack requests by grabbing the user_id, and access_token | ||
Box::new( | ||
Client::default() | ||
.get(slack_token_url) | ||
.header(http::header::USER_AGENT, "whoami") | ||
.send() | ||
.map_err(Into::into) | ||
.and_then(move |mut res| res.json::<SlackUserTokenResponse>().map_err(Into::into)) | ||
.and_then(move |sur| { | ||
if sur.team_id == enforced_team_id { | ||
Ok(sur) | ||
} else { | ||
Err(format_err!("slack team_id missmatch").into()) | ||
} | ||
}) | ||
.and_then(move |sur| { | ||
// Now that we have the access_token, user data, and channel id, go put it in the profile | ||
get.get_user_by(&get_uid, &GetBy::UserId, None) | ||
.and_then(move |profile: Profile| { | ||
update_slack( | ||
format!( | ||
"{}?channel={}&team={}", | ||
slack_uri_data.direct_message_uri, sur.user_id, sur.team_id | ||
), | ||
sur.user.name.clone(), | ||
profile, | ||
get.get_secret_store(), | ||
) | ||
.into_future() | ||
.map_err(Into::into) | ||
}) | ||
.map_err(Into::into) | ||
}) | ||
.and_then(move |profile: Profile| { | ||
// Now finally save the updated user profile | ||
cis_client | ||
.update_user(&user_id.user_id, profile) | ||
.map_err(Into::into) | ||
}) | ||
.and_then(|_| send_response("/e?identityAdded=slack")), | ||
) | ||
} | ||
|
||
pub fn slack_app<T: AsyncCisClientTrait + 'static>( | ||
slack: &Slack, | ||
whoami: &WhoAmI, | ||
secret: &[u8], | ||
cis_client: T, | ||
) -> impl HttpServiceFactory { | ||
let slack_client_id = ClientId::new(slack.client_id.clone()); | ||
let slack_client_secret = ClientSecret::new(slack.client_secret.clone()); | ||
let identity_slack_auth_params = format!( | ||
"?client_id={}&client_secret={}&redirect_uri={}", | ||
&slack.client_id, &slack.client_secret, &slack.identity_redirect_uri | ||
); | ||
let auth_url = AuthUrl::new(Url::parse(AUTH_URL).expect("Invalid authorization endpoint URL")); | ||
let identity_token_url = TokenUrl::new( | ||
Url::parse(&format!("{}{}", TOKEN_URL, identity_slack_auth_params)) | ||
.expect("Invalid token endpoint URL"), | ||
); | ||
let identity_client = Arc::new( | ||
BasicClient::new( | ||
slack_client_id.clone(), | ||
Some(slack_client_secret.clone()), | ||
auth_url.clone(), | ||
Some(identity_token_url), | ||
) | ||
.add_scope(Scope::new(slack.identity_scope.clone())) | ||
.set_redirect_url(RedirectUrl::new( | ||
Url::parse(&slack.identity_redirect_uri).expect("Invalid redirect URL"), | ||
)), | ||
); | ||
let slack_uri_data: SlackUriData = SlackUriData { | ||
identity_slack_auth_params, | ||
direct_message_uri: slack.direct_message_uri.clone(), | ||
team_id: slack.team_id.clone(), | ||
}; | ||
|
||
web::scope("/slack/") | ||
.wrap( | ||
Cors::new() | ||
.allowed_methods(vec!["GET", "POST"]) | ||
.allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT]) | ||
.allowed_header(http::header::CONTENT_TYPE) | ||
.max_age(3600), | ||
) | ||
.wrap( | ||
CookieSession::private(secret) | ||
.name("dpw_s") | ||
.path("/whoami/slack") | ||
.domain(whoami.domain.clone()) | ||
.same_site(SameSite::Lax) | ||
.http_only(true) | ||
.secure(false) | ||
.max_age(300), | ||
) | ||
.data(identity_client) | ||
.data(cis_client) | ||
.data(slack_uri_data) | ||
.service(web::resource("/add").route(web::get().to(redirect_identity))) | ||
.service(web::resource("/auth/identity").route(web::get().to_async(auth_identity::<T>))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This returns "Leo McArdle" rather than "leo", is there no way of returning the username without getting into scope hell again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not hell, but complicated. The display name would require another scope and another call to an endpoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I don't think it's necessary for the moment then.