Skip to content

Commit

Permalink
Fixes #36827 - Tokens for container registries now return OAuth2-comp…
Browse files Browse the repository at this point in the history
…atible headers (#10768)

- 'expires_at' has been depricated and is slated for removal in 4.13. We're keeping it for now to maintain smart proxy upgrade compatibility.
- 'expires_at' is now 'expires_in'. This represents second count after issued_at time when the token expires.
- All token times are now rendered in rfc3339 format.
  • Loading branch information
qcjames53 authored Nov 6, 2023
1 parent e0145f8 commit ad42463
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def authorize_repository_read

def token
if !require_user_authorization?
personal_token = OpenStruct.new(token: 'unauthenticated', issued_at: Time.now, expires_at: Time.now + 3)
personal_token = OpenStruct.new(token: 'unauthenticated', issued_at: Time.now, expires_at: 3.minutes.from_now)
else
personal_token = PersonalAccessToken.where(user_id: User.current.id, name: 'registry').first
if personal_token.nil?
Expand All @@ -147,8 +147,21 @@ def token
end
end

create_time = (personal_token.created_at || personal_token.issued_at).to_time
expiry_time = personal_token.expires_at.to_time
expiration_seconds = (expiry_time - create_time).to_int # result already in seconds

response.headers['Docker-Distribution-API-Version'] = 'registry/2.0'
render json: { token: personal_token.token, expires_at: personal_token.expires_at, issued_at: personal_token.created_at }
render json: {
token: personal_token.token,
expires_in: expiration_seconds,
issued_at: create_time.rfc3339,

# We're keeping the 'expires_at' field for now to maintain compatibility with existing
# smart-proxies during 4.11 upgrades. This is not a part of OAuth2 spec.
# TODO - Remove 'expires_at' in Katello 4.13 or later.
expires_at: expiry_time.rfc3339
}
end

def pull_manifest
Expand Down
32 changes: 22 additions & 10 deletions test/controllers/api/registry/registry_proxies_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,16 @@ def setup_permissions
PersonalAccessToken.expects(:where)
.with(user_id: User.current.id, name: 'registry')
.returns([])
expiration = Time.now
issue_time = Time.now
expiry_time = 30.minutes.from_now
tolerance = 3.seconds

token = mock('token')
token.stubs(:token).returns("12345")
token.stubs(:generate_token).returns("12345")
token.stubs(:user_id).returns(User.current.id)
token.stubs(:expires_at).returns("#{expiration}")
token.stubs(:created_at).returns("#{expiration}")
token.stubs(:expires_at).returns("#{expiry_time.rfc3339}")
token.stubs(:created_at).returns("#{issue_time.rfc3339}")
token.stubs('save!').returns(true)
PersonalAccessToken.expects(:new).returns(token)

Expand All @@ -151,18 +154,24 @@ def setup_permissions
assert_equal 'registry/2.0', response.headers['Docker-Distribution-API-Version']
body = JSON.parse(response.body)
assert_equal "12345", body['token']
assert_equal "#{expiration}", body['expires_at']
assert_equal "#{expiration}", body['issued_at']

response_issue_time = body['issued_at'].to_time
response_expiry_time = response_issue_time + body['expires_in'].seconds
assert (response_expiry_time - tolerance) < expiry_time
assert (response_expiry_time + tolerance) > expiry_time
end

it "token - has 'registry' token" do
expiration = Time.now
issue_time = Time.now
expiry_time = 30.minutes.from_now
tolerance = 3.seconds

token = mock('token')
token.stubs(:token).returns("12345")
token.stubs(:generate_token).returns("12345")
token.stubs(:user_id).returns(User.current.id)
token.stubs(:expires_at).returns("#{expiration}")
token.stubs(:created_at).returns("#{expiration}")
token.stubs(:expires_at).returns(expiry_time.rfc3339)
token.stubs(:created_at).returns(issue_time.rfc3339)
token.stubs('save!').returns(true)
token.expects('expires_at=').returns(true)
PersonalAccessToken.expects(:where)
Expand All @@ -175,8 +184,11 @@ def setup_permissions
assert_equal 'registry/2.0', response.headers['Docker-Distribution-API-Version']
body = JSON.parse(response.body)
assert_equal "12345", body['token']
assert_equal "#{expiration}", body['expires_at']
assert_equal "#{expiration}", body['issued_at']

response_issue_time = body['issued_at'].to_time
response_expiry_time = response_issue_time + body['expires_in'].seconds
assert (response_expiry_time - tolerance) < expiry_time
assert (response_expiry_time + tolerance) > expiry_time
end

it "token - unscoped is authorized" do
Expand Down

0 comments on commit ad42463

Please sign in to comment.