# # (c) Jan Gehring # # vim: set ts=2 sw=2 tw=0: # vim: set expandtab: package Rex::Repositorio::Server::Docker::Auth; use Mojo::Base 'Mojolicious::Controller'; use MIME::Base64; use File::Spec; use File::Path 'make_path', 'remove_tree'; use Digest::MD5 'md5_base64'; use Rex::Repositorio::Server::Docker::Helper::Auth; use JSON::XS; use Data::Dumper; our $VERSION = '1.2.1'; # VERSION # TODO: implement authentication and authorization # currently this is just a random string sub login { my ($self) = @_; my $repo_name = $self->param("repo_namespace") . "/" . $self->param("name"); $self->stash( session_changed => 0 ); if ( $self->req->headers->header("Authorization") && $self->stash("session_authenticated") == 0 ) { my ( $type, $base64_header_line ) = split( / /, $self->req->headers->header("Authorization"), 2 ); if ( $type eq "Basic" ) { my ( $user, $pass ) = split( /:/, decode_base64($base64_header_line) ); my $repo_dir = $self->app->get_repo_dir( repo => $self->repo->{name} ); my $user_dir = File::Spec->catdir( $repo_dir, "users" ); my $user_o = Rex::Repositorio::Server::Docker::Helper::Auth->create( "Plain", { user_path => $user_dir, } ); $pass = md5_base64($pass); if ( $user_o->login( $user, $pass ) ) { my $token = $self->_generate_token; $self->stash( session_token => $token ); $self->stash( session_user => $user ); $self->stash( session_changed => 1 ); $self->app->log->debug("User: $user logged in."); $self->res->headers->add( 'X-Docker-Token' => 'Token signature=' . $token . ',repository="' . $repo_name . '",access=write' ); $self->res->headers->add( 'WWW-Authenticate' => 'Token signature=' . $token . ',repository="' . $repo_name . '",access=write' ); } else { $self->render( text => 'Access denied', status => 401 ); return 0; } } elsif ( $type eq "Token" ) { $self->render( text => 'Access denied', status => 401 ); return 0; } } elsif ( $self->stash("session_authenticated") == 1 ) { # TODO: check if session is valid #$self->res->headers->add( "X-Docker-Token" => $self->req->headers->header("X-Docker-Token")); #$self->res->headers->add( "WWW-Authenticate" => $self->req->headers->header("WWW-Authenticate")); my $user = $self->stash("session_user"); $self->app->log->debug("User: $user logged in. (via session)"); my $token = $self->stash("session_token"); $self->res->headers->add( "X-Docker-Token" => 'Token signature=' . $token . ',repository="' . $repo_name . '",access=write' ); $self->res->headers->add( "WWW-Authenticate" => 'Token signature=' . $token . ',repository="' . $repo_name . '",access=write' ); } $self->res->headers->add( 'X-Docker-Endpoints' => $self->req->headers->host ); $self->res->headers->add( 'Pragma' => 'no-cache' ); $self->res->headers->add( 'Expires' => '-1' ); 1; } sub post_user { my ($self) = @_; my $repo_dir = $self->app->get_repo_dir( repo => $self->repo->{name} ); my $user_dir = File::Spec->catdir( $repo_dir, "users" ); my $ref = $self->req->json; my $username = $ref->{username}; if ( !-d File::Spec->catdir( $user_dir, $username ) ) { make_path( File::Spec->catdir( $user_dir, $username ) ); open( my $fh, ">", File::Spec->catfile( $user_dir, $username, "user.json" ) ) or die($!); my $ref = $self->req->json; $ref->{password} = md5_base64( $ref->{password} ); print $fh encode_json($ref); close($fh); $self->res->headers->add( "Content-Type", "application/json" ); return $self->render( text => '"User Created"', status => 201 ); } else { $self->res->headers->add( "Content-Type", "application/json" ); return $self->render( text => '"User Created"', status => 201 ); } } sub _generate_token { my ($self) = @_; my @chars = ( 'a' .. 'z', 0 .. 9 ); srand(); my $ret = ""; for ( 1 .. 12 ) { $ret .= $chars[ int( rand( scalar(@chars) - 1 ) ) ]; } return $ret; } 1;