Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
gitlab-ce
Commits
f8dea2e2
Commit
f8dea2e2
authored
Dec 03, 2018
by
Grzegorz Bizon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement migration strategy for token authenticatable
parent
a7fec177
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
144 additions
and
39 deletions
+144
-39
app/models/concerns/token_authenticatable_strategies/base.rb
app/models/concerns/token_authenticatable_strategies/base.rb
+8
-0
app/models/concerns/token_authenticatable_strategies/encrypted.rb
...ls/concerns/token_authenticatable_strategies/encrypted.rb
+17
-4
spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
...ncerns/token_authenticatable_strategies/encrypted_spec.rb
+119
-35
No files found.
app/models/concerns/token_authenticatable_strategies/base.rb
View file @
f8dea2e2
...
@@ -47,6 +47,14 @@ module TokenAuthenticatableStrategies
...
@@ -47,6 +47,14 @@ module TokenAuthenticatableStrategies
options
[
:fallback
]
==
true
options
[
:fallback
]
==
true
end
end
def
migrating?
unless
options
[
:migrating
].
in?
([
true
,
false
,
nil
])
raise
ArgumentError
,
'migrating: needs to be a boolean value!'
end
options
[
:migrating
]
==
true
end
def
self
.
fabricate
(
model
,
field
,
options
)
def
self
.
fabricate
(
model
,
field
,
options
)
if
options
[
:digest
]
&&
options
[
:encrypted
]
if
options
[
:digest
]
&&
options
[
:encrypted
]
raise
ArgumentError
,
'Incompatible options set!'
raise
ArgumentError
,
'Incompatible options set!'
...
...
app/models/concerns/token_authenticatable_strategies/encrypted.rb
View file @
f8dea2e2
...
@@ -2,14 +2,24 @@
...
@@ -2,14 +2,24 @@
module
TokenAuthenticatableStrategies
module
TokenAuthenticatableStrategies
class
Encrypted
<
Base
class
Encrypted
<
Base
def
initialize
(
*
)
super
if
migrating?
&&
fallback?
raise
ArgumentError
,
'`fallback` and `migration` options are not compatible!'
end
end
def
find_token_authenticatable
(
token
,
unscoped
=
false
)
def
find_token_authenticatable
(
token
,
unscoped
=
false
)
return
unless
token
return
unless
token
encrypted_value
=
Gitlab
::
CryptoHelper
.
aes256_gcm_encrypt
(
token
)
unless
migrating?
token_authenticatable
=
relation
(
unscoped
)
encrypted_value
=
Gitlab
::
CryptoHelper
.
aes256_gcm_encrypt
(
token
)
.
find_by
(
encrypted_field
=>
encrypted_value
)
token_authenticatable
=
relation
(
unscoped
)
.
find_by
(
encrypted_field
=>
encrypted_value
)
end
if
fallback?
if
migrating?
||
fallback?
token_authenticatable
||=
fallback_strategy
token_authenticatable
||=
fallback_strategy
.
find_token_authenticatable
(
token
)
.
find_token_authenticatable
(
token
)
end
end
...
@@ -39,6 +49,8 @@ module TokenAuthenticatableStrategies
...
@@ -39,6 +49,8 @@ module TokenAuthenticatableStrategies
end
end
def
get_token
(
instance
)
def
get_token
(
instance
)
return
fallback_strategy
.
get_token
(
instance
)
if
migrating?
encrypted_token
=
instance
.
read_attribute
(
encrypted_field
)
encrypted_token
=
instance
.
read_attribute
(
encrypted_field
)
token
=
Gitlab
::
CryptoHelper
.
aes256_gcm_decrypt
(
encrypted_token
)
token
=
Gitlab
::
CryptoHelper
.
aes256_gcm_decrypt
(
encrypted_token
)
...
@@ -49,6 +61,7 @@ module TokenAuthenticatableStrategies
...
@@ -49,6 +61,7 @@ module TokenAuthenticatableStrategies
raise
ArgumentError
unless
token
.
present?
raise
ArgumentError
unless
token
.
present?
instance
[
encrypted_field
]
=
Gitlab
::
CryptoHelper
.
aes256_gcm_encrypt
(
token
)
instance
[
encrypted_field
]
=
Gitlab
::
CryptoHelper
.
aes256_gcm_encrypt
(
token
)
instance
[
token_field
]
=
token
if
migrating?
instance
[
token_field
]
=
nil
if
fallback?
instance
[
token_field
]
=
nil
if
fallback?
token
token
end
end
...
...
spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb
View file @
f8dea2e2
...
@@ -3,7 +3,6 @@ require 'spec_helper'
...
@@ -3,7 +3,6 @@ require 'spec_helper'
describe
TokenAuthenticatableStrategies
::
Encrypted
do
describe
TokenAuthenticatableStrategies
::
Encrypted
do
let
(
:model
)
{
double
(
:model
)
}
let
(
:model
)
{
double
(
:model
)
}
let
(
:instance
)
{
double
(
:instance
)
}
let
(
:instance
)
{
double
(
:instance
)
}
let
(
:options
)
{
{
fallback:
true
}
}
let
(
:encrypted
)
do
let
(
:encrypted
)
do
Gitlab
::
CryptoHelper
.
aes256_gcm_encrypt
(
'my-value'
)
Gitlab
::
CryptoHelper
.
aes256_gcm_encrypt
(
'my-value'
)
...
@@ -13,60 +12,145 @@ describe TokenAuthenticatableStrategies::Encrypted do
...
@@ -13,60 +12,145 @@ describe TokenAuthenticatableStrategies::Encrypted do
described_class
.
new
(
model
,
'some_field'
,
options
)
described_class
.
new
(
model
,
'some_field'
,
options
)
end
end
describe
'.new'
do
context
'when fallback and migration strategies are set'
do
let
(
:options
)
{
{
fallback:
true
,
migrating:
true
}
}
it
'raises an error'
do
expect
{
subject
}.
to
raise_error
ArgumentError
,
/not compatible/
end
end
end
describe
'#find_token_authenticatable'
do
describe
'#find_token_authenticatable'
do
it
'finds the encrypted resource by cleartext'
do
context
'when using fallback strategy'
do
allow
(
model
).
to
receive
(
:find_by
)
let
(
:options
)
{
{
fallback:
true
}
}
.
with
(
'some_field_encrypted'
=>
encrypted
)
.
and_return
(
'encrypted resource'
)
it
'finds the encrypted resource by cleartext'
do
allow
(
model
).
to
receive
(
:find_by
)
.
with
(
'some_field_encrypted'
=>
encrypted
)
.
and_return
(
'encrypted resource'
)
expect
(
subject
.
find_token_authenticatable
(
'my-value'
))
.
to
eq
'encrypted resource'
end
expect
(
subject
.
find_token_authenticatable
(
'my-value'
))
it
'uses fallback strategy when encrypted token cannot be found'
do
.
to
eq
'encrypted resource'
allow
(
subject
.
send
(
:fallback_strategy
))
.
to
receive
(
:find_token_authenticatable
)
.
and_return
(
'plaintext resource'
)
allow
(
model
).
to
receive
(
:find_by
)
.
with
(
'some_field_encrypted'
=>
encrypted
)
.
and_return
(
nil
)
expect
(
subject
.
find_token_authenticatable
(
'my-value'
))
.
to
eq
'plaintext resource'
end
end
end
it
'uses fallback strategy when encrypted token cannot be found'
do
context
'when using migration strategy'
do
allow
(
subject
.
send
(
:fallback_strategy
))
let
(
:options
)
{
{
migrating:
true
}
}
.
to
receive
(
:find_token_authenticatable
)
.
and_return
(
'plaintext resource'
)
it
'finds the cleartext resource by cleartext'
do
allow
(
model
).
to
receive
(
:find_by
)
.
with
(
'some_field'
=>
'my-value'
)
.
and_return
(
'cleartext resource'
)
allow
(
model
).
to
receive
(
:find_by
)
expect
(
subject
.
find_token_authenticatable
(
'my-value'
)
)
.
with
(
'some_field_encrypted'
=>
encrypted
)
.
to
eq
'cleartext resource'
.
and_return
(
nil
)
end
expect
(
subject
.
find_token_authenticatable
(
'my-value'
))
it
'returns nil if resource cannot be found'
do
.
to
eq
'plaintext resource'
allow
(
model
).
to
receive
(
:find_by
)
.
with
(
'some_field'
=>
'my-value'
)
.
and_return
(
nil
)
expect
(
subject
.
find_token_authenticatable
(
'my-value'
))
.
to
be_nil
end
end
end
end
end
describe
'#get_token'
do
describe
'#get_token'
do
it
'returns decrypted token when an encrypted token is present'
do
context
'when using fallback strategy'
do
allow
(
instance
).
to
receive
(
:read_attribute
)
let
(
:options
)
{
{
fallback:
true
}
}
.
with
(
'some_field_encrypted'
)
.
and_return
(
encrypted
)
it
'returns decrypted token when an encrypted token is present'
do
allow
(
instance
).
to
receive
(
:read_attribute
)
.
with
(
'some_field_encrypted'
)
.
and_return
(
encrypted
)
expect
(
subject
.
get_token
(
instance
)).
to
eq
'my-value'
end
expect
(
subject
.
get_token
(
instance
)).
to
eq
'my-value'
it
'returns the plaintext token when encrypted token is not present'
do
allow
(
instance
).
to
receive
(
:read_attribute
)
.
with
(
'some_field_encrypted'
)
.
and_return
(
nil
)
allow
(
instance
).
to
receive
(
:read_attribute
)
.
with
(
'some_field'
)
.
and_return
(
'cleartext value'
)
expect
(
subject
.
get_token
(
instance
)).
to
eq
'cleartext value'
end
end
end
it
'returns the plaintext token when encrypted token is not present'
do
context
'when using migration strategy'
do
allow
(
instance
).
to
receive
(
:read_attribute
)
let
(
:options
)
{
{
migrating:
true
}
}
.
with
(
'some_field_encrypted'
)
.
and_return
(
nil
)
it
'returns cleartext token when an encrypted token is present'
do
allow
(
instance
).
to
receive
(
:read_attribute
)
.
with
(
'some_field_encrypted'
)
.
and_return
(
encrypted
)
allow
(
instance
).
to
receive
(
:read_attribute
)
.
with
(
'some_field'
)
.
and_return
(
'my-cleartext-value'
)
expect
(
subject
.
get_token
(
instance
)).
to
eq
'my-cleartext-value'
end
it
'returns the cleartext token when encrypted token is not present'
do
allow
(
instance
).
to
receive
(
:read_attribute
)
.
with
(
'some_field_encrypted'
)
.
and_return
(
nil
)
allow
(
instance
).
to
receive
(
:read_attribute
)
allow
(
instance
).
to
receive
(
:read_attribute
)
.
with
(
'some_field'
)
.
with
(
'some_field'
)
.
and_return
(
'cleartext value'
)
.
and_return
(
'cleartext value'
)
expect
(
subject
.
get_token
(
instance
)).
to
eq
'cleartext value'
expect
(
subject
.
get_token
(
instance
)).
to
eq
'cleartext value'
end
end
end
end
end
describe
'#set_token'
do
describe
'#set_token'
do
it
'writes encrypted token and removes plaintext token and returns it'
do
context
'when using fallback strategy'
do
expect
(
instance
).
to
receive
(
:[]=
)
let
(
:options
)
{
{
fallback:
true
}
}
.
with
(
'some_field_encrypted'
,
encrypted
)
expect
(
instance
).
to
receive
(
:[]=
)
it
'writes encrypted token and removes plaintext token and returns it'
do
.
with
(
'some_field'
,
nil
)
expect
(
instance
).
to
receive
(
:[]=
)
.
with
(
'some_field_encrypted'
,
encrypted
)
expect
(
instance
).
to
receive
(
:[]=
)
.
with
(
'some_field'
,
nil
)
expect
(
subject
.
set_token
(
instance
,
'my-value'
)).
to
eq
'my-value'
end
end
context
'when using migration strategy'
do
let
(
:options
)
{
{
migrating:
true
}
}
it
'writes encrypted token and writes plaintext token'
do
expect
(
instance
).
to
receive
(
:[]=
)
.
with
(
'some_field_encrypted'
,
encrypted
)
expect
(
instance
).
to
receive
(
:[]=
)
.
with
(
'some_field'
,
'my-value'
)
expect
(
subject
.
set_token
(
instance
,
'my-value'
)).
to
eq
'my-value'
expect
(
subject
.
set_token
(
instance
,
'my-value'
)).
to
eq
'my-value'
end
end
end
end
end
end
end
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