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

Bug 1612286 - Single sign-on through Mozilla IAM #1680

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
9 changes: 9 additions & 0 deletions .circleci/checksetup_answers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,12 @@ $answer{'urlbase'} = 'http://bmo.test/';
$answer{'mail_delivery_method'} = 'Test';
$answer{'auth_delegation'} = 1;
$answer{'utf8'} = 'utf8mb4';
$answer{'oauth2_client_enabled'} = 1,
$answer{'oauth2_client_id'} = 'client_id';
$answer{'oauth2_client_secret'} = 'client_secret';
$answer{'oauth2_client_authorize_url'} = '/oauth/test/authorize';
$answer{'oauth2_client_scopes'} = 'openid profile email';
$answer{'mozilla_iam_enabled'} = 1;
$answer{'mozilla_iam_person_api_client_id'} = 'client_id';
$answer{'mozilla_iam_person_api_client_secret'} = 'client_secret';
$answer{'mozilla_iam_mandatory_domains'} = 'mozilla.com';
22 changes: 13 additions & 9 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ jobs:
name: run sanity tests
command: |
[[ -f build_info/only_version_changed.txt ]] && exit 0
docker-compose -f docker-compose.test.yml run --no-deps bmo.test \
test_sanity $(circleci tests glob 't/*.t' 'extensions/*/t/*.t' | \
docker-compose -f docker-compose.test.yml run -e CIRCLE_JOB=$CIRCLE_JOB \
--no-deps bmo.test test_sanity $(circleci tests glob 't/*.t' 'extensions/*/t/*.t' | \
circleci tests split) | tee artifacts/$CIRCLE_JOB.txt
- store_artifacts:
path: /app/artifacts
Expand Down Expand Up @@ -222,8 +222,8 @@ jobs:
at: /app/build_info
- run: |
[[ -f build_info/only_version_changed.txt ]] && exit 0
docker-compose -f docker-compose.test.yml run bmo.test test_webservices | \
tee artifacts/$CIRCLE_JOB.txt
docker-compose -f docker-compose.test.yml run -e CIRCLE_JOB=$CIRCLE_JOB \
bmo.test test_webservices | tee artifacts/$CIRCLE_JOB.txt
- store_artifacts:
path: /app/artifacts
- *store_log
Expand All @@ -250,8 +250,8 @@ jobs:
at: /app/build_info
- run: |
[[ -f build_info/only_version_changed.txt ]] && exit 0
docker-compose -f docker-compose.test.yml run bmo.test test_selenium | \
tee artifacts/$CIRCLE_JOB.txt
docker-compose -f docker-compose.test.yml run -e CIRCLE_JOB=$CIRCLE_JOB \
bmo.test test_selenium | tee artifacts/$CIRCLE_JOB.txt
- store_artifacts:
path: /app/artifacts
- *store_log
Expand All @@ -276,9 +276,13 @@ jobs:
[[ -d artifacts ]] || mkdir artifacts
- attach_workspace:
at: /app/build_info
- run: |
[[ -f build_info/only_version_changed.txt ]] && exit 0
docker-compose -f docker-compose.test.yml run bmo.test test_bmo -q -f t/bmo/*.t
- run:
name: run bmo specific tests
command: |
[[ -f build_info/only_version_changed.txt ]] && exit 0
docker-compose -f docker-compose.test.yml run -e CI=1 -e CIRCLE_JOB=$CIRCLE_JOB \
bmo.test test_bmo -q -f $(circleci tests glob 't/bmo/*.t' 'extensions/*/t/bmo/*.t' | \
circleci tests split) | tee artifacts/$CIRCLE_JOB.txt
- *store_log

workflows:
Expand Down
6 changes: 3 additions & 3 deletions Bugzilla.pm
Original file line number Diff line number Diff line change
Expand Up @@ -206,15 +206,15 @@ sub page_requires_login {
return request_cache->{page_requires_login};
}

sub github_secret {
sub github_token {
my ($class) = @_;
my $cache = request_cache;
my $cgi = $class->cgi;

$cache->{github_secret} //= $cgi->cookie('github_secret')
$cache->{github_token} //= $cgi->cookie('github_token')
// generate_random_password(256);

return $cache->{github_secret};
return $cache->{github_token};
}

sub passwdqc {
Expand Down
1 change: 1 addition & 0 deletions Bugzilla/API/V1/User.pm
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ sub user_profile {
groups => [map { $_->name } @{$user->groups}],
mfa => lc($user->mfa),
mfa_required_by_group => $user->in_mfa_group ? true : false,
iam_username => $user->iam_username,
}
);
}
Expand Down
7 changes: 4 additions & 3 deletions Bugzilla/App.pm
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use Bugzilla::App::API;
use Bugzilla::App::BouncedEmails;
use Bugzilla::App::CGI;
use Bugzilla::App::Main;
use Bugzilla::App::OAuth2::Clients;
use Bugzilla::App::OAuth2::Provider::Clients;
use Bugzilla::App::SES;
use Bugzilla::App::Static;
use Mojo::Loader qw( find_modules );
Expand Down Expand Up @@ -53,7 +53,8 @@ sub startup {
unless $ENV{BUGZILLA_DISABLE_SIZELIMIT};
$self->plugin('ForwardedFor') if Bugzilla->has_feature('better_xff');
$self->plugin('Bugzilla::App::Plugin::Helpers');
$self->plugin('Bugzilla::App::Plugin::OAuth2');
$self->plugin('Bugzilla::App::Plugin::OAuth2::Client');
$self->plugin('Bugzilla::App::Plugin::OAuth2::Provider');

push @{$self->commands->namespaces}, 'Bugzilla::App::Command';
push @{$self->renderer->paths}, @{ Bugzilla::Template::_include_path() };
Expand Down Expand Up @@ -201,7 +202,7 @@ sub setup_routes {
Bugzilla::App::BouncedEmails->setup_routes($r);
Bugzilla::App::CGI->setup_routes($r);
Bugzilla::App::Main->setup_routes($r);
Bugzilla::App::OAuth2::Clients->setup_routes($r);
Bugzilla::App::OAuth2::Provider::Clients->setup_routes($r);
Bugzilla::App::SES->setup_routes($r);

$r->static_file('/__lbheartbeat__');
Expand Down
67 changes: 48 additions & 19 deletions Bugzilla/App/API.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package Bugzilla::App::API;
use 5.10.1;
use Mojo::Base qw( Mojolicious::Controller );

use File::Basename qw(basename);
use Mojo::Loader qw( find_modules );
use Module::Runtime qw(require_module);
use Try::Tiny;
Expand All @@ -22,18 +23,20 @@ use constant SUPPORTED_VERSIONS => qw(V1);
sub setup_routes {
my ($class, $r) = @_;

# Add Bugzilla::API to namespaces for searching for controllers
# Add Bugzilla::API and Bugzilla::Extension to
# namespaces for searching for API controllers
my $namespaces = $r->namespaces;
push @$namespaces, 'Bugzilla::API';
push @$namespaces, 'Bugzilla::API', 'Bugzilla::Extension';
$r->namespaces($namespaces);

# Backwards compat with /api/user/profile which Phabricator requires
$r->under('/api' => sub {
my ($c) = @_;
_insert_rest_headers($c);
Bugzilla->usage_mode(USAGE_MODE_REST);
})
->get('/user/profile')->to('V1::User#user_profile');
$r->under(
'/api' => sub {
my ($c) = @_;
_insert_rest_headers($c);
Bugzilla->usage_mode(USAGE_MODE_REST);
}
)->get('/user/profile')->to('V1::User#user_profile');

# Other backwards compat routes
$r->under(
Expand All @@ -60,31 +63,57 @@ sub setup_routes {
}
);

# Standard API support
foreach my $version (SUPPORTED_VERSIONS) {
foreach my $module (find_modules("Bugzilla::API::$version")) {
try {
require_module($module);
my $controller = $module->new;
if ($controller->can('setup_routes')) {
$controller->setup_routes($rest_routes);
}
_load_api_module($rest_routes, $module);
}
}

# Extension API support
my @ext_paths = glob bz_locations()->{'extensionsdir'} . '/*';
my @ext_api_paths = grep { !-e "$_/disabled" && -d "$_/lib/API" } @ext_paths;

foreach my $version (SUPPORTED_VERSIONS) {
foreach my $ext_path (@ext_api_paths) {
my $ext_name = $ext_path;
$ext_name =~ s|^.*extensions/||;

my @module_paths = glob "$ext_path/lib/API/$version/*";
foreach my $module_path (@module_paths) {
my $module = "Bugzilla::Extension::${ext_name}::API::${version}::"
. basename($module_path, '.pm');
_load_api_module($rest_routes, $module);
}
catch {
WARN("$module could not be loaded");
};
}
}
}

sub _load_api_module {
my ($routes, $module) = @_;
try {
require_module($module);
my $controller = $module->new;
if ($controller->can('setup_routes')) {
$controller->setup_routes($routes);
}
}
catch {
WARN("$module could not be loaded");
};
}

sub _insert_rest_headers {
my ($c) = @_;

# Access Control
my @allowed_headers
= qw(accept authorization content-type origin user-agent x-bugzilla-api-key x-requested-with);
$c->res->headers->header('Access-Control-Allow-Origin' => '*');
$c->res->headers->header('Access-Control-Allow-Headers' =>
join ', ', @allowed_headers);
$c->res->headers->header(
'Access-Control-Allow-Headers' => join ', ',
@allowed_headers
);
}

1;
2 changes: 1 addition & 1 deletion Bugzilla/App/Main.pm
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ sub setup_routes {
sub root {
my ($c) = @_;
$c->res->headers->cache_control('public, max-age=3600, immutable');
$c->render(handler => 'bugzilla');
$c->render('index', handler => 'bugzilla');
}

sub testagent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.

package Bugzilla::App::OAuth2::Clients;
package Bugzilla::App::OAuth2::Provider::Clients;
use 5.10.1;
use Mojo::Base 'Mojolicious::Controller';

Expand All @@ -20,7 +20,7 @@ sub setup_routes {

# Manage the client list
my $client_route = $r->under(
'/admin/oauth' => sub {
'/admin/oauth/provider' => sub {
my ($c) = @_;
Bugzilla->usage_mode(USAGE_MODE_MOJO);
my $user = $c->bugzilla->login(LOGIN_REQUIRED) || return undef;
Expand All @@ -30,12 +30,12 @@ sub setup_routes {
return 1;
}
);
$client_route->any('/list')->to('OAuth2::Clients#list')->name('list_clients');
$client_route->any('/create')->to('OAuth2::Clients#create')
$client_route->any('/list')->to('OAuth2::Provider::Clients#list')->name('list_clients');
$client_route->any('/create')->to('OAuth2::Provider::Clients#create')
->name('create_client');
$client_route->any('/delete')->to('OAuth2::Clients#delete')
$client_route->any('/delete')->to('OAuth2::Provider::Clients#delete')
->name('delete_client');
$client_route->any('/edit')->to('OAuth2::Clients#edit')->name('edit_client');
$client_route->any('/edit')->to('OAuth2::Provider::Clients#edit')->name('edit_client');
}

# Show list of clients
Expand All @@ -44,7 +44,7 @@ sub list {
my $clients = Bugzilla->dbh->selectall_arrayref('SELECT * FROM oauth2_client',
{Slice => {}});
$self->stash(clients => $clients);
return $self->render(template => 'admin/oauth/list', handler => 'bugzilla');
return $self->render(template => 'admin/oauth/provider/list', handler => 'bugzilla');
}

# Create new client
Expand All @@ -60,7 +60,7 @@ sub create {
$vars->{scopes}
= $dbh->selectall_arrayref('SELECT * FROM oauth2_scope', {Slice => {}});
$self->stash(%{$vars});
return $self->render(template => 'admin/oauth/create', handler => 'bugzilla');
return $self->render(template => 'admin/oauth/provider/create', handler => 'bugzilla');
}

$dbh->bz_start_transaction;
Expand Down Expand Up @@ -107,7 +107,7 @@ sub create {
$vars->{'client'} = {description => $description};
$vars->{'clients'} = $clients;
$self->stash(%{$vars});
return $self->render(template => 'admin/oauth/list', handler => 'bugzilla');
return $self->render(template => 'admin/oauth/provider/list', handler => 'bugzilla');
}

# Delete client
Expand All @@ -126,7 +126,7 @@ sub delete {
$vars->{'token'} = issue_session_token('delete_oauth_client');
$self->stash(%{$vars});
return $self->render(
template => 'admin/oauth/confirm-delete',
template => 'admin/oauth/provider/confirm-delete',
handler => 'bugzilla'
);
}
Expand All @@ -149,7 +149,7 @@ sub delete {
$vars->{'client'} = {description => $client_data->{description}};
$vars->{'clients'} = $clients;
$self->stash(%{$vars});
return $self->render(template => 'admin/oauth/list', handler => 'bugzilla');
return $self->render(template => 'admin/oauth/provider/list', handler => 'bugzilla');
}

# Edit client
Expand Down Expand Up @@ -177,7 +177,7 @@ sub edit {
if ($self->req->method ne 'POST') {
$vars->{token} = issue_session_token('edit_oauth_client');
$self->stash(%{$vars});
return $self->render(template => 'admin/oauth/edit', handler => 'bugzilla');
return $self->render(template => 'admin/oauth/provider/edit', handler => 'bugzilla');
}

$dbh->bz_start_transaction;
Expand Down Expand Up @@ -216,7 +216,7 @@ sub edit {
$vars->{'client'} = {description => $description};
$vars->{'clients'} = $clients;
$self->stash(%{$vars});
return $self->render(template => 'admin/oauth/list', handler => 'bugzilla');
return $self->render(template => 'admin/oauth/provider/list', handler => 'bugzilla');
}

1;
Loading