/config/environments/development.rb
/config/environments/test.rb
/config/environments/production.rb
+/config/application.yml
/config/piwik.yml
class UsersController < ApplicationController
skip_before_filter :find_object_by_uuid, :only => :welcome
skip_around_filter :thread_with_mandatory_api_token, :only => :welcome
+ before_filter :ensure_current_user_is_admin, only: :sudo
def welcome
if current_user
end
end
+ def show_pane_list
+ if current_user.andand.is_admin
+ super | %w(Admin)
+ else
+ super
+ end
+ end
+
+ def sudo
+ resp = $arvados_api_client.api(ApiClientAuthorization, '', {
+ api_client_authorization: {
+ owner_uuid: @object.uuid
+ }
+ })
+ redirect_to root_url(api_token: resp[:api_token])
+ end
+
def home
@showallalerts = false
@my_ssh_keys = AuthorizedKey.where(authorized_user_uuid: current_user.uuid)
--- /dev/null
+<p>As an admin, you can log in as this user. When you’ve
+finished, you will need to log out and log in again with your own
+account.</p>
+
+<blockquote>
+<%= button_to "Log in as #{@object.full_name}", sudo_user_url(id: @object.uuid), class: 'btn btn-primary' %>
+</blockquote>
--- /dev/null
+# Do not use this file for site configuration. Create config.yml
+# instead (see application.yml.example).
+
+development:
+ cache_classes: false
+ whiny_nils: true
+ consider_all_requests_local: true
+ action_controller.perform_caching: false
+ action_mailer.raise_delivery_errors: false
+ active_support.deprecation: :log
+ action_dispatch.best_standards_support: :builtin
+ active_record.mass_assignment_sanitizer: :strict
+ active_record.auto_explain_threshold_in_seconds: 0.5
+ assets.compress: false
+ assets.debug: true
+ profiling_enabled: true
+ site_name: Workbench:dev
+
+production:
+ force_ssl: true
+ cache_classes: true
+ consider_all_requests_local: false
+ action_controller.perform_caching: true
+ serve_static_assets: false
+ assets.compress: true
+ assets.compile: false
+ assets.digest: true
+ i18n.fallbacks: true
+ active_support.deprecation: :notify
+ profiling_enabled: false
+
+ arvados_insecure_https: false
+
+ data_import_dir: /data/arvados-workbench-upload/data
+ data_export_dir: /data/arvados-workbench-download/data
+
+ site_name: Arvados Workbench
+
+test:
+ cache_classes: true
+ serve_static_assets: true
+ static_cache_control: public, max-age=3600
+ whiny_nils: true
+ consider_all_requests_local: true
+ action_controller.perform_caching: false
+ action_dispatch.show_exceptions: false
+ action_controller.allow_forgery_protection: false
+ action_mailer.delivery_method: :test
+ active_record.mass_assignment_sanitizer: :strict
+ active_support.deprecation: :stderr
+ profiling_enabled: false
+ secret_token: <%= rand(2**256).to_s(36) %>
+
+ site_name: Workbench:test
+
+common:
+ data_import_dir: /tmp/arvados-workbench-upload
+ data_export_dir: /tmp/arvados-workbench-download
+ arvados_login_base: https://arvados.local/login
+ arvados_v1_base: https://arvados.local/arvados/v1
+ arvados_insecure_https: true
+ activation_contact_link: mailto:info@arvados.org
+ arvados_docsite: http://doc.arvados.org
+ arvados_theme: default
+ show_user_agreement_inline: false
+ secret_token: ~
--- /dev/null
+# Copy this file to application.yml and edit to suit.
+#
+# Consult application.default.yml for the full list of configuration
+# settings.
+#
+# The order of precedence is:
+# 1. config/environments/{RAILS_ENV}.rb (deprecated)
+# 2. Section in application.yml corresponding to RAILS_ENV (e.g., development)
+# 3. Section in application.yml called "common"
+# 4. Section in application.default.yml corresponding to RAILS_ENV
+# 5. Section in application.default.yml called "common"
+
+common:
+ # At minimum, you need a nice long randomly generated secret_token here.
+ secret_token: ~
+
+ # You probably also want to point to your API server.
+ arvados_login_base: https://arvados.local:3000/login
+ arvados_v1_base: https://arvados.local:3000/arvados/v1
+ arvados_insecure_https: true
--- /dev/null
+$application_config = {}
+
+%w(application.default application).each do |cfgfile|
+ path = "#{::Rails.root.to_s}/config/#{cfgfile}.yml"
+ if File.exists? path
+ yaml = ERB.new(IO.read path).result(binding)
+ confs = YAML.load(yaml)
+ $application_config.merge!(confs['common'] || {})
+ $application_config.merge!(confs[::Rails.env.to_s] || {})
+ end
+end
+
+ArvadosWorkbench::Application.configure do
+ nils = []
+ $application_config.each do |k, v|
+ # "foo.bar: baz" --> { config.foo.bar = baz }
+ cfg = config
+ ks = k.split '.'
+ k = ks.pop
+ ks.each do |kk|
+ cfg = cfg.send(kk)
+ end
+ if cfg.respond_to?(k.to_sym) and !cfg.send(k).nil?
+ # Config must have been set already in environments/*.rb.
+ #
+ # After config files have been migrated, this mechanism should
+ # be deprecated, then removed.
+ elsif v.nil?
+ # Config variables are not allowed to be nil. Make a "naughty"
+ # list, and present it below.
+ nils << k
+ else
+ cfg.send "#{k}=", v
+ end
+ end
+ if !nils.empty?
+ raise <<EOS
+Refusing to start in #{::Rails.env.to_s} mode with missing configuration.
+
+The following configuration settings must be specified in
+config/application.yml:
+* #{nils.join "\n* "}
+
+EOS
+ end
+end
resources :users do
get 'home', :on => :member
get 'welcome', :on => :collection
+ post 'sudo', :on => :member
end
resources :logs
resources :factory_jobs
--- /dev/null
+namespace :config do
+ desc 'Ensure site configuration has all required settings'
+ task check: :environment do
+ $application_config.sort.each do |k, v|
+ $stderr.puts "%-32s %s" % [k, eval("Rails.configuration.#{k}")]
+ end
+ end
+end
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/api_client_authorization@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/api_client_authorizations@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/authorized_key@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/authorized_keys@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/commit@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/commits@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/commit_ancestor@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/commit_ancestors@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/group@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/groups@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/human@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/humans@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/keep_disk@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/keep_disks@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/log@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/logs@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/node@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/nodes@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/pipeline_instance@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/pipeline_instances@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/pipeline_template@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/pipeline_templates@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/repository@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/repositories@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/specimen@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/specimens@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/trait@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/traits@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/user@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/users@
h2. Creation
See "REST methods for working with Arvados resources":/api/methods.html
-API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/virtual_machine@
+API endpoint base: @https://{{ site.arvados_api_host }}/arvados/v1/virtual_machines@
h2. Creation
navorder: 1
...
-{% include 'alert_stub' %}
-
# API server setup
-## Prerequisites
+## Prerequisites:
-1. A GNU/linux (virtual) machine
+1. A GNU/Linux (virtual) machine
2. A domain name for your api server
+3. Ruby >= 2.0.0
+4. Bundler
## Download the source tree
-Please follow the instructions on the [Download page](https://arvados.org/projects/arvados/wiki/Download) in the wiki.
+ git clone https://github.com/curoverse/arvados.git
+
+See also: [Downloading the source code](https://arvados.org/projects/arvados/wiki/Download) on the Arvados wiki.
## Configure the API server
Next, configure the database:
- cp config/database.yml.sample config/database.yml
+ cp -i config/database.yml.sample config/database.yml
-Edit database.yml to your liking and make sure the database and db user exist.
+Edit `database.yml` to your liking and make sure the database and db user exist.
Then set up the database:
RAILS_ENV=production rake db:setup
Then set up omniauth:
- cp config/initializers/omniauth.rb.example config/initializers/omniauth.rb
+ cp -i config/initializers/omniauth.rb.example config/initializers/omniauth.rb
-Edit config/initializers/omniauth.rb. Choose an *APP_SECRET* and *APP_ID*. Also set
-*CUSTOM_PROVIDER_URL*.
+Edit `config/initializers/omniauth.rb`. Choose an *APP_SECRET* and
+*APP_ID*. Also set *CUSTOM_PROVIDER_URL*.
Make sure your Omniauth provider knows about your *APP_ID* and *APP_SECRET*
combination.
-You also need to update config/initializers/secret_token.rb. Generate a new secret with
+You also need to update `config/initializers/secret_token.rb`.
+Generate a new secret with
rake secret
-and put it in config/initializers/secret_token.rb:
+and put it in `config/initializers/secret_token.rb`:
Server::Application.config.secret_token = 'your-new-secret-here'
-Finally, edit the main configuration:
+Edit the main configuration:
- cp config/environments/production.rb.example config/environments/production.rb
+ cp -i config/config.yml.example config/config.yml
-First, you want to make sure that
+First, you want to make sure that
- config.uuid_prefix
+ uuid_prefix
-is set to a unique 5-digit hex string. You can replace the 'cfi-aws-0' string
-with a string of your choice to make that happen.
+is set to a unique 5-character alphanumeric string. An example is
+given that generates a 5-character string based on a hash of your
+hostname.
-The *config.uuid_prefix* string is a unique identifier for your API server. It
-also serves as the first part of the hostname for your API server, for instance
+The `uuid_prefix` is a unique identifier for your API server. It also
+serves as the first part of the hostname for your API server, for
+instance
{{ site.arvados_api_host }}
-You should use your own domain instead of arvadosapi.com
-
-Second, unless you are running on AWS, you will want to change the definition of
-
- config.compute_node_nameservers
+For a development site, use your own domain instead of arvadosapi.com.
-If you know your nameservers and they are fixed, you can hardcode them, and
-make sure to remove the code that tries to look them up from the AWS metadata:
+You will also want to change `compute_node_nameservers` to suit your
+environment.
- config.compute_node_nameservers = ['1.2.3.4','2.3.4.5','3.4.5.6']
- #require 'net/http'
- #config.compute_node_nameservers = ['local', 'public'].collect do |iface|
- # Net::HTTP.get(URI("http://169.254.169.254/latest/meta-data/#{iface}-ipv4")).match(/^[\d\.]+$/)[0]
- #end << '172.16.0.23'
+Consult `config.defaults.yml` for a full list of configuration
+options. Always put your local configuration in `config.yml` instead
+of editing `config.defaults.yml`.
## Apache/Passenger
class CollectionReader(object):
def __init__(self, manifest_locator_or_text):
- if re.search(r'^[a-f0-9]{32}\+\d+(\+\S)*$', manifest_locator_or_text):
+ if re.search(r'^[a-f0-9]{32}(\+\d+)?(\+\S+)*$', manifest_locator_or_text):
self._manifest_locator = manifest_locator_or_text
self._manifest_text = None
- else:
+ elif re.search(r'^\S+( [a-f0-9]{32,}(\+\S+)*)*( \d+:\d+:\S+)+\n', manifest_locator_or_text):
self._manifest_text = manifest_locator_or_text
self._manifest_locator = None
+ else:
+ raise errors.ArgumentError(
+ "Argument to CollectionReader must be a manifest or a collection UUID")
self._streams = None
def __enter__(self):
# errors.py - Arvados-specific exceptions.
+class ArgumentError(Exception):
+ pass
class SyntaxError(Exception):
pass
class AssertionError(Exception):
os.environ['KEEP_LOCAL_STORE'] = '/tmp'
LocalCollectionWriterTest().runTest()
def runTest(self):
- cr = arvados.CollectionReader('d6c3b8e571f1b81ebb150a45ed06c884+114')
+ cr = arvados.CollectionReader('d6c3b8e571f1b81ebb150a45ed06c884+114+Xzizzle')
got = []
for s in cr.all_streams():
for f in s.all_files():
/config/api.clinicalfuture.com.*
/config/database.yml
/config/initializers/omniauth.rb
+/config/application.yml
# asset cache
/public/assets/
resource_attrs[:user_id] =
User.where(uuid: resource_attrs.delete(:owner_uuid)).first.andand.id
end
+ resource_attrs[:api_client_id] = Thread.current[:api_client].id
super
end
def update_modified_by_fields
self.created_at ||= Time.now
- self.owner_uuid ||= current_default_owner
+ self.owner_uuid ||= current_default_owner if self.respond_to? :owner_uuid=
self.modified_at = Time.now
self.modified_by_user_uuid = current_user ? current_user.uuid : nil
self.modified_by_client_uuid = current_api_client ? current_api_client.uuid : nil
--- /dev/null
+class Blob
+
+ # In order to get a Blob from Keep, you have to prove either
+ # [a] you have recently written it to Keep yourself, or
+ # [b] apiserver has recently decided that you should be able to read it
+ #
+ # To ensure that the requestor of a blob is authorized to read it,
+ # Keep requires clients to timestamp the blob locator with an expiry
+ # time, and to sign the timestamped locator with their API token.
+ #
+ # A signed blob locator has the form:
+ # locator_hash +A blob_signature @ timestamp
+ # where the timestamp is a Unix time expressed as a hexadecimal value,
+ # and the blob_signature is the signed locator_hash + API token + timestamp.
+ #
+ class InvalidSignatureError < StandardError
+ end
+
+ # Blob.sign_locator: return a signed and timestamped blob locator.
+ #
+ # The 'opts' argument should include:
+ # [required] :key - the Arvados server-side blobstore key
+ # [required] :api_token - user's API token
+ # [optional] :ttl - number of seconds before this request expires
+ #
+ def self.sign_locator blob_locator, opts
+ # We only use the hash portion for signatures.
+ blob_hash = blob_locator.split('+').first
+
+ # Generate an expiry timestamp (seconds since epoch, base 16)
+ timestamp = (Time.now.to_i + (opts[:ttl] || 600)).to_s(16)
+ # => "53163cb4"
+
+ # Generate a signature.
+ signature =
+ generate_signature opts[:key], blob_hash, opts[:api_token], timestamp
+
+ blob_locator + '+A' + signature + '@' + timestamp
+ end
+
+ # Blob.verify_signature
+ # Safely verify the signature on a blob locator.
+ # Return value: true if the locator has a valid signature, false otherwise
+ # Arguments: signed_blob_locator, opts
+ #
+ def self.verify_signature *args
+ begin
+ self.verify_signature! *args
+ true
+ rescue Blob::InvalidSignatureError
+ false
+ end
+ end
+
+ # Blob.verify_signature!
+ # Verify the signature on a blob locator.
+ # Return value: true if the locator has a valid signature
+ # Arguments: signed_blob_locator, opts
+ # Exceptions:
+ # Blob::InvalidSignatureError if the blob locator does not include a
+ # valid signature
+ #
+ def self.verify_signature! signed_blob_locator, opts
+ blob_hash = signed_blob_locator.split('+').first
+ given_signature, timestamp = signed_blob_locator.
+ split('+A').last.
+ split('+').first.
+ split('@')
+
+ if !timestamp
+ raise Blob::InvalidSignatureError.new 'No signature provided.'
+ end
+ if !timestamp.match /^[\da-f]+$/
+ raise Blob::InvalidSignatureError.new 'Timestamp is not a base16 number.'
+ end
+ if timestamp.to_i(16) < Time.now.to_i
+ raise Blob::InvalidSignatureError.new 'Signature expiry time has passed.'
+ end
+
+ my_signature =
+ generate_signature opts[:key], blob_hash, opts[:api_token], timestamp
+
+ if my_signature != given_signature
+ raise Blob::InvalidSignatureError.new 'Signature is invalid.'
+ end
+
+ true
+ end
+
+ def self.generate_signature key, blob_hash, api_token, timestamp
+ OpenSSL::HMAC.hexdigest('sha1', key,
+ [blob_hash,
+ api_token,
+ timestamp].join('@'))
+ end
+end
MAX_SLOTS = 64
- @@confdir = if Rails.configuration.respond_to? :dnsmasq_conf_dir
- Rails.configuration.dnsmasq_conf_dir
- elsif File.exists? '/etc/dnsmasq.d/.'
- '/etc/dnsmasq.d'
- else
- nil
- end
+ @@confdir = Rails.configuration.dnsmasq_conf_dir
@@domain = Rails.configuration.compute_node_domain rescue `hostname --domain`.strip
@@nameservers = Rails.configuration.compute_node_nameservers
def start!(ping_url_method)
ensure_permission_to_update
ping_url = ping_url_method.call({ uuid: self.uuid, ping_secret: self.info[:ping_secret] })
- if (Rails.configuration.compute_node_ec2run_args rescue false) and
- (Rails.configuration.compute_node_ami rescue false)
+ if (Rails.configuration.compute_node_ec2run_args and
+ Rails.configuration.compute_node_ami)
ec2_args = ["--user-data '#{ping_url}'",
"-t c1.xlarge -n 1",
Rails.configuration.compute_node_ec2run_args,
--- /dev/null
+# Do not use this file for site configuration. Create application.yml
+# instead (see application.yml.example).
+
+development:
+ force_ssl: false
+ cache_classes: false
+ whiny_nils: true
+ consider_all_requests_local: true
+ action_controller.perform_caching: false
+ action_mailer.raise_delivery_errors: false
+ action_mailer.perform_deliveries: false
+ active_support.deprecation: :log
+ action_dispatch.best_standards_support: :builtin
+ active_record.mass_assignment_sanitizer: :strict
+ active_record.auto_explain_threshold_in_seconds: 0.5
+ assets.compress: false
+ assets.debug: true
+
+production:
+ force_ssl: true
+ cache_classes: true
+ consider_all_requests_local: false
+ action_controller.perform_caching: true
+ serve_static_assets: false
+ assets.compress: true
+ assets.compile: false
+ assets.digest: true
+
+test:
+ force_ssl: false
+ cache_classes: true
+ serve_static_assets: true
+ static_cache_control: public, max-age=3600
+ whiny_nils: true
+ consider_all_requests_local: true
+ action_controller.perform_caching: false
+ action_dispatch.show_exceptions: false
+ action_controller.allow_forgery_protection: false
+ action_mailer.delivery_method: :test
+ active_support.deprecation: :stderr
+ active_record.mass_assignment_sanitizer: :strict
+
+common:
+ secret_token: ~
+ uuid_prefix: <%= Digest::MD5.hexdigest(`hostname`).to_i(16).to_s(36)[0..4] %>
+
+ git_repositories_dir: /var/cache/git
+
+ # :none or :slurm_immediate
+ crunch_job_wrapper: :none
+
+ # username, or false = do not set uid when running jobs.
+ crunch_job_user: crunch
+
+ # The web service must be able to create/write this file, and
+ # crunch-job must be able to stat() it.
+ crunch_refresh_trigger: /tmp/crunch_refresh_trigger
+
+ # Path to /etc/dnsmasq.d, or false = do not update dnsmasq data.
+ dnsmasq_conf_dir: false
+
+ # Set to AMI id (ami-123456) to auto-start nodes. See app/models/node.rb
+ compute_node_ami: false
+ compute_node_ec2run_args: -g arvados-compute
+ compute_node_spot_bid: 0.11
+
+ compute_node_domain: <%= `hostname`.split('.')[1..-1].join('.').strip %>
+ compute_node_nameservers:
+ - 192.168.1.1
+ compute_node_ec2_tag_enable: false
+
+ accept_api_token: {}
+
+ new_users_are_active: false
+ admin_notifier_email_from: arvados@example.com
+ email_subject_prefix: "[ARVADOS] "
+
+ # Visitors to the API server will be redirected to the workbench
+ workbench_address: https://workbench.local:3001/
+
+ # The e-mail address of the user you would like to become marked as an admin
+ # user on their first login.
+ # In the default configuration, authentication happens through the Arvados SSO
+ # server, which uses openid against Google's servers, so in that case this
+ # should be an address associated with a Google account.
+ auto_admin_user: ~
--- /dev/null
+# Copy this file to application.yml and edit to suit.
+#
+# Consult application.default.yml for the full list of configuration
+# settings.
+#
+# The order of precedence is:
+# 1. config/environments/{RAILS_ENV}.rb (deprecated)
+# 2. Section in application.yml corresponding to RAILS_ENV (e.g., development)
+# 3. Section in application.yml called "common"
+# 4. Section in application.default.yml corresponding to RAILS_ENV
+# 5. Section in application.default.yml called "common"
+
+development:
+
+production:
+ # At minimum, you need a nice long randomly generated secret_token here.
+ secret_token: ~
+
+ uuid_prefix: bogus
+
+ # This is suitable for AWS; see common section below for a static example.
+ compute_node_nameservers: <%=
+ require 'net/http'
+ ['local', 'public'].collect do |iface|
+ Net::HTTP.get(URI("http://169.254.169.254/latest/meta-data/#{iface}-ipv4")).match(/^[\d\.]+$/)[0]
+ end << '172.16.0.23'
+ %>
+ # You must customize these. See config.defaults.yml for information.
+ compute_node_ami: ~
+ compute_node_ec2_tag_enable: ~
+ compute_node_domain: ~
+ compute_node_spot_bid: ~
+
+test:
+ uuid_prefix: zzzzz
+
+common:
+ secret_token: ~
+ compute_node_nameservers:
+ - 192.168.0.1
+ - 172.16.0.1
development:
- adapter: mysql
+ adapter: postgresql
encoding: utf8
database: arvados_development
username: arvados
host: localhost
test:
- adapter: mysql
+ adapter: postgresql
encoding: utf8
database: arvados_test
username: arvados
host: localhost
production:
- adapter: mysql
+ adapter: postgresql
encoding: utf8
database: arvados_production
username: arvados
# Visitors to the API server will be redirected to the workbench
config.workbench_address = "http://localhost:3000/"
+
+ # The e-mail address of the user you would like to become marked as an admin
+ # user on their first login.
+ # In the default configuration, authentication happens through the Arvados SSO
+ # server, which uses openid against Google's servers, so in that case this
+ # should be an address associated with a Google account.
+ config.auto_admin_user = ''
end
--- /dev/null
+$application_config = {}
+
+%w(application.default application).each do |cfgfile|
+ path = "#{::Rails.root.to_s}/config/#{cfgfile}.yml"
+ if File.exists? path
+ yaml = ERB.new(IO.read path).result(binding)
+ confs = YAML.load(yaml)
+ $application_config.merge!(confs['common'] || {})
+ $application_config.merge!(confs[::Rails.env.to_s] || {})
+ end
+end
+
+Server::Application.configure do
+ nils = []
+ $application_config.each do |k, v|
+ # "foo.bar: baz" --> { config.foo.bar = baz }
+ cfg = config
+ ks = k.split '.'
+ k = ks.pop
+ ks.each do |kk|
+ cfg = cfg.send(kk)
+ end
+ if cfg.respond_to?(k.to_sym) and !cfg.send(k).nil?
+ # Config must have been set already in environments/*.rb.
+ #
+ # After config files have been migrated, this mechanism should
+ # be deprecated, then removed.
+ elsif v.nil?
+ # Config variables are not allowed to be nil. Make a "naughty"
+ # list, and present it below.
+ nils << k
+ else
+ cfg.send "#{k}=", v
+ end
+ end
+ if !nils.empty?
+ raise <<EOS
+Refusing to start in #{::Rails.env.to_s} mode with missing configuration.
+
+The following configuration settings must be specified in
+config/application.yml:
+* #{nils.join "\n* "}
+
+EOS
+ end
+end
--- /dev/null
+namespace :config do
+ desc 'Ensure site configuration has all required settings'
+ task check: :environment do
+ $application_config.sort.each do |k, v|
+ $stderr.puts "%-32s %s" % [k, eval("Rails.configuration.#{k}")]
+ end
+ end
+end
assert_response :success
end
+ test "create token for different user" do
+ post "/arvados/v1/api_client_authorizations", {
+ :format => :json,
+ :api_client_authorization => {
+ :owner_uuid => users(:spectator).uuid
+ }
+ }, {'HTTP_AUTHORIZATION' => "OAuth2 #{api_client_authorizations(:admin_trustedclient).api_token}"}
+ assert_response :success
+
+ get "/arvados/v1/users/current", {
+ :format => :json
+ }, {'HTTP_AUTHORIZATION' => "OAuth2 #{jresponse['api_token']}"}
+ @jresponse = nil
+ assert_equal users(:spectator).uuid, jresponse['uuid']
+ end
+
+ test "refuse to create token for different user if not trusted client" do
+ post "/arvados/v1/api_client_authorizations", {
+ :format => :json,
+ :api_client_authorization => {
+ :owner_uuid => users(:spectator).uuid
+ }
+ }, {'HTTP_AUTHORIZATION' => "OAuth2 #{api_client_authorizations(:admin).api_token}"}
+ assert_response 403
+ end
+
+ test "refuse to create token for different user if not admin" do
+ post "/arvados/v1/api_client_authorizations", {
+ :format => :json,
+ :api_client_authorization => {
+ :owner_uuid => users(:spectator).uuid
+ }
+ }, {'HTTP_AUTHORIZATION' => "OAuth2 #{api_client_authorizations(:active_trustedclient).api_token}"}
+ assert_response 403
+ end
+
end
--- /dev/null
+require 'test_helper'
+
+class BlobTest < ActiveSupport::TestCase
+ @@api_token = rand(2**512).to_s(36)[0..49]
+ @@key = rand(2**2048).to_s(36)
+ @@blob_data = 'foo'
+ @@blob_locator = Digest::MD5.hexdigest(@@blob_data) +
+ '+' + @@blob_data.size.to_s
+
+ test 'correct' do
+ signed = Blob.sign_locator @@blob_locator, api_token: @@api_token, key: @@key
+ assert_equal true, Blob.verify_signature!(signed, api_token: @@api_token, key: @@key)
+ end
+
+ test 'expired' do
+ signed = Blob.sign_locator @@blob_locator, api_token: @@api_token, key: @@key, ttl: -1
+ assert_raise Blob::InvalidSignatureError do
+ Blob.verify_signature!(signed, api_token: @@api_token, key: @@key)
+ end
+ end
+
+ test 'expired, but no raise' do
+ signed = Blob.sign_locator @@blob_locator, api_token: @@api_token, key: @@key, ttl: -1
+ assert_equal false, Blob.verify_signature(signed,
+ api_token: @@api_token,
+ key: @@key)
+ end
+
+ test 'bogus, wrong block hash' do
+ signed = Blob.sign_locator @@blob_locator, api_token: @@api_token, key: @@key
+ assert_raise Blob::InvalidSignatureError do
+ Blob.verify_signature!(signed.sub('acbd','abcd'), api_token: @@api_token, key: @@key)
+ end
+ end
+
+ test 'bogus, expired' do
+ signed = 'acbd18db4cc2f85cedef654fccc4a4d8+3+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@531641bf'
+ assert_raises Blob::InvalidSignatureError do
+ Blob.verify_signature!(signed, api_token: @@api_token, key: @@key)
+ end
+ end
+
+ test 'bogus, wrong key' do
+ signed = Blob.sign_locator(@@blob_locator,
+ api_token: @@api_token,
+ key: (@@key+'x'))
+ assert_raise Blob::InvalidSignatureError do
+ Blob.verify_signature!(signed, api_token: @@api_token, key: @@key)
+ end
+ end
+
+ test 'bogus, wrong api token' do
+ signed = Blob.sign_locator(@@blob_locator,
+ api_token: @@api_token.reverse,
+ key: @@key)
+ assert_raise Blob::InvalidSignatureError do
+ Blob.verify_signature!(signed, api_token: @@api_token, key: @@key)
+ end
+ end
+
+ test 'bogus, signature format 1' do
+ signed = 'acbd18db4cc2f85cedef654fccc4a4d8+3+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@'
+ assert_raise Blob::InvalidSignatureError do
+ Blob.verify_signature!(signed, api_token: @@api_token, key: @@key)
+ end
+ end
+
+ test 'bogus, signature format 2' do
+ signed = 'acbd18db4cc2f85cedef654fccc4a4d8+3+A@531641bf'
+ assert_raise Blob::InvalidSignatureError do
+ Blob.verify_signature!(signed, api_token: @@api_token, key: @@key)
+ end
+ end
+
+ test 'bogus, signature format 3' do
+ signed = 'acbd18db4cc2f85cedef654fccc4a4d8+3+Axyzzy@531641bf'
+ assert_raise Blob::InvalidSignatureError do
+ Blob.verify_signature!(signed, api_token: @@api_token, key: @@key)
+ end
+ end
+
+ test 'bogus, timestamp format' do
+ signed = 'acbd18db4cc2f85cedef654fccc4a4d8+3+Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@xyzzy'
+ assert_raise Blob::InvalidSignatureError do
+ Blob.verify_signature!(signed, api_token: @@api_token, key: @@key)
+ end
+ end
+
+ test 'no signature at all' do
+ assert_raise Blob::InvalidSignatureError do
+ Blob.verify_signature!(@@blob_locator, api_token: @@api_token, key: @@key)
+ end
+ end
+end