Maintenance: Improve package installation.

This commit is contained in:
Dominik Klein 2021-09-13 15:33:22 +02:00 committed by Thorsten Eckel
parent f86576c1e4
commit 57b9ac91f3
3 changed files with 120 additions and 23 deletions

View file

@ -3,6 +3,11 @@
</div> </div>
<div class="page-content"> <div class="page-content">
<p>
<%- @T('The installation of packages comes with security implications, because arbitrary code will be executed in the context of the Zammad application.') %>
<br>
<%- @T('Only packages from known, trusted and verfied sources should be installed.') %>
</p>
<p> <p>
<%- @T('After installing, updating or uninstalling packages the following commands need to be executed on the server:') %> <%- @T('After installing, updating or uninstalling packages the following commands need to be executed on the server:') %>
<ul> <ul>
@ -48,4 +53,4 @@
<% end %> <% end %>
</tbody> </tbody>
</table> </table>
</div> </div>

View file

@ -263,32 +263,37 @@ subsequently in a separate step.
) )
end end
# store package Transaction.execute do
if !data[:reinstall] # store package
package_db = Package.create(meta) if !data[:reinstall]
Store.add( package_db = Package.create(meta)
object: 'Package', Store.add(
o_id: package_db.id, object: 'Package',
data: package.to_json, o_id: package_db.id,
filename: "#{meta[:name]}-#{meta[:version]}.zpm", data: package.to_json,
preferences: {}, filename: "#{meta[:name]}-#{meta[:version]}.zpm",
created_by_id: UserInfo.current_user_id || 1, preferences: {},
) created_by_id: UserInfo.current_user_id || 1,
end )
end
# write files # write files
package['files'].each do |file| package['files'].each do |file|
permission = file['permission'] || '644' if !allowed_file_path?(file['location'])
content = Base64.decode64(file['content']) raise "Can't create file, because of not allowed file location: #{file['location']}!"
_write_file(file['location'], permission, content) end
end
# update package state permission = file['permission'] || '644'
package_db.state = 'installed' content = Base64.decode64(file['content'])
package_db.save _write_file(file['location'], permission, content)
end
# update package state
package_db.state = 'installed'
package_db.save
end
# prebuild assets # prebuild assets
package_db package_db
end end
@ -483,4 +488,9 @@ execute all pending package migrations at once
true true
end end
def self.allowed_file_path?(file)
file.exclude?('..') && file.exclude?('%2e%2e')
end
private_class_method :allowed_file_path?
end end

View file

@ -0,0 +1,82 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
RSpec.describe Package, type: :model do
let(:package_zpm_files_json) do
<<-JSON
[
{
"permission": "644",
"location": "example.rb",
"content": "YWJjw6TDtsO8w58="
},
{
"permission": "644",
"location": "app/controllers/test_controller.rb",
"content": "YWJjw6TDtsO8w58="
}
]
JSON
end
let(:package_zpm_json) do
<<-JSON
{
"name": "UnitTestSample",
"version": "1.0.1",
"vendor": "Zammad Foundation",
"license": "ABC",
"url": "https://zammad.org/",
"description": [
{
"language": "en",
"text": "some description"
}
],
"files": #{package_zpm_files_json}
}
JSON
end
context 'with different file locations' do
context 'with correct file locations' do
it 'installation should work' do
expect(described_class.install(string: package_zpm_json)).to be_truthy
end
end
shared_examples 'check not allowed file location' do |file_location|
let(:package_zpm_files_json) do
<<-JSON
[
{
"permission": "644",
"location": "example.rb",
"content": "YWJjw6TDtsO8w58="
},
{
"permission": "644",
"location": "#{file_location}",
"content": "YWJjw6TDtsO8w58="
}
]
JSON
end
it 'installation should raise a error and package/store should not be present, because of not allowed file location' do
expect { described_class.install(string: package_zpm_json) }
.to raise_error(RuntimeError)
.and change(described_class, :count).by(0)
.and change(Store, :count).by(0)
end
end
context "with not allowed file location part: '..'" do
include_examples 'check not allowed file location', '../../../../../tmp/test_controller.rb'
end
context "with not allowed file location part: '%2e%2e'" do
include_examples 'check not allowed file location', '%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/tmp/test_controller.rb'
end
end
end