Skip to content

Commit

Permalink
Merge branch 'master' into depfu/update/active_model_serializers-0.10.15
Browse files Browse the repository at this point in the history
  • Loading branch information
digitaltom authored Dec 17, 2024
2 parents 0246a92 + c386c36 commit c81bd49
Show file tree
Hide file tree
Showing 22 changed files with 235 additions and 35 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/lint-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,12 @@ jobs:
- name: Run core tests
run: |
bundle exec rake test:core
- name: Run core tests with sqlite
run: |
sed -i 's/adapter: mysql2/adapter: sqlite3/' config/rmt.yml
bundle exec rake test:core
- name: Run PubCloud engines tests
run: |
bundle exec rake test:engines
Expand Down
10 changes: 10 additions & 0 deletions app/controllers/api/connect/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,14 @@ def authenticate_with_token
end
end

def system_token_header
headers[SYSTEM_TOKEN_HEADER] = @system.system_token
end

def refresh_system_token
if system_tokens_enabled?
@system.update(system_token: SecureRandom.uuid)
system_token_header
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class Api::Connect::V3::Systems::ProductsController < Api::Connect::BaseControll
before_action :check_product_service_and_repositories, only: %i[show activate]
before_action :load_subscription, only: %i[activate upgrade]
before_action :check_base_product_dependencies, only: %i[activate upgrade show]
after_action :refresh_system_token, only: %i[activate upgrade], if: -> { request.headers.key?(SYSTEM_TOKEN_HEADER) }

def activate
create_product_activation
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class Api::Connect::V3::Systems::SystemsController < Api::Connect::BaseController

before_action :authenticate_system
after_action :refresh_system_token, only: [:update], if: -> { request.headers.key?(SYSTEM_TOKEN_HEADER) }

def update
if params[:online_at].present?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class Api::Connect::V4::Systems::ProductsController < Api::Connect::V3::Systems::ProductsController

after_action :refresh_system_token, only: %i[activate upgrade synchronize destroy], if: -> { request.headers.key?(SYSTEM_TOKEN_HEADER) }
def destroy
if @product.base?
raise ActionController::TranslatedError.new(N_('The product "%s" is a base product and cannot be deactivated'), @product.name)
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ def authenticate_system(skip_on_duplicated: false)
update_user_agent

# If SYSTEM_TOKEN_HEADER is present, RMT assumes the client uses a SUSEConnect version
# that supports this feature. In this case, refresh the token and include it in the response.
# that supports this feature.
if system_tokens_enabled? && request.headers.key?(SYSTEM_TOKEN_HEADER)
@system.update(last_seen_at: Time.zone.now, system_token: SecureRandom.uuid)
headers[SYSTEM_TOKEN_HEADER] = @system.system_token
@system.update(last_seen_at: Time.zone.now)
system_token_header
# only update last_seen_at each 3 minutes,
# so that a system that calls SCC every second doesn't write + lock the database row
elsif !@system.last_seen_at || @system.last_seen_at < 3.minutes.ago
Expand Down
5 changes: 3 additions & 2 deletions app/models/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ class Repository < ApplicationRecord
class << self

def remove_suse_repos_without_tokens!
where(auth_token: nil).where('external_url LIKE ?', 'https://updates.suse.com%').delete_all
where(auth_token: nil).where("external_url LIKE '%.suse.com%'").where(installer_updates: 0).where.not(scc_id: nil).delete_all
end

# Mangles remote repo URL to make a nicer local path, see specs for examples
def make_local_path(url)
uri = URI(url)
path = uri.path.to_s
path.gsub!(%r{^/repo}, '') if (uri.hostname == 'updates.suse.com')
# drop '/repo' from SLE11 paths, to avoid double /repo/repo in local storage path.
path.gsub!(%r{^/repo/\$RCE/}, '/$RCE/')
(path == '') ? '/' : path
end

Expand Down
2 changes: 1 addition & 1 deletion config/rmt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ database_test:
database: rmt_test

scc:
host: https://scc.suse.com/connect
host: <%= ENV.fetch('SCC_HOST'){ 'https://scc.suse.com/connect' } %>
username: <%= ENV['SCC_USERNAME'] %>
password: <%= ENV['SCC_PASSWORD'] %>
sync_systems: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ def check
# belongs to a PAYG or BYOS instance
verification_provider = InstanceVerification.provider.new(
logger,
nil,
request,
nil,
params[:metadata]
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ def instance_identifier
end

def allowed_extension?
# method to check if a product (extension) meet the criteria
# to be acivated on SCC or not, i.e. LTSS in Azure Basic VM
# method to check if a product (extension) meets the criteria
# to be activated on SCC or not, i.e. LTSS in Azure Basic VM
true
end
end
5 changes: 5 additions & 0 deletions package/obs/rmt-server.changes
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ Wed Oct 30 09:01:32 UTC 2024 - Natnael Getahun <natnael.getahun@suse.com>
* rmt-server-pubcloud:
* Fix LTSS product verification (bsc#1230154)
* Fix activations check when no product info is available (bsc#1230157)
* Fix Azure SCC connection (bsc#1233314)
* Deny access of Azure Basic type images to LTSS
* Allow SLE Micro system to access SLES repositories (bsc#1230419)
* Skip system token rotation in read-only APIs
* Enable RMT to handle the new dl.suse.com CDN domain (bsc#1234641)

-------------------------------------------------------------------
Wed Aug 21 15:28:43 UTC 2024 - Jesús Bermúdez Velázquez <jesus.bv@suse.com>
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/rmt/cli/smt_importer_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'rails_helper'
require 'rmt/cli/smt_importer'

describe RMT::CLI::SMTImporter do
describe RMT::CLI::SMTImporter, :skip_sqlite do
let(:data_dir) { File.join(Dir.pwd, 'spec/fixtures/files/csv') }
let(:no_systems) { false }
let(:importer) { described_class.new(data_dir, no_systems) }
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/rmt/lockfile_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
RSpec.describe RMT::Lockfile do
let(:lock_name) { nil }

describe '#lock' do
describe '#lock', :skip_sqlite do
subject(:lock) { described_class.lock(lock_name) { nil } }

context 'with an unnamed lock' do
Expand Down
19 changes: 17 additions & 2 deletions spec/lib/rmt/scc_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@
described_class.new.sync
end

it 'removes existing predecessor associations' do
it 'removes existing predecessor associations', :skip_sqlite do
expect { ProductPredecessorAssociation.find(existing_association.id) }.to raise_error(ActiveRecord::RecordNotFound)
end
end
Expand All @@ -261,7 +261,18 @@
:repository,
:with_products,
auth_token: nil,
external_url: 'https://example.com/repos/not/updates.suse.com/'
external_url: 'https://installer-updates.suse.com/repos/not/updates',
installer_updates: true
)
end
let!(:custom_repo) do
FactoryBot.create(
:repository,
:with_products,
auth_token: nil,
external_url: 'http://customer.com/stuff.suse.com/x86',
installer_updates: false,
scc_id: nil
)
end

Expand Down Expand Up @@ -297,6 +308,10 @@ def scc
it 'other repos without auth_tokens persist' do
expect { other_repo_without_token.reload }.not_to raise_error
end

it 'custom repos without auth_tokens persist' do
expect { custom_repo.reload }.not_to raise_error
end
end

describe '#export' do
Expand Down
6 changes: 3 additions & 3 deletions spec/models/repository_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@
expect(friendly_id).to eq('my-repo-100000')
end

it 'appends with unicode within the chain' do
it 'appends with unicode within the chain', :skip_sqlite do
create(:repository, friendly_id: 'my-repo')
create(:repository, friendly_id: 'my-repö-1')
expect(friendly_id).to eq('my-repo-2')
Expand All @@ -165,13 +165,13 @@
expect(friendly_id).to eq('dümmy-repö')
end

it 'appends with unicode within the chain' do
it 'appends with unicode within the chain', :skip_sqlite do
create(:repository, friendly_id: 'dummy-repo')
create(:repository, friendly_id: 'dümmy-repö-1')
expect(friendly_id).to eq('dümmy-repö-2')
end

it 'correctly appends' do
it 'correctly appends', :skip_sqlite do
create(:repository, friendly_id: 'dummy-repo')
create(:repository, friendly_id: 'dummy-repo-1')
expect(friendly_id).to eq('dümmy-repö-2')
Expand Down
6 changes: 6 additions & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@
config.filter_rails_from_backtrace!
# arbitrary gems may also be filtered via:
# config.filter_gems_from_backtrace("gem name")

# Skipping some tests when running with (experimental) sqlite backend.
# Some tests / code parts are using specific mysql behavior
if ActiveRecord::Base.connection.adapter_name == 'SQLite'
config.filter_run_excluding skip_sqlite: true
end
end

Shoulda::Matchers.configure do |config|
Expand Down
19 changes: 2 additions & 17 deletions spec/requests/api/connect/base_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,6 @@ def require_product
end
end

shared_examples 'updates the system token' do
it 'updates the system token' do
allow(SecureRandom).to receive(:uuid).and_return(new_system_token)

expect { get :service, params: { id: 1 } }
.to change { system.reload.system_token }
.from(current_system_token).to(new_system_token)
end
end

shared_examples "does not update the old system's token" do
it 'does not update the system token' do
Expand All @@ -74,8 +65,6 @@ def require_product

shared_examples 'creates a duplicate system' do
it 'creates a new System (duplicate)' do
allow(SecureRandom).to receive(:uuid).and_return(new_system_token)

expect { get :service, params: { id: 1 } }
.to change { System.get_by_credentials(system.login, system.password).count }
.by(1)
Expand All @@ -85,7 +74,6 @@ def require_product
expect(duplicate_system).not_to eq(system)
expect(duplicate_system.activations.count).to eq(system.activations.count)
expect(duplicate_system.system_token).not_to eq(system.system_token)
expect(duplicate_system.system_token).to eq(new_system_token)
end
end

Expand Down Expand Up @@ -182,8 +170,7 @@ def require_product
let(:system) { create(:system, hostname: 'system') }

include_examples 'does not create a duplicate system'
include_examples 'updates the system token'
include_examples 'responds with a new token'
include_examples "does not update the old system's token"
end

context 'when the system has a token and the header matches it' do
Expand All @@ -193,8 +180,7 @@ def require_product
let(:system) { create(:system, hostname: 'system', system_token: current_system_token) }

include_examples 'does not create a duplicate system'
include_examples 'updates the system token'
include_examples 'responds with a new token'
include_examples "does not update the old system's token"
end

context 'when the system has a token and the header is blank' do
Expand All @@ -208,7 +194,6 @@ def require_product

include_examples "does not update the old system's token"
include_examples 'creates a duplicate system'
include_examples 'responds with a new token'
end

context 'when the system has a token and the header does not match it' do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,28 @@
expect(system.scc_synced_at).to be_nil
end
end

context 'system token header' do
context 'when system token header is present in request' do
let(:token_headers) do
authenticated_headers.merge({ 'System-Token' => 'some_token' })
end

it 'sets system token in response headers' do
get url, headers: token_headers
expect(response.code).to eq '200'
expect(response.headers).to include('System-Token')
expect(response.headers['System-Token']).not_to be_nil
expect(response.headers['System-Token']).not_to be_empty
end

it 'does not set system token header if no system token header in request' do
get url, headers: authenticated_headers

expect(response.code).to eq '200'
expect(response.headers).not_to include('System-Token')
end
end
end
end
end
55 changes: 55 additions & 0 deletions spec/requests/api/connect/v3/systems/products_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,26 @@
end
end

shared_context 'activate with token in request headers' do
let(:payload) do
{
identifier: product.identifier,
version: product.version,
arch: product.arch,
token: regcode
}
end

before { post url, headers: { 'System-Token' => 'existing_token' }.merge(headers), params: payload }
subject do
Struct.new(:body, :code, :headers).new(
JSON.parse(response.body, symbolize_names: true),
response.status,
response.headers
)
end
end

context 'unknown subscription' do
include_context 'with subscriptions'
let(:regcode) { 'NOT-EXISTING-SUBSCRIPTION' }
Expand Down Expand Up @@ -173,6 +193,17 @@
expect(activation.product).to eq(product)
end
end

context 'token update after activation is success' do
let(:subscription) { create :subscription, :with_products }
let(:product) { subscription.products.first }
let(:regcode) { subscription.regcode }

include_context 'activate with token in request headers'
its(:code) { is_expected.to eq(201) }
its(:headers) { is_expected.to include('System-Token') }
its(:headers['System-Token']) { is_expected.not_to eq('existing_token') }
end
end
end

Expand Down Expand Up @@ -225,6 +256,18 @@
its(:body) { is_expected.to eq(serialized_json) }
end

describe 'response header should contain token' do
subject { response }

let(:token_headers) do
headers.merge({ 'System-Token' => 'some_token' })
end

before { get url, headers: token_headers, params: payload }
its(:code) { is_expected.to eq('200') }
its(:headers) { is_expected.to include('System-Token') }
end

describe 'response with "-" in version' do
subject { response }

Expand Down Expand Up @@ -339,6 +382,18 @@
system.reload
end

it 'calls refresh_system_token after upgrade action when system token header is present' do
put url, headers: headers.merge('System-Token' => 'test_token'), params: payload
expect(response.code).to eq('201')
expect(response.headers).to include('System-Token')
expect(response.headers['System-Token']).not_to eq('test_token')
end

it 'No update in token after upgrade action when system token header is absent' do
put url, headers: headers, params: payload
expect(response.code).to eq('201')
expect(response.headers).not_to include('System-Token')
end
context 'new product' do
its(:code) { is_expected.to eq('201') }
its(:body) { is_expected.to eq(serialized_json) }
Expand Down
Loading

0 comments on commit c81bd49

Please sign in to comment.