BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
011a905a
Commit
011a905a
authored
May 02, 2016
by
Kamil Trzcinski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split docker authentication service
parent
105017c3
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
163 additions
and
101 deletions
+163
-101
jwt_controller.rb
app/controllers/jwt_controller.rb
+13
-101
docker_authentication_service.rb
app/services/jwt/docker_authentication_service.rb
+65
-0
rsa_token.rb
lib/jwt/rsa_token.rb
+36
-0
token.rb
lib/jwt/token.rb
+49
-0
No files found.
app/controllers/jwt_controller.rb
View file @
011a905a
...
...
@@ -2,6 +2,10 @@ class JwtController < ApplicationController
skip_before_action
:authenticate_user!
skip_before_action
:verify_authenticity_token
SERVICES
=
{
'docker'
=>
Jwt
::
DockerAuthenticationService
,
}
def
auth
@authenticated
=
authenticate_with_http_basic
do
|
login
,
password
|
@ci_project
=
ci_project
(
login
,
password
)
...
...
@@ -9,46 +13,22 @@ class JwtController < ApplicationController
end
unless
@authenticated
return
render_403
if
has_basic_credentials?
end
case
params
[
:service
]
when
'docker'
docker_token_auth
(
params
[
:scope
],
params
[
:offline_token
])
else
return
render_404
head
:forbidden
if
ActionController
::
HttpAuthentication
::
Basic
.
has_basic_credentials?
(
request
)
end
end
private
def
render_400
head
:invalid_request
end
service
=
SERVICES
[
params
[
:service
]]
head
:not_found
unless
service
def
render_404
head
:not_found
end
result
=
service
.
new
(
@ci_project
,
@user
,
auth_params
).
execute
return
head
result
[
:http_status
]
if
result
[
:http_status
]
def
render_403
head
:forbidden
render
json:
result
end
def
docker_token_auth
(
scope
,
offline_token
)
payload
=
{
aud:
params
[
:service
],
sub:
@user
.
try
(
:username
)
}
if
offline_token
return
render_403
unless
@user
elsif
scope
access
=
process_access
(
scope
)
return
render_404
unless
access
payload
[
:access
]
=
[
access
]
end
private
render
json:
{
token:
encode
(
payload
)
}
def
auth_params
params
.
permit
(
:service
,
:scope
,
:offline_token
,
:account
,
:client_id
)
end
def
ci_project
(
login
,
password
)
...
...
@@ -102,72 +82,4 @@ class JwtController < ApplicationController
user
end
def
process_access
(
scope
)
type
,
name
,
actions
=
scope
.
split
(
':'
,
3
)
actions
=
actions
.
split
(
','
)
case
type
when
'repository'
process_repository_access
(
type
,
name
,
actions
)
end
end
def
process_repository_access
(
type
,
name
,
actions
)
project
=
Project
.
find_with_namespace
(
name
)
return
unless
project
actions
=
actions
.
select
do
|
action
|
can_access?
(
project
,
action
)
end
{
type:
'repository'
,
name:
name
,
actions:
actions
}
if
actions
end
def
default_payload
{
aud:
'docker'
,
sub:
@user
.
try
(
:username
),
aud:
params
[
:service
],
}
end
def
private_key
@private_key
||=
OpenSSL
::
PKey
::
RSA
.
new
File
.
read
Gitlab
.
config
.
registry
.
key
end
def
encode
(
payload
)
issued_at
=
Time
.
now
payload
=
payload
.
merge
(
iss:
Gitlab
.
config
.
registry
.
issuer
,
iat:
issued_at
.
to_i
,
nbf:
issued_at
.
to_i
-
5
.
seconds
.
to_i
,
exp:
issued_at
.
to_i
+
60
.
minutes
.
to_i
,
jti:
SecureRandom
.
uuid
,
)
headers
=
{
kid:
kid
(
private_key
)
}
JWT
.
encode
(
payload
,
private_key
,
'RS256'
,
headers
)
end
def
can_access?
(
project
,
action
)
case
action
when
'pull'
project
==
@ci_project
||
can?
(
@user
,
:download_code
,
project
)
when
'push'
project
==
@ci_project
||
can?
(
@user
,
:push_code
,
project
)
else
false
end
end
def
kid
(
private_key
)
sha256
=
Digest
::
SHA256
.
new
sha256
.
update
(
private_key
.
public_key
.
to_der
)
payload
=
StringIO
.
new
(
sha256
.
digest
).
read
(
30
)
Base32
.
encode
(
payload
).
split
(
''
).
each_slice
(
4
).
each_with_object
([])
do
|
slice
,
mem
|
mem
<<
slice
.
join
end
.
join
(
':'
)
end
end
app/services/jwt/docker_authentication_service.rb
0 → 100644
View file @
011a905a
module
Jwt
class
DockerAuthenticationService
<
BaseService
def
execute
if
params
[
:offline_token
]
return
error
(
'forbidden'
,
403
)
unless
current_user
end
{
token:
token
.
encoded
}
end
private
def
token
token
=
::
Jwt
::
RSAToken
.
new
(
registry
.
key
)
token
.
issuer
=
registry
.
issuer
token
.
audience
=
params
[
:service
]
token
.
subject
=
current_user
.
try
(
:username
)
token
[
:access
]
=
access
token
end
def
access
return
unless
params
[
:scope
]
scope
=
process_scope
(
params
[
:scope
])
[
scope
].
compact
end
def
process_scope
(
scope
)
type
,
name
,
actions
=
scope
.
split
(
':'
,
3
)
actions
=
actions
.
split
(
','
)
case
type
when
'repository'
process_repository_access
(
type
,
name
,
actions
)
end
end
def
process_repository_access
(
type
,
name
,
actions
)
current_project
=
Project
.
find_with_namespace
(
name
)
return
unless
current_project
actions
=
actions
.
select
do
|
action
|
can_access?
(
current_project
,
action
)
end
{
type:
type
,
name:
name
,
actions:
actions
}
if
actions
end
def
can_access?
(
current_project
,
action
)
case
action
when
'pull'
current_project
==
project
||
can?
(
current_user
,
:download_code
,
current_project
)
when
'push'
current_project
==
project
||
can?
(
current_user
,
:push_code
,
current_project
)
else
false
end
end
def
registry
Gitlab
.
config
.
registry
end
end
end
lib/jwt/rsa_token.rb
0 → 100644
View file @
011a905a
module
Jwt
class
RSAToken
<
Token
attr_reader
:key_file
def
initialize
(
key_file
)
super
()
@key_file
=
key_file
end
def
encoded
headers
=
{
kid:
kid
}
JWT
.
encode
(
payload
,
key
,
'RS256'
,
headers
)
end
private
def
key_data
@key_data
||=
File
.
read
(
key_file
)
end
def
key
@key
||=
OpenSSL
::
PKey
::
RSA
.
new
(
key_data
)
end
def
kid
sha256
=
Digest
::
SHA256
.
new
sha256
.
update
(
key
.
public_key
.
to_der
)
payload
=
StringIO
.
new
(
sha256
.
digest
).
read
(
30
)
Base32
.
encode
(
payload
).
split
(
''
).
each_slice
(
4
).
each_with_object
([])
do
|
slice
,
mem
|
mem
<<
slice
.
join
end
.
join
(
':'
)
end
end
end
lib/jwt/token.rb
0 → 100644
View file @
011a905a
module
Jwt
class
Token
attr_accessor
:issuer
,
:subject
,
:audience
,
:id
attr_accessor
:issued_at
,
:not_before
,
:expire_time
def
initialize
@payload
=
{}
@id
=
SecureRandom
.
uuid
@issued_at
=
Time
.
now
@not_before
=
issued_at
-
5
.
seconds
@expire_time
=
issued_at
+
1
.
minute
end
def
[]
(
key
)
@payload
[
key
]
end
def
[]=
(
key
,
value
)
@payload
[
key
]
=
value
end
def
encoded
raise
NotImplementedError
end
def
payload
@payload
.
merge
(
default_payload
)
end
def
to_json
payload
.
to_json
end
private
def
default_payload
{
jti:
id
,
aud:
audience
,
sub:
subject
,
iss:
issuer
,
iat:
issued_at
.
to_i
,
nbf:
not_before
.
to_i
,
exp:
expire_time
.
to_i
}.
compact
end
end
end
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment