├── .deepsource.toml
├── .dockerignore
├── .env.example
├── .gitignore
├── .rspec
├── .rubocop.yml
├── .ruby-version
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── README.md
├── Rakefile
├── VERSION
├── api_blueprint
├── bin
│ └── dredd_server.sh
├── group.apib
├── hooks
│ └── dredd_hooks.rb
├── user.apib
└── vpns.apib
├── app
├── assets
│ ├── config
│ │ └── manifest.js
│ ├── images
│ │ ├── .keep
│ │ ├── app_store_en_badge.png
│ │ ├── apple-touch-icon-114x114-precomposed.png
│ │ ├── apple-touch-icon-114x114.png
│ │ ├── apple-touch-icon-120x120-precomposed.png
│ │ ├── apple-touch-icon-120x120.png
│ │ ├── apple-touch-icon-144x144-precomposed.png
│ │ ├── apple-touch-icon-144x144.png
│ │ ├── apple-touch-icon-152x152-precomposed.png
│ │ ├── apple-touch-icon-152x152.png
│ │ ├── apple-touch-icon-180x180-precomposed.png
│ │ ├── apple-touch-icon-180x180.png
│ │ ├── apple-touch-icon-57x57-precomposed.png
│ │ ├── apple-touch-icon-57x57.png
│ │ ├── apple-touch-icon-72x72-precomposed.png
│ │ ├── apple-touch-icon-72x72.png
│ │ ├── apple-touch-icon-76x76-precomposed.png
│ │ ├── apple-touch-icon-76x76.png
│ │ ├── apple-touch-icon-precomposed.png
│ │ ├── apple-touch-icon.png
│ │ ├── bg.jpg
│ │ ├── favicon.ico
│ │ ├── google_play_en_badge.png
│ │ ├── logo.png
│ │ ├── saml_configure_datadog_01.png
│ │ ├── saml_configure_datadog_02.png
│ │ ├── saml_configure_datadog_03.png
│ │ ├── saml_configure_datadog_04.png
│ │ ├── saml_configure_datadog_05.png
│ │ ├── saml_configure_datadog_06.png
│ │ ├── saml_configure_datadog_07.png
│ │ ├── saml_configure_datadog_08.png
│ │ └── saml_configure_datadog_09.png
│ ├── javascripts
│ │ ├── admin.coffee
│ │ ├── api_resources.coffee
│ │ ├── application.js
│ │ ├── bootstrap.js.coffee
│ │ ├── group.coffee
│ │ ├── groups.coffee
│ │ ├── home.coffee
│ │ ├── host_access_groups.coffee
│ │ ├── host_machine_groups.coffee
│ │ ├── host_machines.coffee
│ │ ├── nss.coffee
│ │ ├── omniauth_callbacks.coffee
│ │ ├── profile.coffee
│ │ ├── users.coffee
│ │ ├── utilities.coffee
│ │ └── viewport.js
│ └── stylesheets
│ │ ├── application.scss
│ │ ├── bootstrap-social.scss
│ │ ├── general.css
│ │ ├── home.scss.erb
│ │ ├── profile.css
│ │ └── scaffolds.scss
├── clients
│ └── data_dog_client.rb
├── controllers
│ ├── admin_controller.rb
│ ├── api
│ │ └── v1
│ │ │ ├── base_controller.rb
│ │ │ ├── endpoints_controller.rb
│ │ │ ├── groups_controller.rb
│ │ │ ├── users_controller.rb
│ │ │ └── vpns_controller.rb
│ ├── api_resources_controller.rb
│ ├── application_controller.rb
│ ├── concerns
│ │ └── .keep
│ ├── groups_controller.rb
│ ├── home_controller.rb
│ ├── host_controller.rb
│ ├── host_machine_groups_controller.rb
│ ├── host_machines_controller.rb
│ ├── nss_controller.rb
│ ├── organisations_controller.rb
│ ├── pings_controller.rb
│ ├── profile_controller.rb
│ ├── saml_idp_controller.rb
│ ├── users
│ │ ├── auth_controller.rb
│ │ └── omniauth_callbacks_controller.rb
│ ├── users_controller.rb
│ ├── vpn_domain_name_servers_controller.rb
│ └── vpns_controller.rb
├── helpers
│ ├── admin_helper.rb
│ ├── api_resources_helper.rb
│ ├── application_helper.rb
│ ├── group_helper.rb
│ ├── groups_helper.rb
│ ├── home_helper.rb
│ ├── host_access_groups_helper.rb
│ ├── host_machine_groups_helper.rb
│ ├── host_machines_helper.rb
│ ├── nss_helper.rb
│ ├── omniauth_callbacks_helper.rb
│ ├── profile_helper.rb
│ └── users_helper.rb
├── lib
│ ├── datadog.rb
│ └── saml_app.rb
├── mailers
│ └── .keep
├── models
│ ├── .keep
│ ├── access_token.rb
│ ├── api_resource.rb
│ ├── application_record.rb
│ ├── concerns
│ │ ├── .keep
│ │ └── ms_chap_auth.rb
│ ├── endpoint.rb
│ ├── group.rb
│ ├── group_admin.rb
│ ├── group_association.rb
│ ├── group_endpoint.rb
│ ├── host.rb
│ ├── host_access_group.rb
│ ├── host_machine.rb
│ ├── ip_address.rb
│ ├── organisation.rb
│ ├── saml_app_config.rb
│ ├── user.rb
│ ├── vpn.rb
│ ├── vpn_domain_name_server.rb
│ ├── vpn_group_association.rb
│ ├── vpn_group_user_association.rb
│ ├── vpn_search_domain.rb
│ └── vpn_supplemental_match_domain.rb
├── validators
│ └── email_validator.rb
└── views
│ ├── admin
│ └── index.html.slim
│ ├── api
│ └── v1
│ │ └── users
│ │ └── show.json.jbuilder
│ ├── api_resources
│ ├── _api_resource.json.jbuilder
│ ├── _form.html.slim
│ ├── edit.html.slim
│ ├── index.html.slim
│ ├── index.json.jbuilder
│ ├── new.html.slim
│ ├── show.html.slim
│ └── show.json.jbuilder
│ ├── application
│ ├── _admin.html.slim
│ ├── _groups_header.html.slim
│ └── _host_header.html.slim
│ ├── common
│ └── errors.json.jbuilder
│ ├── groups
│ ├── _form.html.slim
│ ├── index.html.slim
│ ├── new.html.slim
│ └── show.html.slim
│ ├── home
│ └── index.html.slim
│ ├── host_machines
│ ├── index.html.slim
│ ├── new.html.slim
│ └── show.html.slim
│ ├── layouts
│ ├── application.html.slim
│ ├── home.html.slim
│ └── profile.html.slim.disabled
│ ├── nss
│ └── add_host.json.jbuilder
│ ├── organisations
│ ├── _form.html.slim
│ ├── config_saml_app.html.slim
│ ├── index.html.slim
│ ├── new.html.slim
│ ├── saml_apps
│ │ └── _datadog.html.erb
│ └── show.html.slim
│ ├── profile
│ ├── _group_search.html.slim
│ ├── _user_search.html.slim
│ ├── group_admin.html.slim
│ ├── list.html.slim
│ ├── public_key.html.slim
│ ├── show.html.slim
│ ├── user.html.slim
│ └── user_admin.html.slim
│ ├── saml_idp
│ └── idp
│ │ └── new.html.erb
│ ├── users
│ ├── _search.html.slim
│ ├── index.html.slim
│ ├── new.html.erb
│ └── show.html.slim
│ └── vpns
│ ├── _form.html.slim
│ ├── edit.html.slim
│ ├── index.html.slim
│ ├── new.html.slim
│ └── show.html.slim
├── bin
├── bundle
├── rails
├── rake
├── setup
└── update
├── config.ru
├── config
├── application.rb
├── boot.rb
├── cable.yml
├── database.yml
├── environment.rb
├── environments
│ ├── development.rb
│ ├── integration.rb
│ ├── production.rb
│ └── test.rb
├── initializers
│ ├── application_controller_renderer.rb
│ ├── assets.rb
│ ├── backtrace_silencers.rb
│ ├── content_security_policy.rb
│ ├── cookies_serializer.rb
│ ├── devise.rb
│ ├── dotenv.rb
│ ├── filter_parameter_logging.rb
│ ├── inflections.rb
│ ├── mime_types.rb
│ ├── new_framework_defaults.rb
│ ├── new_framework_defaults_7_0.rb
│ ├── permissions_policy.rb
│ ├── session_store.rb
│ └── wrap_parameters.rb
├── locales
│ ├── devise.en.yml
│ ├── en.bootstrap.yml
│ └── en.yml
├── newrelic.yml
├── puma.rb
├── redis.yml
├── routes.rb
├── schedule.rb
├── secrets.yml
├── spring.rb
└── storage.yml
├── db
├── migrate
│ ├── 20160419122430_devise_create_users.rb
│ ├── 20160419132647_add_provider_to_users.rb
│ ├── 20160419144739_add_name_to_users.rb
│ ├── 20160427123146_add_auth_key_to_user.rb
│ ├── 20160427123233_add_provisioning_uri_to_user.rb
│ ├── 20160519042340_add_active_to_users.rb
│ ├── 20160519064340_add_default_value_to_users.rb
│ ├── 20160615044834_create_hosts.rb
│ ├── 20160615045052_add_admin_to_user.rb
│ ├── 20160615112805_add_user_to_host.rb
│ ├── 20160628140022_add_deleted_at_to_host.rb
│ ├── 20160628140440_add_deleted_by_to_host.rb
│ ├── 20160629043358_add_homedir_to_user.rb
│ ├── 20160629043415_add_shell_to_user.rb
│ ├── 20160629075435_create_groups.rb
│ ├── 20160701090045_create_group_associations.rb
│ ├── 20160701112600_add_deleted_properties_to_group.rb
│ ├── 20160707115313_create_access_tokens.rb
│ ├── 20160714115228_add_public_key_to_user.rb
│ ├── 20160908081651_create_host_machines.rb
│ ├── 20161003145832_create_host_access_groups.rb
│ ├── 20170803140620_add_user_login_id_to_user.rb
│ ├── 20171013115441_create_versions.rb
│ ├── 20171016064705_remove_index_group_name.rb
│ ├── 20171016071526_add_unique_index_on_groups_name.rb
│ ├── 20171031060034_create_group_admin.rb
│ ├── 20171031060217_add_foreign_key_ref_on_group_admin.rb
│ ├── 20171031100758_create_vpns.rb
│ ├── 20171031101026_create_vpn_group_association.rb
│ ├── 20171031103518_add_foreign_key_ref_on_vpn_group_association.rb
│ ├── 20171031113123_create_vpn_group_user_association.rb
│ ├── 20171031121702_add_foreign_key_ref_on_vpn_group_user_association.rb
│ ├── 20171102071909_add_ip_address_to_vpns.rb
│ ├── 20171107114249_remove_url_from_vpns.rb
│ ├── 20171108130234_add_user_id_to_access_token.rb
│ ├── 20171108130353_add_foreign_key_ref_on_access_tokens.rb
│ ├── 20171124090240_add_uuid_to_vpns.rb
│ ├── 20171124114427_create_vpn_domain_name_servers.rb
│ ├── 20171124114830_create_vpn_search_domains.rb
│ ├── 20171124115925_create_vpn_supplemental_match_domains.rb
│ ├── 20180104081814_add_product_name_to_users.rb
│ ├── 20180202102206_create_saml_service_providers.rb
│ ├── 20180214050204_add_api_key_to_host_machines.rb
│ ├── 20180214052451_create_ip_addresses.rb
│ ├── 20180214052644_add_host_machine_to_ip_address.rb
│ ├── 20180219150818_add_description_to_group.rb
│ ├── 20180222135930_add_access_key_to_host_machine.rb
│ ├── 20180222140000_add_access_key_to_user.rb
│ ├── 20180227051732_create_api_resources.rb
│ ├── 20180301010021_add_user_to_api_resources.rb
│ ├── 20180301010035_add_group_to_api_resources.rb
│ ├── 20180306231200_add_deactivated_at_to_users.rb
│ ├── 20180311082600_rename_access_key_in_api_resources.rb
│ ├── 20180311161200_rename_token_in_access_tokens.rb
│ ├── 20180318083000_create_indexes_to_speedup_nss_controller.rb
│ ├── 20180613074108_create_organisations.rb
│ ├── 20180613165050_drop_saml_service_providers.rb
│ ├── 20180723175600_update_organisations_for_saml.rb
│ ├── 20181002023107_add_default_admins_to_host_machines.rb
│ ├── 20181016093315_create_saml_app_configs.rb
│ ├── 20181208184236_add_fields_to_user.rb
│ ├── 20190624024930_add_expiration_date_to_group_associations.rb
│ ├── 20190820070910_create_endpoints.rb
│ ├── 20190820075040_create_group_endpoints.rb
│ ├── 20190820080624_add_foreign_key_ref_on_group_endpoints.rb
│ ├── 20200113065717_add_sessions_table.rb
│ ├── 20220926001848_add_service_name_to_active_storage_blobs.active_storage.rb
│ ├── 20220926001849_create_active_storage_variant_records.active_storage.rb
│ └── 20220926001850_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb
├── schema.rb
├── seeds.rb
└── seeds
│ ├── development.rb
│ ├── production.rb
│ └── test.rb
├── docker-compose.yaml
├── docs
├── additional_setup.md
├── administration.md
├── dredd_setup.md
├── newrelic.md
└── oauth_setup.md
├── dredd.yml
├── lib
├── assets
│ └── .keep
├── tasks
│ ├── .keep
│ ├── app.rake
│ ├── setup.rake
│ ├── users.rake
│ └── vpn.rake
└── vpn
│ ├── mobileconfig.erb
│ ├── mobileconfig.rb
│ └── namespace.rb
├── node_modules
└── .yarn-integrity
├── public
├── 404.html
├── 422.html
├── 500.html
├── favicon.ico
└── robots.txt
├── scripts
├── gen-client-conf
└── gen-client-keys
├── setup.sh
├── spec
├── clients
│ └── data_dog_client_spec.rb
├── controllers
│ ├── admin_controller_spec.rb
│ ├── api
│ │ └── v1
│ │ │ ├── api_controller_spec.rb
│ │ │ ├── endpoints_controller_spec.rb
│ │ │ ├── groups_controller_spec.rb
│ │ │ ├── users_controller_spec.rb
│ │ │ └── vpns_controller_spec.rb
│ ├── api_resources_controller_spec.rb
│ ├── groups_controller_spec.rb
│ ├── home_controller_spec.rb
│ ├── host_machine_groups_controller_spec.rb
│ ├── host_machines_controller_spec.rb
│ ├── nss_controller_spec.rb
│ ├── omniauth_callbacks_controller_spec.rb
│ ├── organisations_controller_spec.rb
│ ├── profile_controller_spec.rb
│ ├── users
│ │ └── auth_controller_spec.rb
│ ├── users_controller_spec.rb
│ └── vpns_controller_spec.rb
├── factories
│ ├── access_tokens.rb
│ ├── api_resources.rb
│ ├── endpoints.rb
│ ├── group_associations.rb
│ ├── groups.rb
│ ├── host_access_groups.rb
│ ├── host_machine_groups.rb
│ ├── host_machines.rb
│ ├── ip_addresses.rb
│ ├── organisations.rb
│ ├── saml_app_configs.rb
│ ├── user_host_access_groups.rb
│ ├── users.rb
│ └── vpns.rb
├── features
│ ├── layout_spec.rb
│ ├── organisations
│ │ ├── add_user_saml_app_spec.rb
│ │ ├── config_saml_app_spec.rb
│ │ ├── create_spec.rb
│ │ ├── list_spec.rb
│ │ ├── list_user_saml_app_spec.rb
│ │ ├── remove_user_saml_app_spec.rb
│ │ ├── save_config_saml_app_spec.rb
│ │ ├── setup_saml_spec.rb
│ │ └── update_spec.rb
│ ├── saml
│ │ └── show_spec.rb
│ └── users
│ │ ├── create_user_spec.rb
│ │ └── regenerate_auth_spec.rb
├── helpers
│ └── application_helper_spec.rb
├── lib
│ ├── datadog_spec.rb
│ ├── saml_app_spec.rb
│ └── tasks
│ │ └── users_rake_spec.rb
├── models
│ ├── access_token_spec.rb
│ ├── api_resource_spec.rb
│ ├── endpoint_spec.rb
│ ├── group_association_spec.rb
│ ├── group_endpoint_spec.rb
│ ├── group_spec.rb
│ ├── host_machine_spec.rb
│ ├── host_spec.rb
│ ├── ip_address_spec.rb
│ ├── organisation_spec.rb
│ ├── user_spec.rb
│ └── vpn_spec.rb
├── rails_helper.rb
├── routing
│ └── api_resources_routing_spec.rb
├── spec_helper.rb
├── support
│ └── helpers
│ │ └── x509_certificate_helper.rb
└── views
│ ├── api_resources
│ ├── edit.html.slim_spec.rb
│ ├── index.html.slim_spec.rb
│ ├── new.html.slim_spec.rb
│ └── show.html.slim_spec.rb
│ ├── groups
│ └── show.html.slim_spec.rb
│ └── layouts
│ └── home.html.slim_spec.rb
├── vendor
└── assets
│ ├── javascripts
│ └── .keep
│ └── stylesheets
│ └── .keep
└── yarn.lock
/.deepsource.toml:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | [[analyzers]]
4 | name = "ruby"
5 | enabled = true
6 |
7 | [[analyzers]]
8 | name = "javascript"
9 | enabled = true
10 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | /log/*
2 | !/log/.keep
3 | /tmp
4 | .idea
5 | .env
6 | *.swp
7 | config/application.yml
8 | dump.rdb
9 | coverage
10 | .git
11 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | GATE_SERVER_URL=http://localhost:3000
2 | SIGN_IN_TYPE=
3 | GATE_OAUTH_CLIENT_ID=totally_secret_client_id
4 | GATE_OAUTH_CLIENT_SECRET=totally_secret
5 | GATE_HOSTED_DOMAIN=gate.domain
6 | GATE_HOSTED_DOMAINS=test1.com,test2.com
7 | GATE_DB_HOST=localhost
8 | GATE_DB_PORT=3306
9 | GATE_DB_NAME=
10 | GATE_DB_USER=gate
11 | GATE_DB_PASSWORD=gate
12 | CACHE_HOST=localhost
13 | CACHE_PORT=6379
14 | SECRET_KEY_BASE=
15 | SECRET_API_KEY=
16 | GATE_CONFIG_SECRET=
17 | USER_ROLES=employee,consultant
18 | UID_BUFFER=5000
19 | DEFAULT_HOST_PATTERN=s*
20 | PRODUCT_LIST=pr1,pr2
21 | SAML_APPS=datadog
22 | GATE_ORGANIZATION_NAME=
23 | GATE_ORGANIZATION_STATIC=
24 | GATE_VPN_SSL_CERT=
25 | GATE_VPN_SSL_XSIGNED=
26 | GATE_VPN_SSL_PVTKEY=
27 | NEWRELIC_AGENT_ENABLED=false
28 | NEWRELIC_LICENSE_KEY=
29 | NEWRELIC_APP_NAME=Gate
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile '~/.gitignore_global'
6 |
7 | # Ignore bundler config.
8 | /.bundle
9 | .local
10 | vendor/*
11 |
12 | # Ignore the default SQLite database.
13 | /db/*.sqlite3
14 | /db/*.sqlite3-journal
15 |
16 | # Ignore all logfiles and tempfiles.
17 | /log/*
18 | !/log/.keep
19 | /tmp
20 | .idea
21 | .env
22 | .ruby-gemset
23 | *.swp
24 | config/application.yml
25 | public/assets/*
26 | dump.rdb
27 | coverage
28 | data/
29 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --format documentation
3 | --require spec_helper
4 |
--------------------------------------------------------------------------------
/.ruby-version:
--------------------------------------------------------------------------------
1 | ruby-3.1.2
2 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | ## Releasing Gate
4 |
5 | > Gate uses semantic versioning, check [this page](https://semver.org/) for more details on how to bump the version number.
6 |
7 | Steps on releasing Gate.
8 |
9 | 1. Bump version on [VERSION](VERSION) file.
10 | 2. Add appropriate changelogs on [CHANGELOG.md](CHANGELOG.md) file. Please follow existing format.
11 | 3. Tag the commit by the new version number and push it, travis will automatically build and release Gate.
12 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ruby:2.4
2 |
3 | RUN apt-get update
4 | RUN curl -sL https://deb.nodesource.com/setup_10.x | bash
5 | RUN apt-get update -qq && apt-get install -y build-essential nodejs git
6 |
7 | RUN mkdir /app
8 | WORKDIR /app
9 |
10 | COPY Gemfile /app
11 | COPY Gemfile.lock /app
12 |
13 | RUN gem install bundler -v '>= 2.0'
14 | RUN bundle install --without development
15 | COPY . /app
16 |
17 | CMD [ "bundle", "exec", "rails", "s" ]
18 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'rails', '7.1.3.2'
4 |
5 | gem 'activerecord-session_store'
6 | gem 'ansi'
7 | gem 'bootstrap'
8 | gem 'countries', require: 'countries/global'
9 | gem 'devise'
10 | gem 'dotenv-rails'
11 | gem 'font-awesome-rails'
12 | gem 'httparty'
13 | gem 'jbuilder'
14 | gem 'mysql2'
15 | gem 'omniauth'
16 | gem 'omniauth-google-oauth2'
17 | gem 'paranoia'
18 | gem 'puma'
19 | gem 'redis'
20 | gem 'rotp'
21 | gem 'rqrcode'
22 |
23 | gem 'sassc-rails'
24 |
25 |
26 | #Disabling SAML Feature during upgrade
27 | # #TODO ENable this feature later
28 | #gem 'ruby-saml', '1.8.0'
29 | #gem 'saml_idp', git: 'https://github.com/gate-sso/saml_idp'
30 | gem 'sdoc', group: :doc
31 | # #TODO ENable this feature later
32 |
33 | gem 'slim-rails'
34 | gem 'turbolinks'
35 | gem 'uglifier'
36 | gem 'whenever', require: false
37 |
38 | group :development, :test do
39 | gem 'capybara'
40 | gem 'coveralls'
41 | gem 'database_cleaner'
42 | gem 'dredd_hooks'
43 | gem 'factory_bot_rails'
44 | gem 'faker'
45 | gem 'mock_redis'
46 | gem 'pry'
47 | gem 'rails-controller-testing'
48 | gem 'rspec-rails'
49 | gem 'rubocop'
50 | gem 'rubocop-faker'
51 | gem 'rubocop-performance'
52 | gem 'rubocop-rails'
53 | gem 'rubocop-rspec'
54 | gem 'shoulda-matchers'
55 | gem 'simplecov'
56 | gem 'simplecov-console'
57 | gem 'timecop'
58 | gem 'webmock'
59 | end
60 |
61 | group :development do
62 | gem 'web-console', platform: :ruby
63 | end
64 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 gate-sso
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require File.expand_path('../config/application', __FILE__)
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 1.1.8
2 |
--------------------------------------------------------------------------------
/api_blueprint/bin/dredd_server.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # dredd_server.sh
3 | kill -9 $(lsof -i tcp:9865 -t)
4 | export RAILS_ENV=test
5 | export LOG_LEVEL=info
6 | rake db:drop
7 | rake db:setup
8 | bundle exec rails server --port=9865
9 |
10 |
--------------------------------------------------------------------------------
/api_blueprint/hooks/dredd_hooks.rb:
--------------------------------------------------------------------------------
1 | ENV['RAILS_ENV'] ||= 'test'
2 |
3 | require File.expand_path('../../config/environment', __dir__)
4 | require 'dredd_hooks/methods'
5 |
6 | include DreddHooks::Methods
7 |
8 | before_all do |_|
9 | user = User.create(name: 'foo', email: 'bar@test.com', admin: 1)
10 | access_token = AccessToken.new
11 | access_token.token = 'token'
12 | access_token.user = user
13 | user.access_token = access_token
14 | access_token.save!
15 | user.save!
16 | inactive_user = User.create(name: 'foo', email: 'foo@test2.com', active: 0, user_login_id: 'foo')
17 | inactive_user.save!
18 | active_user = User.create(name: 'foo', email: 'foo@test.com', active: 1, user_login_id: 'foo')
19 | active_user.save!
20 | end
21 |
--------------------------------------------------------------------------------
/api_blueprint/vpns.apib:
--------------------------------------------------------------------------------
1 | FORMAT: 1A
2 |
3 | # API VPNS
4 |
5 | # VPNS [/api/v1/vpns]
6 |
7 | ## Create VPNS [POST]
8 | Create new vpns
9 |
10 | + Request(application/json)
11 |
12 | + Headers
13 |
14 | Authorization: token
15 |
16 | + Body
17 |
18 | {
19 | "id": 1,
20 | "name": "test-vpn",
21 | "host_name": "test-vpn.example.com",
22 | "ip_address" : "10.10.10.10"
23 | }
24 |
25 | + Schema
26 |
27 | {
28 | "type": "object",
29 | "properties" : {
30 | "id" : {
31 | "type" : int
32 | },
33 | "name" : {
34 | "type" : "string"
35 | },
36 | "host_name" : {
37 | "type" : "string"
38 | },
39 | "ip_address" : {
40 | "type" : "string"
41 | }
42 | }
43 | }
44 |
45 | + Response 200
46 |
47 | + Body
48 |
49 | {
50 | "id": 1,
51 | "name": "test-vpn",
52 | "host_name": "test-vpn.example.com",
53 | "ip_address": "10.10.10.10"
54 | }
55 |
56 | + Request(application/json)
57 |
58 | + Headers
59 |
60 | Authorization: wrong-token
61 |
62 | + Body
63 |
64 | + Response 401
65 |
66 | + Headers
67 |
68 | x-frame-options: SAMEORIGIN
69 | x-xss-protection: 1; mode=block
70 | x-content-type-options: nosniff
71 | content-type: text/html
72 | cache-control: no-cache
73 | x-request-id: 73b10aa8-6f68-400b-b723-2e992ac4d000
74 | x-runtime: 0.002242
75 | connection: close
76 | transfer-encoding: chunked
77 |
--------------------------------------------------------------------------------
/app/assets/config/manifest.js:
--------------------------------------------------------------------------------
1 | //= link application.css
2 | //= link apple-touch-icon-144x144-precomposed.png
3 | //= link apple-touch-icon-72x72-precomposed.png
4 | //= link apple-touch-icon-precomposed.png
5 | //= link favicon.ico
6 | //= link application.js
7 |
--------------------------------------------------------------------------------
/app/assets/images/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/.keep
--------------------------------------------------------------------------------
/app/assets/images/app_store_en_badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/app_store_en_badge.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-114x114-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-114x114-precomposed.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-114x114.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-120x120-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-120x120-precomposed.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-144x144-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-144x144-precomposed.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-144x144.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-152x152-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-152x152-precomposed.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-180x180-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-180x180-precomposed.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-57x57-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-57x57-precomposed.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-57x57.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-72x72-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-72x72-precomposed.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-72x72.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-76x76-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-76x76-precomposed.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/app/assets/images/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/apple-touch-icon.png
--------------------------------------------------------------------------------
/app/assets/images/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/bg.jpg
--------------------------------------------------------------------------------
/app/assets/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/favicon.ico
--------------------------------------------------------------------------------
/app/assets/images/google_play_en_badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/google_play_en_badge.png
--------------------------------------------------------------------------------
/app/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/logo.png
--------------------------------------------------------------------------------
/app/assets/images/saml_configure_datadog_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/saml_configure_datadog_01.png
--------------------------------------------------------------------------------
/app/assets/images/saml_configure_datadog_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/saml_configure_datadog_02.png
--------------------------------------------------------------------------------
/app/assets/images/saml_configure_datadog_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/saml_configure_datadog_03.png
--------------------------------------------------------------------------------
/app/assets/images/saml_configure_datadog_04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/saml_configure_datadog_04.png
--------------------------------------------------------------------------------
/app/assets/images/saml_configure_datadog_05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/saml_configure_datadog_05.png
--------------------------------------------------------------------------------
/app/assets/images/saml_configure_datadog_06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/saml_configure_datadog_06.png
--------------------------------------------------------------------------------
/app/assets/images/saml_configure_datadog_07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/saml_configure_datadog_07.png
--------------------------------------------------------------------------------
/app/assets/images/saml_configure_datadog_08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/saml_configure_datadog_08.png
--------------------------------------------------------------------------------
/app/assets/images/saml_configure_datadog_09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/assets/images/saml_configure_datadog_09.png
--------------------------------------------------------------------------------
/app/assets/javascripts/admin.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/api_resources.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
5 | API_RESOURCE_NAME_FORMAT_ERROR_MSG = "Please enter valid name containing only alphanumeric (a-z, A-Z, 0-9), underscore (_) and dash (-)"
6 | API_RESOURCE_NAME_UNIQUENESS_ERROR_MSG = "API name already taken"
7 | API_RESOURCE_DESC_REQUIRED_ERROR_MSG = "Please enter description"
8 |
9 | api_resources_ready = ->
10 | $('#api_resource_name').on 'blur', ->
11 | valid = validate_pattern($('#api_resource_name'), '^[a-zA-Z0-9_-]+$', API_RESOURCE_NAME_FORMAT_ERROR_MSG)
12 | if valid
13 | validate_uniqueness($('#api_resource_name'), '/api_resources/search', API_RESOURCE_NAME_UNIQUENESS_ERROR_MSG)
14 |
15 | $('#api_resource_description').on 'blur', ->
16 | validate_required($('#api_resource_description'), API_RESOURCE_DESC_REQUIRED_ERROR_MSG)
17 |
18 | $('#new_api_resource').submit (event) ->
19 | if $('.is-invalid').length > 0
20 | event.preventDefault()
21 | event.stopPropagation()
22 | return
23 |
24 | $(document).on('turbolinks:load', api_resources_ready)
25 |
--------------------------------------------------------------------------------
/app/assets/javascripts/application.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into application.js, which will include all the files
2 | // listed below.
3 | //
4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6 | //
7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8 | // compiled file.
9 | //
10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11 | // about supported directives.
12 | //
13 | // require jquery3
14 | // require popper
15 | // require bootstrap-sprockets
16 | // require jquery_ujs
17 | // require turbolinks
18 | // require_tree .
19 |
--------------------------------------------------------------------------------
/app/assets/javascripts/bootstrap.js.coffee:
--------------------------------------------------------------------------------
1 | jQuery ->
2 | $("a[rel~=popover], .has-popover").popover()
3 | $("a[rel~=tooltip], .has-tooltip").tooltip()
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/groups.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/home.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/host_access_groups.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/host_machine_groups.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/host_machines.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
5 | host_machines_ready = ->
6 | $('#group_id').selectize
7 | maxItems: 1
8 | valueField: 'id'
9 | labelField: 'name'
10 | searchField: 'name'
11 | create: false
12 | render: option: (item, escape) ->
13 | '
' + escape(item.name) + '
'
14 | load: (query, callback) ->
15 | if !query.length
16 | return callback()
17 |
18 | # Use remote as source
19 | $.ajax
20 | url: '/groups/search?q=' + encodeURIComponent(query)
21 | type: 'GET'
22 | error: ->
23 | callback()
24 | return
25 | success: (res) ->
26 | callback res
27 | return
28 | return
29 |
30 | $('#group_id').on 'change', ->
31 | set_allow_submit($(this).val(), $(this))
32 |
33 | $(document).on('turbolinks:load', host_machines_ready)
34 |
--------------------------------------------------------------------------------
/app/assets/javascripts/nss.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/omniauth_callbacks.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/profile.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/users.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://coffeescript.org/
4 |
5 | users_ready = ->
6 | $('#group_id').selectize
7 | maxItems: 1
8 | valueField: 'id'
9 | labelField: 'name'
10 | searchField: 'name'
11 | create: false
12 | render: option: (item, escape) ->
13 | '' + escape(item.name) + '
'
14 | load: (query, callback) ->
15 | if !query.length
16 | return callback()
17 |
18 | # Use remote as source
19 | $.ajax
20 | url: '/groups/search?q=' + encodeURIComponent(query)
21 | type: 'GET'
22 | error: ->
23 | callback()
24 | return
25 | success: (res) ->
26 | callback res
27 | return
28 | return
29 |
30 | $('#group_id').on 'change', ->
31 | set_allow_submit($(this).val(), $(this))
32 |
33 | $(document).on('turbolinks:load', users_ready)
34 |
--------------------------------------------------------------------------------
/app/assets/javascripts/utilities.coffee:
--------------------------------------------------------------------------------
1 | # Utility functions
2 |
3 | @append_error_msg = (elem, res, msg) ->
4 | if !res
5 | elem.addClass('is-invalid')
6 | elem.next('.invalid-feedback').html(msg)
7 | else
8 | elem.removeClass('is-invalid')
9 | elem.next('.invalid-feedback').html('')
10 |
11 | @validate_required = (elem, msg) ->
12 | input = elem.val()
13 | append_error_msg(elem, input, msg)
14 | return !!input
15 |
16 | @validate_pattern = (elem, pattern, msg) ->
17 | input = elem.val()
18 | regex = new RegExp(pattern)
19 | validate_regex = regex.test(input)
20 | append_error_msg(elem, validate_regex, msg)
21 | return !!validate_regex
22 |
23 | @validate_uniqueness = (elem, check_url, msg) ->
24 | input = elem.val()
25 | $.ajax
26 | url: check_url + '?q=' + encodeURIComponent(input) + '&exact=true'
27 | type: 'GET'
28 | error: ->
29 | return
30 | success: (res) ->
31 | append_error_msg(elem, $.isEmptyObject(res), msg)
32 | return
33 |
34 | @set_allow_submit = (cond, elem) ->
35 | curSubmit = $("input[type=submit]", $(elem).parents('form'))
36 | if !!cond
37 | curSubmit.prop("disabled", false)
38 | else
39 | curSubmit.prop('disabled', true)
40 | return
41 |
--------------------------------------------------------------------------------
/app/assets/javascripts/viewport.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * IE10 viewport hack for Surface/desktop Windows 8 bug
3 | * Copyright 2014-2015 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | // See the Getting Started docs for more information:
8 | // http://getbootstrap.com/getting-started/#support-ie10-width
9 |
10 | (function () {
11 | 'use strict';
12 |
13 | if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
14 | var msViewportStyle = document.createElement('style')
15 | msViewportStyle.appendChild(
16 | document.createTextNode(
17 | '@-ms-viewport{width:auto!important}'
18 | )
19 | )
20 | document.querySelector('head').appendChild(msViewportStyle)
21 | }
22 |
23 | })();
24 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9 | * compiled file so the styles you add here take precedence over styles defined in any styles
10 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11 | * file per style scope.
12 | *
13 | *= require_tree .
14 | *= require_self
15 | *= stub 'profile'
16 | *= stub 'general'
17 | */
18 |
19 |
20 | @import url(https://fonts.googleapis.com/css?family=Roboto:300);
21 | @import url(https://fonts.googleapis.com/css?family=Lato:300);
22 | @import "bootstrap";
23 | @import "font-awesome";
24 |
25 | /*
26 | * https://github.com/ladjs/bootstrap-social
27 | */
28 | @import "bootstrap-social";
29 | a.btn { color: white!important; }
30 | .form-group .field_with_errors { display: block; background: none; }
31 | .form-group .field_with_errors label::after { content: ' *'; color: red; }
32 | body {
33 | font-family: 'Roboto', 'Lato', sans-serif;
34 | }
35 |
36 | .container-profile {
37 | max-width: 768px;
38 | min-width: 768px;
39 | }
40 |
41 | a:visited {
42 | color: blue;
43 | }
44 | /* mouse over link */
45 | a:hover {
46 | color: blue;
47 | background: none;
48 | }
49 | .table-responsive { overflow-x: inherit; }
50 |
51 | #configAppTabsContent .tab-pane { padding-top: 20px; }
52 | #configAppTabsContent ol li { margin-top: 10px; }
53 | #configAppTabsContent li > ol { margin-bottom: 10px; }
54 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/general.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding-top: 70px;
3 | }
4 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/home.scss.erb:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the Home controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: http://sass-lang.com/
4 |
5 | :root {
6 | --input-padding-x: .75rem;
7 | --input-padding-y: .75rem;
8 | }
9 |
10 | html,
11 | body {
12 | height: 100%;
13 | }
14 | @import url(https://fonts.googleapis.com/css?family=Roboto:300);
15 | @import url(https://fonts.googleapis.com/css?family=Lato:300);
16 |
17 | .home {
18 | display: -ms-flexbox;
19 | display: -webkit-box;
20 | display: flex;
21 | -ms-flex-align: center;
22 | -ms-flex-pack: center;
23 | -webkit-box-align: center;
24 | align-items: center;
25 | -webkit-box-pack: center;
26 | justify-content: center;
27 | padding-top: 40px;
28 | padding-bottom: 40px;
29 | font-family: 'Roboto', sans-serif;
30 | font-size: 16px;
31 | font-weight: 300;
32 | color: white;
33 | line-height: 30px;
34 | text-align: center;
35 | background-image: image-url('bg.jpeg');
36 | background-size: cover;
37 | background-repeat: no-repeat;
38 | background-color: #444444;
39 | background-position: 50%;
40 | }
41 |
42 | .form-signin {
43 | width: 100%;
44 | max-width: 420px;
45 | padding: 15px;
46 | margin: 0 auto;
47 | }
48 |
49 | .token-qr table {
50 | border-width: 0;
51 | border-style: none;
52 | border-color: #0000ff;
53 | border-collapse: collapse;
54 | }
55 |
56 | .token-qr td {
57 | border-left: solid 5px #000;
58 | padding: 0;
59 | margin: 0;
60 | width: 0px;
61 | height: 5px;
62 | }
63 |
64 | .token-qr td.black { border-color: #000; }
65 | .token-qr td.white { border-color: #fff; }
66 |
67 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/profile.css:
--------------------------------------------------------------------------------
1 | /* Everything but the jumbotron gets side spacing for mobile first views */
2 |
3 | .container-profile {
4 | max-width: 730px;
5 | min-width: 768px;
6 | }
7 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/scaffolds.scss:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #fff;
3 | color: #333;
4 | font-family: verdana, arial, helvetica, sans-serif;
5 | font-size: 13px;
6 | line-height: 18px;
7 | }
8 |
9 | p, ol, ul, td {
10 | font-family: verdana, arial, helvetica, sans-serif;
11 | font-size: 13px;
12 | line-height: 18px;
13 | }
14 |
15 | pre {
16 | background-color: #eee;
17 | padding: 10px;
18 | font-size: 11px;
19 | }
20 |
21 | a {
22 | color: #000;
23 |
24 | &:visited {
25 | color: #666;
26 | }
27 |
28 | &:hover {
29 | color: #fff;
30 | background-color: #000;
31 | }
32 | }
33 |
34 | div {
35 | &.field, &.actions {
36 | margin-bottom: 10px;
37 | }
38 | }
39 |
40 | #notice {
41 | color: green;
42 | }
43 |
44 | .field_with_errors {
45 | padding: 2px;
46 | background-color: red;
47 | display: table;
48 | }
49 |
50 | #error_explanation {
51 | width: 450px;
52 | border: 2px solid red;
53 | padding: 7px;
54 | padding-bottom: 0;
55 | margin-bottom: 20px;
56 | background-color: #f0f0f0;
57 |
58 | h2 {
59 | text-align: left;
60 | font-weight: bold;
61 | padding: 5px 5px 5px 15px;
62 | font-size: 12px;
63 | margin: -7px;
64 | margin-bottom: 0px;
65 | background-color: #c00;
66 | color: #fff;
67 | }
68 |
69 | ul li {
70 | font-size: 12px;
71 | list-style: square;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/app/clients/data_dog_client.rb:
--------------------------------------------------------------------------------
1 | class DataDogClient
2 | include HTTParty
3 | base_uri 'https://api.datadoghq.com/api/v1'
4 |
5 | def initialize(app_key, api_key)
6 | @base_path = 'https://api.datadoghq.com/api/v1'
7 | @app_key = app_key
8 | @api_key = api_key
9 | @headers = {
10 | 'Content-Type' => 'application/json',
11 | 'Accept' => 'application/json',
12 | }
13 | end
14 |
15 | def get_user(email)
16 | url = append_auth("/user/#{email}")
17 | response = self.class.get(url, headers: @headers)
18 | if response.success?
19 | JSON.parse(response.body)['user']
20 | else
21 | {}
22 | end
23 | end
24 |
25 | def new_user(email)
26 | url = append_auth('/user')
27 | response = self.class.post(url, body: { handle: email }.to_json, headers: @headers)
28 | if response.success?
29 | JSON.parse(response.body)['user']
30 | else
31 | {}
32 | end
33 | end
34 |
35 | def activate_user(email)
36 | url = append_auth("/user/#{email}")
37 | response = self.class.put(url, body: { email: email, disabled: false }.to_json, headers: @headers)
38 | if response.success?
39 | JSON.parse(response.body)['user']
40 | else
41 | {}
42 | end
43 | end
44 |
45 | def deactivate_user(email)
46 | url = append_auth("/user/#{email}")
47 | response = self.class.put(url, body: { email: email, disabled: true }.to_json, headers: @headers)
48 | if response.success?
49 | JSON.parse(response.body)['user']
50 | else
51 | {}
52 | end
53 | end
54 |
55 | private
56 |
57 | def append_auth(str)
58 | auth_str = "api_key=#{@api_key}&application_key=#{@app_key}"
59 | str += str.include?('?') ? "{auth_str}" : "?#{auth_str}"
60 | str
61 | end
62 | end
63 |
--------------------------------------------------------------------------------
/app/controllers/admin_controller.rb:
--------------------------------------------------------------------------------
1 | class AdminController < ApplicationController
2 | def index; end
3 | end
4 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/base_controller.rb:
--------------------------------------------------------------------------------
1 | class ::Api::V1::BaseController < ActionController::Base
2 | protect_from_forgery with: :null_session
3 | before_action :authenticate_user_from_token!
4 |
5 | def authenticate_user_from_token!
6 | if get_token.nil? || !AccessToken.valid_token(get_token)
7 | raise_unauthorized
8 | end
9 | end
10 |
11 | protected
12 |
13 | def current_user
14 | access_token = AccessToken.find_token(get_token)
15 | access_token.user
16 | end
17 |
18 | private
19 |
20 | def get_token
21 | if params.key?(:access_token)
22 | params[:access_token]
23 | elsif params.key?(:token)
24 | params[:token]
25 | elsif request.headers.key?(:Authorization)
26 | request.headers[:Authorization].split(' ').last
27 | end
28 | end
29 |
30 | def raise_unauthorized
31 | head :unauthorized
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/endpoints_controller.rb:
--------------------------------------------------------------------------------
1 | class ::Api::V1::EndpointsController < ::Api::V1::BaseController
2 | before_action :authorize_user
3 |
4 | def create
5 | endpoint = Endpoint.new(endpoint_param)
6 | if endpoint.save
7 | render json: {
8 | id: endpoint.id,
9 | path: endpoint.path,
10 | method: endpoint.method,
11 | }
12 | else
13 | render json: { status: endpoint.errors }, status: :unprocessable_entity
14 | end
15 | end
16 |
17 | def add_group
18 | endpoint = Endpoint.find_by(id: params[:id])
19 | if endpoint.nil?
20 | return head :not_found
21 | end
22 |
23 | group = Group.find_by(group_param)
24 | group_endpoint = GroupEndpoint.new(group: group, endpoint: endpoint)
25 |
26 | if group_endpoint.save
27 | render json: {}
28 | else
29 | head :unprocessable_entity
30 | end
31 | end
32 |
33 | private
34 |
35 | def authorize_user
36 | unless current_user.admin?
37 | head :forbidden
38 | end
39 | end
40 |
41 | def group_param
42 | params.require(:group).permit(:id)
43 | end
44 |
45 | def endpoint_param
46 | params.require(:endpoint).permit(:path, :method)
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/groups_controller.rb:
--------------------------------------------------------------------------------
1 | class ::Api::V1::GroupsController < ::Api::V1::BaseController
2 | def create
3 | if current_user.admin?
4 | @group = Group.new(group_params)
5 | if @group.save
6 | render json: {
7 | id: @group.id,
8 | name: @group.name,
9 | }, status: :ok
10 | else
11 | is_taken = @group.errors.details[:name].select { |x| x[:error] == :taken }
12 |
13 | if !is_taken.blank?
14 | existing_group = Group.find_by(name: @group.name)
15 | render json: {
16 | status: 'group already exist',
17 | id: existing_group.id,
18 | name: existing_group.name,
19 | }, status: :unprocessable_entity
20 | else
21 | render json: {
22 | status: 'error',
23 | }, status: :unprocessable_entity
24 | end
25 | end
26 | end
27 | end
28 |
29 | def add_user
30 | @group = Group.find_by(id: params[:id])
31 | return head :not_found unless @group.present?
32 |
33 | return raise_unauthorized unless current_user.admin? || @group.admin?(current_user)
34 |
35 | user = User.find_by(id: params[:user_id])
36 | return head :unprocessable_entity unless user.present?
37 |
38 | expiration_date = params[:expiration_date]
39 | @group.add_user_with_expiration(params[:user_id], expiration_date)
40 | head :no_content
41 | end
42 |
43 | private
44 |
45 | def group_params
46 | params.require(:group).permit(:name)
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/vpns_controller.rb:
--------------------------------------------------------------------------------
1 | class ::Api::V1::VpnsController < ::Api::V1::BaseController
2 | before_action :set_vpn, only: [:assign_group]
3 |
4 | def create
5 | if current_user.admin?
6 | @vpn = Vpn.new(vpn_params)
7 | @vpn.uuid = SecureRandom.uuid
8 | if @vpn.save
9 | render json: {
10 | id: @vpn.id,
11 | name: @vpn.name,
12 | host_name: @vpn.host_name,
13 | ip_address: @vpn.ip_address,
14 | }, status: :ok
15 | else
16 | render json: { status: 'error' }, status: :unprocessable_entity
17 | end
18 | end
19 | end
20 |
21 | def assign_group
22 | if current_user.admin?
23 | @vpn.groups.delete_all
24 | @vpn.groups << Group.where(id: params[:group_id]).first
25 | render json: { status: 'group assigned' }, status: :ok
26 | end
27 | end
28 |
29 | private
30 |
31 | def set_vpn
32 | @vpn = Vpn.find(params[:id])
33 | end
34 |
35 | def vpn_params
36 | params.require(:vpn).permit(:name, :host_name, :ip_address)
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | # Prevent CSRF attacks by raising an exception.
3 | # For APIs, you may want to use :null_session instead.
4 | protect_from_forgery with: :exception
5 |
6 | def render_404
7 | respond_to do |format|
8 | format.html { render file: "#{Rails.root}/public/404", layout: false, status: :not_found }
9 | format.xml { head :not_found }
10 | format.any { head :not_found }
11 | end
12 | end
13 |
14 | def authenticate_access_token!
15 | unless AccessToken.valid_token(params[:token])
16 | render_error(['Unauthorized'], :unauthorized)
17 | end
18 | end
19 |
20 | def render_error(errors, status = 400)
21 | render 'common/errors', locals: { errors: errors }, status: status
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/controllers/concerns/.keep
--------------------------------------------------------------------------------
/app/controllers/home_controller.rb:
--------------------------------------------------------------------------------
1 | class HomeController < ApplicationController
2 |
3 | before_action :check_signed_in
4 |
5 | def check_signed_in
6 | redirect_to profile_path if signed_in?
7 | end
8 |
9 | def index; end
10 | end
11 |
--------------------------------------------------------------------------------
/app/controllers/host_controller.rb:
--------------------------------------------------------------------------------
1 | class HostController < ApplicationController
2 | before_action :authenticate_user!
3 | def add_host
4 | @user = User.find(params[:id])
5 | if current_user.admin?
6 | host = Host.new
7 | host.user = @user
8 | host.host_pattern = params[:host_pattern]
9 | host.save!
10 |
11 | end
12 | redirect_to user_path
13 | end
14 |
15 | def delete_host
16 | @user = User.find(params[:user_id])
17 | if current_user.admin?
18 | @host = Host.find(params[:id])
19 | @host.deleted_by = current_user.id
20 | @host.save!
21 | @host.destroy
22 | end
23 |
24 | redirect_to user_path(@user)
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/app/controllers/host_machine_groups_controller.rb:
--------------------------------------------------------------------------------
1 | class HostMachineGroupsController < ApplicationController
2 | def show
3 | @host_machines = HostMachine.all
4 | end
5 |
6 | def create
7 | @host_machine = HostMachine.new(host_machine_params)
8 | respond_to do |format|
9 | @host_machine.save
10 | format.html { redirect_to :show, notice: 'host_machine was successfully created.' }
11 | format.json { render status: :created, json: "#{@host_machine.name}host created" }
12 | end
13 | end
14 |
15 | private
16 |
17 | # Use callbacks to share common setup or constraints between actions.
18 | def set_host_machine
19 | @host_machine = host_machine.find(params[:id])
20 | end
21 |
22 | # Never trust parameters from the scary internet, only allow the white list through.
23 | def host_machine_params
24 | params.require(:host_machine).permit(:name)
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/app/controllers/pings_controller.rb:
--------------------------------------------------------------------------------
1 | class PingsController < ApplicationController
2 | def show
3 | render plain: 'pong'
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/controllers/users/auth_controller.rb:
--------------------------------------------------------------------------------
1 | class Users::AuthController < ApplicationController
2 |
3 | def log_in
4 | unless ENV['SIGN_IN_TYPE'] == 'form'
5 | return redirect_to root_path
6 | end
7 |
8 | email = params.require(:email)
9 | name = params.require(:name)
10 |
11 | unless User.valid_domain? email.split('@').last
12 | return render plain: 'Your domain is unauthorized', status: :unauthorized
13 | end
14 |
15 | user = User.create_user(name, email)
16 | user.generate_two_factor_auth
17 | sign_in_and_redirect user, event: :authentication
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/app/controllers/users/omniauth_callbacks_controller.rb:
--------------------------------------------------------------------------------
1 | class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
2 | def google_oauth2
3 | # You need to implement the method below in your model (e.g. app/models/user.rb)
4 | #
5 | data = request.env['omniauth.auth']
6 | domain = data['info']['email'].split('@').last
7 |
8 | unless User.valid_domain? domain
9 | return render plain: 'Your domain is unauthorized', status: :unauthorized
10 | end
11 |
12 | @user = User.create_user(data.info['name'], data.info['email'])
13 |
14 | if @user.persisted?
15 | @user.generate_two_factor_auth
16 | sign_in_and_redirect @user, event: :authentication
17 | else
18 | session['devise.google_data'] = request.env['omniauth.auth']
19 | redirect_to new_user_registration_url
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/app/controllers/vpn_domain_name_servers_controller.rb:
--------------------------------------------------------------------------------
1 | class VpnsController < ApplicationController
2 | before_action :authorize_user
3 | before_action :set_vpn, only: %i[show edit update destroy user_associated_groups]
4 |
5 | def destroy; end
6 | end
7 |
8 | #TODO fix this in future. This is something not great.
9 | class VpnDomainNameServersController < ApplicationController
10 | end
11 |
--------------------------------------------------------------------------------
/app/helpers/admin_helper.rb:
--------------------------------------------------------------------------------
1 | module AdminHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/api_resources_helper.rb:
--------------------------------------------------------------------------------
1 | module ApiResourcesHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | def add_placeholder_to_list(list, placeholder, string_convert: 'titleize')
3 | (list.map do |row|
4 | name = string_convert.present? ? row.send(string_convert.to_sym) : row
5 | [name, row]
6 | end).insert(0, [placeholder, ''])
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/helpers/group_helper.rb:
--------------------------------------------------------------------------------
1 | module GroupHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/groups_helper.rb:
--------------------------------------------------------------------------------
1 | module GroupsHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/home_helper.rb:
--------------------------------------------------------------------------------
1 | module HomeHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/host_access_groups_helper.rb:
--------------------------------------------------------------------------------
1 | module HostAccessGroupsHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/host_machine_groups_helper.rb:
--------------------------------------------------------------------------------
1 | module HostMachineGroupsHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/host_machines_helper.rb:
--------------------------------------------------------------------------------
1 | module HostMachinesHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/nss_helper.rb:
--------------------------------------------------------------------------------
1 | module NssHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/omniauth_callbacks_helper.rb:
--------------------------------------------------------------------------------
1 | module OmniauthCallbacksHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/profile_helper.rb:
--------------------------------------------------------------------------------
1 | module ProfileHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/helpers/users_helper.rb:
--------------------------------------------------------------------------------
1 | module UsersHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/lib/datadog.rb:
--------------------------------------------------------------------------------
1 | class Datadog < SamlApp
2 |
3 | def initialize(org_id)
4 | @app_name = 'datadog'
5 | super(org_id)
6 | if @config.persisted?
7 | @client = DataDogClient.new(
8 | @config.config['app_key'],
9 | @config.config['api_key']
10 | )
11 | else
12 | @config.config = { app_key: '', api_key: '' }
13 | end
14 | end
15 |
16 | def save_config(sso_url, config = {})
17 | @config.config = @config.config.merge(config)
18 | super(sso_url, config)
19 | end
20 |
21 | def add_user(email)
22 | user_detail_response = @client.get_user(email)
23 | response = if user_detail_response.eql?({})
24 | @client.new_user(email)
25 | else
26 | @client.activate_user(email)
27 | end
28 | super(email) unless response.eql?({})
29 | end
30 |
31 | def remove_user(email)
32 | response = @client.deactivate_user(email)
33 | super(email) unless response.eql?({})
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/app/lib/saml_app.rb:
--------------------------------------------------------------------------------
1 | class SamlApp
2 |
3 | attr_accessor :config, :app_name
4 |
5 | def initialize(org_id)
6 | @config = SamlAppConfig.find_or_initialize_by(
7 | app_name: @app_name, organisation_id: org_id
8 | )
9 | end
10 |
11 | def save_config(sso_url, config = {})
12 | unless @config.persisted?
13 | group_name = "#{@config.organisation.slug}_saml_#{app_name}_users"
14 | @config.group = Group.find_or_create_by(name: group_name)
15 | end
16 | @config.sso_url = sso_url
17 | @config.save
18 | end
19 |
20 | def add_user(email)
21 | user = User.where(email: email).first
22 | unless user.blank?
23 | @config.group.add_user(user.id)
24 | return true
25 | end
26 | false
27 | end
28 |
29 | def remove_user(email)
30 | user = User.where(email: email).first
31 | unless user.blank?
32 | @config.group.remove_user(user.id)
33 | return true
34 | end
35 | false
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/app/mailers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/mailers/.keep
--------------------------------------------------------------------------------
/app/models/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/models/.keep
--------------------------------------------------------------------------------
/app/models/access_token.rb:
--------------------------------------------------------------------------------
1 | class AccessToken < ApplicationRecord
2 | attr_accessor :token
3 |
4 |
5 | belongs_to :user
6 |
7 | before_save :hash_token!
8 |
9 | def self.find_token challenge_token
10 | AccessToken.where(hashed_token: Digest::SHA512.hexdigest(challenge_token)).first
11 | end
12 |
13 | def self.valid_token challenge_token
14 | find_token(challenge_token).present?
15 | end
16 |
17 | private
18 |
19 | def hash_token!
20 | self.hashed_token = Digest::SHA512.hexdigest self.token unless self.token.blank?
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/app/models/api_resource.rb:
--------------------------------------------------------------------------------
1 | class ApiResource < ApplicationRecord
2 | attr_accessor :access_key
3 |
4 | validates :name, format: { with: /\A[a-zA-Z0-9_-]+\Z/ }, uniqueness: true, presence: true
5 | validates :access_key, presence: true, on: :create
6 | belongs_to :user
7 | belongs_to :group
8 |
9 | before_save :hash_access_key!
10 |
11 | def self.authenticate access_key, access_token
12 | api_resource = ApiResource.find_by(hashed_access_key: Digest::SHA512.hexdigest(access_key))
13 | user = AccessToken.find_by(hashed_token: Digest::SHA512.hexdigest(access_token)).user
14 | api_resource.group.member? user
15 | end
16 |
17 | private
18 |
19 | def hash_access_key!
20 | self.hashed_access_key = Digest::SHA512.hexdigest self.access_key unless self.access_key.blank?
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | class ApplicationRecord < ActiveRecord::Base
2 | self.abstract_class = true
3 | end
4 |
--------------------------------------------------------------------------------
/app/models/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/models/concerns/.keep
--------------------------------------------------------------------------------
/app/models/endpoint.rb:
--------------------------------------------------------------------------------
1 | class Endpoint < ApplicationRecord
2 |
3 |
4 | has_many :group_endpoints
5 | has_many :groups, through: :group_endpoints
6 |
7 | validates_presence_of :path
8 | validates_presence_of :method
9 | validates :method, inclusion: { in: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] }
10 | validates_format_of :path, with: /\A((\/(([0-9, a-z,\-,_]+)|(:[a-z]+))+)+|\/)\Z/i
11 | end
12 |
--------------------------------------------------------------------------------
/app/models/group_admin.rb:
--------------------------------------------------------------------------------
1 | class GroupAdmin < ApplicationRecord
2 | belongs_to :user
3 | belongs_to :group
4 | end
5 |
--------------------------------------------------------------------------------
/app/models/group_association.rb:
--------------------------------------------------------------------------------
1 | class GroupAssociation < ApplicationRecord
2 | belongs_to :user
3 | belongs_to :group
4 |
5 | def self.revoke_expired(date = Date.today)
6 | where('expiration_date < ?', date).destroy_all
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/models/group_endpoint.rb:
--------------------------------------------------------------------------------
1 | class GroupEndpoint < ApplicationRecord
2 |
3 |
4 | belongs_to :group
5 | belongs_to :endpoint
6 |
7 | validates :group, uniqueness: { scope: :endpoint }
8 | validates_presence_of :group
9 | validates_presence_of :endpoint
10 | end
11 |
--------------------------------------------------------------------------------
/app/models/host.rb:
--------------------------------------------------------------------------------
1 | class Host < ApplicationRecord
2 | belongs_to :user
3 | acts_as_paranoid
4 | end
5 |
--------------------------------------------------------------------------------
/app/models/host_access_group.rb:
--------------------------------------------------------------------------------
1 | class HostAccessGroup < ApplicationRecord
2 | belongs_to :host_machine
3 | belongs_to :group
4 | end
5 |
--------------------------------------------------------------------------------
/app/models/host_machine.rb:
--------------------------------------------------------------------------------
1 | class HostMachine < ApplicationRecord
2 |
3 | has_many :host_access_groups
4 | has_many :groups, through: :host_access_groups
5 | validates_uniqueness_of :name, case_sensitive: false
6 | validates :name, presence: true
7 |
8 | before_create :set_lower_case_name
9 | before_create :set_host_access_key
10 |
11 | def set_host_access_key
12 | self.access_key = ROTP::Base32.random_base32
13 | end
14 |
15 | def set_lower_case_name
16 | self.name = self.name.downcase
17 | end
18 |
19 | def self.get_group_response name
20 | host_machine = HostMachine.find_by_name(name)
21 | response = {}
22 | return response if host_machine.blank?
23 | response[:host_name] = name
24 | response[:groups] = host_machine.groups.collect { |g| g.name }
25 | response
26 | end
27 |
28 | def sysadmins
29 | users = GroupAssociation.
30 | select(:user_id).
31 | distinct.
32 | joins(:user).
33 | where("group_id IN (?)", groups.collect(&:id)).
34 | collect(&:user_id)
35 | end
36 |
37 | def add_host_group(name)
38 | name = name.squish
39 | if name.present?
40 | name = "#{name}_host_group"
41 | self.add_group(name.downcase)
42 | end
43 | end
44 |
45 | def add_group(name)
46 | name = name.squish
47 | if name.present?
48 | group = Group.find_or_initialize_by(name: name.downcase)
49 | self.groups << group unless self.groups.include? group
50 | self.save
51 | end
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/app/models/ip_address.rb:
--------------------------------------------------------------------------------
1 | class IpAddress < ApplicationRecord
2 | end
3 |
--------------------------------------------------------------------------------
/app/models/saml_app_config.rb:
--------------------------------------------------------------------------------
1 | class SamlAppConfig < ApplicationRecord
2 | belongs_to :group
3 | belongs_to :organisation
4 |
5 | serialize :config, JSON
6 |
7 | def self.get_config(app_name, org_id)
8 | SamlAppConfig.find_or_initialize_by(
9 | app_name: app_name, organisation_id: org_id
10 | )
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/models/vpn_domain_name_server.rb:
--------------------------------------------------------------------------------
1 | class VpnDomainNameServer < ApplicationRecord
2 | belongs_to :vpn
3 | end
4 |
--------------------------------------------------------------------------------
/app/models/vpn_group_association.rb:
--------------------------------------------------------------------------------
1 | class VpnGroupAssociation < ApplicationRecord
2 | belongs_to :vpn
3 | belongs_to :group
4 | end
5 |
6 |
--------------------------------------------------------------------------------
/app/models/vpn_group_user_association.rb:
--------------------------------------------------------------------------------
1 | class VpnGroupUserAssociation < ApplicationRecord
2 | belongs_to :vpn
3 | belongs_to :user
4 | end
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/models/vpn_search_domain.rb:
--------------------------------------------------------------------------------
1 | class VpnSearchDomain < ApplicationRecord
2 | belongs_to :vpn
3 | end
4 |
--------------------------------------------------------------------------------
/app/models/vpn_supplemental_match_domain.rb:
--------------------------------------------------------------------------------
1 | class VpnSupplementalMatchDomain < ApplicationRecord
2 | belongs_to :vpn
3 | end
4 |
--------------------------------------------------------------------------------
/app/validators/email_validator.rb:
--------------------------------------------------------------------------------
1 | class EmailValidator < ActiveModel::EachValidator
2 | def validate_each(record, attribute, value)
3 | unless value.to_s.match?(/\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i)
4 | record.errors[attribute] << (options[:message] || 'is not an email')
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/app/views/admin/index.html.slim:
--------------------------------------------------------------------------------
1 | h1 hello
2 |
--------------------------------------------------------------------------------
/app/views/api/v1/users/show.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.(@user, :email, :uid, :name, :active, :admin, :home_dir, :shell, :public_key, :user_login_id, :product_name)
2 | json.groups @user.groups, :gid, :name
3 |
--------------------------------------------------------------------------------
/app/views/api_resources/_api_resource.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.extract! api_resource, :id, :name, :description, :access_key, :created_at, :updated_at
2 | json.url api_resource_url(api_resource, format: :json)
3 |
--------------------------------------------------------------------------------
/app/views/api_resources/_form.html.slim:
--------------------------------------------------------------------------------
1 | = form_for @api_resource, :class => 'form-horizontal', html: {novalidate: 'true'} do |f|
2 | - if @api_resource.errors.any?
3 | #error_explanation
4 | h2 = "#{pluralize(@api_resource.errors.count, "error")} prohibited this api_resource from being saved:"
5 | ul
6 | - @api_resource.errors.full_messages.each do |message|
7 | li = message
8 |
9 | hr
10 | .mb-3
11 | label for="name"
12 | | API Name
13 | = f.text_field :name, required: true, class: "form-control", placeholder: "API Name"
14 | .invalid-feedback
15 | .mb-3
16 | label for="description"
17 | | Description
18 | = f.text_field :description, required: true, class: "form-control", placeholder: "Description"
19 | .invalid-feedback
20 | .mb-4
21 | = f.submit "Save", class: "btn btn-primary pull-right"
22 |
--------------------------------------------------------------------------------
/app/views/api_resources/edit.html.slim:
--------------------------------------------------------------------------------
1 | h1 Editing api_resource
2 |
3 | == render 'form'
4 |
5 | => link_to 'Show', @api_resource
6 | '|
7 | =< link_to 'Back', api_resources_path
8 |
9 |
--------------------------------------------------------------------------------
/app/views/api_resources/index.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-8
2 | - if notice.present?
3 | .alert.alert-primary role="alert"
4 | #notice
5 | = notice
6 |
7 |
8 | h4 API Keys
9 |
10 | table.table.responsive
11 | thead
12 | tr
13 | th Name
14 | th Description
15 | th Access key
16 | th Owner
17 | th Access Group
18 | th
19 |
20 | tbody
21 | - @api_resources.each do |api_resource|
22 | tr
23 | td = api_resource.name
24 | td = api_resource.description
25 | td = link_to 'Regenerate', regenerate_access_key_api_resource_path(api_resource), data: { confirm: 'Are you sure?' }
26 | td = link_to api_resource.user.name, api_resource.user if api_resource.user.present?
27 | td = link_to api_resource.group.name, api_resource.group if api_resource.group.present?
28 | td = link_to 'Destroy', api_resource, data: { confirm: 'Are you sure?' }, method: :delete
29 |
30 | br
31 |
32 | javascript:
33 | $("#apiresource-index").addClass("active");
34 |
--------------------------------------------------------------------------------
/app/views/api_resources/index.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.array! @api_resources, partial: 'api_resources/api_resource', as: :api_resource
2 |
--------------------------------------------------------------------------------
/app/views/api_resources/new.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-4.col-md-offset-4
2 | - if notice.present?
3 | .alert.alert-primary role="alert"
4 | #notice
5 | = notice
6 | br
7 | h5 Create new API
8 |
9 | == render 'form'
10 |
11 | = link_to 'Back', api_resources_path
12 |
13 |
14 | javascript:
15 | $("#apiresource-index").addClass("active");
16 |
--------------------------------------------------------------------------------
/app/views/api_resources/show.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-4.col-md-offset-4
2 | - if notice.present?
3 | .alert.alert-primary role="alert"
4 | #notice
5 | = notice
6 | br
7 | h5 Show API
8 |
9 | hr
10 | .mb-3
11 | label for="name"
12 | | API Name
13 | p.form-control-static
14 | = @api_resource.name
15 | .mb-3
16 | label for="description"
17 | | Description
18 | p.form-control-static
19 | = @api_resource.description
20 | - if flash[:access_key]
21 | .mb-3
22 | label for="access_key"
23 | | Access Key
24 | .alert.alert-warning role="alert"
25 | | Important! please make note of this access key, you will see it only this once.
26 | = text_field_tag :access_key, flash[:access_key], class: 'form-control', readonly: ""
27 | .mb-4
28 | => link_to 'Edit', edit_api_resource_path(@api_resource)
29 | '|
30 | => link_to 'Regenerate Access Key', regenerate_access_key_api_resource_path(@api_resource), :data => {:confirm => 'Are you sure?'}
31 | '|
32 | =< link_to 'Back', api_resources_path
33 |
--------------------------------------------------------------------------------
/app/views/api_resources/show.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.partial! "api_resources/api_resource", api_resource: @api_resource
2 |
--------------------------------------------------------------------------------
/app/views/application/_admin.html.slim:
--------------------------------------------------------------------------------
1 | div
2 | ul.navbar-nav
3 | li.nav-item.active
4 | a.nav-link href="#" Users
5 | li.nav-item
6 | a.nav-link href="#" Groups
7 |
--------------------------------------------------------------------------------
/app/views/application/_groups_header.html.slim:
--------------------------------------------------------------------------------
1 | #notice
2 | = notice
3 | - if current_user.admin?
4 | = form_tag groups_path, method: 'post' do
5 | .row
6 | .col-md-8
7 | = text_field_tag "group[name]", "", class: "form-control", autofocus: true
8 | .col-md-4
9 | = submit_tag "Add Group", class: "form-control btn btn-sm btn-primary", name: nil
10 |
11 | br
12 | = form_tag groups_path, method: 'get' do
13 | .row
14 | .col-md-8
15 | = text_field_tag :group_search, params[:group_search], class: "form-control" , autofocus: true
16 | .col-md-4
17 | = submit_tag "Search groups", class: "form-control btn btn-sm btn-primary", name: nil
18 |
19 | hr
20 |
21 |
--------------------------------------------------------------------------------
/app/views/application/_host_header.html.slim:
--------------------------------------------------------------------------------
1 | ul.nav.nav-tabs
2 | li#host_machine role="presentation"
3 | = link_to "MyHosts", host_machines_path
4 | li#group role="presentation"
5 | = link_to "Groups", groups_path
6 | li#host_machine_search role="presentation"
7 | a href="#" Search Host
8 | li#host_machine_group_search role="presentation"
9 | a href="#" Search Host Groups
10 | p
11 | br
12 |
13 |
--------------------------------------------------------------------------------
/app/views/common/errors.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.success false
2 | json.errors errors
3 |
--------------------------------------------------------------------------------
/app/views/groups/_form.html.slim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/views/groups/_form.html.slim
--------------------------------------------------------------------------------
/app/views/groups/index.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col.container-profile
2 | - if current_user.admin?
3 | = form_tag groups_path, method: 'get', class: "p-2" do
4 | .input-group
5 | = text_field_tag :group_search, params[:group_search], class: "form-control" , autofocus: true, placeholder: "Search group name..."
6 | .input-group-append
7 | = submit_tag "Search", class: "button btn btn-secondary", name: nil
8 |
9 |
10 | - if @groups.count > 0
11 | h5 Your managed groups
12 | .table-responsive
13 | table.table.table-striped
14 | thead
15 | tr
16 | th Name
17 | th Gid
18 | th Group Admin
19 | tbody
20 | - @groups.each do |group|
21 | tr
22 | td
23 | = link_to "#{group.name}", group_path(group)
24 | td
25 | = "#{group.gid}"
26 | td
27 | - if group.group_admins.present?
28 | - group.group_admins.each do |admin|
29 | .row
30 | = "#{admin.user.try(:name)}"
31 |
32 |
33 | javascript:
34 | $("#group-index").addClass("active");
35 |
36 |
--------------------------------------------------------------------------------
/app/views/groups/new.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-4.col-md-offset-4
2 | h5 Add new group
3 | = form_for @group, :class => 'form-horizontal' do |f|
4 | - if @group.errors.any?
5 | #error_explanation
6 | h2 = "#{pluralize(@group.errors.count, "error")} prohibited this vpn from being saved:"
7 | ul
8 | - @group.errors.full_messages.each do |message|
9 | li = message
10 |
11 | hr
12 | .mb-3
13 | label for="name"
14 | | Name
15 | = f.text_field :name, required: true, class: "form-control", placeholder: "Group Name"
16 | .invalid-feedback
17 | | Please enter a name
18 |
19 | .mb-4
20 | = f.submit "Add Group", class: "btn btn-primary pull-right"
21 |
22 |
--------------------------------------------------------------------------------
/app/views/home/index.html.slim:
--------------------------------------------------------------------------------
1 | .form-signin
2 | .row
3 | .col
4 | h1 Gate-SSO
5 | br
6 | .row
7 | .col
8 | h3 Single Sign-On
9 | br
10 | br
11 | br
12 | br
13 | - case ENV['SIGN_IN_TYPE']
14 | - when 'form'
15 | = form_tag user_sign_in_path, method: :post do
16 | .row
17 | .col-sm-10.offset-sm-1
18 | = text_field_tag :name, '', class: 'form-control', placeholder: 'Name', required: true
19 | = text_field_tag :email, '', class: 'form-control', placeholder: 'Email', required: true, type: 'email'
20 | = submit_tag 'Sign in', class: 'form-control btn-md btn-primary'
21 | - else
22 | .row
23 | .col
24 | .col
25 | a.btn.btn-block.btn-social.btn-google href="#{url_for user_google_oauth2_omniauth_authorize_path}"
26 | span.fa.fa-google
27 | | Sign in with Google
28 | .col
29 |
30 |
--------------------------------------------------------------------------------
/app/views/host_machines/index.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-6.col-md-offset-2
2 | = form_tag host_machines_path, method: 'get', class: "p-2" do
3 | .input-group
4 | = text_field_tag :host_machine_search, params[:host_machine_search], class: "form-control" , autofocus: true, placeholder: "Search host..."
5 | .input-group-append
6 | = submit_tag "Search", class: "button btn btn-secondary", name: nil
7 |
8 |
9 |
10 |
11 | .container-fluid.col-md-6.col-md-offset-2
12 | - if @host_machines.count > 0
13 | .table-responsive
14 | table.table.table-striped
15 | thead
16 | tr
17 | th Name
18 | tbody
19 | - @host_machines.each do |host_machine|
20 | tr
21 | td
22 | = link_to "#{host_machine.name}", host_machine
23 | br
24 |
25 | javascript:
26 | $("#hostmachine-index").addClass("active");
27 |
--------------------------------------------------------------------------------
/app/views/host_machines/new.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-4.col-md-offset-4
2 | = form_tag host_machines_path, method: 'post' do
3 | .input-group
4 | = text_field_tag "host_machine[name]", "", class: "form-control", autofocus: true
5 | .input-group
6 | = submit_tag "Add Host machine", class: "form-control btn btn-sm btn-primary", name: nil
7 |
8 |
--------------------------------------------------------------------------------
/app/views/host_machines/show.html.slim:
--------------------------------------------------------------------------------
1 | .container.col-md-8
2 | h5.mb-3 Host Details
3 | hr
4 | .row
5 | .col
6 | = @host_machine.name
7 | - if current_user.admin?
8 | .card
9 | .card-body
10 | h6.card-title Configurations
11 | hr
12 | = form_tag "/host_machines/#{@host_machine.id}", method: 'put' do
13 | .row
14 | .col
15 | .custom-control.custom-checkbox
16 | = check_box "host_machine", "default_admins", class: "custom-control-input", id: "admin-checkbox"
17 | label.custom-control-label for="admin-checkbox" Default Admins?
18 | .col
19 | = submit_tag "Update", class: "form-control btn-md btn-primary"
20 | br
21 |
22 | .card
23 | .card-body
24 | .table-responsive
25 | table.table.table-striped
26 | thead
27 | tr
28 | th Group Name
29 | th
30 | tbody
31 | - @host_machine.groups.each do |group|
32 | tr
33 | td
34 | = link_to "#{group.name}", group_path(group)
35 | td
36 | = link_to "Delete", [@machine, group], method: :delete, data: {confirm: 'Are you sure to remove this machine from the group??'} if current_user.admin?
37 | br
38 | = "*This host does not have any group" if @host_machine.groups.count == 0
39 | br
40 | hr
41 | - if current_user.admin?
42 | = form_tag add_group_to_machine_path, method: :post do
43 | .row
44 | .col
45 | | Assign group
46 | .col
47 | .col
48 | = text_field_tag "group_id", "", class: "form-control"
49 | .col
50 | = submit_tag "Add group", class: "form-control btn-md btn-primary", disabled: true
51 |
52 |
--------------------------------------------------------------------------------
/app/views/layouts/home.html.slim:
--------------------------------------------------------------------------------
1 | doctype html
2 | html lang="en"
3 | head
4 | link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'
5 | meta charset="utf-8"
6 | meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"
7 | meta name="viewport" content="width=device-width, initial-scale=1.0"
8 | title= content_for?(:title) ? yield(:title) : "Gate"
9 | = csrf_meta_tags
10 | = stylesheet_link_tag "application", :media => "all"
11 | = favicon_link_tag 'apple-touch-icon-144x144-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '144x144'
12 | = favicon_link_tag 'apple-touch-icon-72x72-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png', :sizes => '72x72'
13 | = favicon_link_tag 'apple-touch-icon-precomposed.png', :rel => 'apple-touch-icon-precomposed', :type => 'image/png'
14 | = favicon_link_tag 'favicon.ico', :rel => 'shortcut icon'
15 | = javascript_include_tag "application"
16 | /! Le HTML5 shim, for IE6-8 support of HTML elements
17 | /[if lt IE 9]
18 | = javascript_include_tag "//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js"
19 |
20 |
21 | body.home
22 | = yield
23 |
--------------------------------------------------------------------------------
/app/views/layouts/profile.html.slim.disabled:
--------------------------------------------------------------------------------
1 | doctype html
2 | html lang="en"
3 | head
4 | meta charset="utf-8"
5 | meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"
6 | meta name="viewport" content="width=device-width, initial-scale=1.0"
7 | title= content_for?(:title) ? yield(:title) : "Gate"
8 | = csrf_meta_tags
9 | = stylesheet_link_tag "application", :media => "all"
10 | = stylesheet_link_tag 'profile'
11 | = stylesheet_link_tag "general", :media => "all"
12 | = javascript_include_tag "application"
13 | /! Le HTML5 shim, for IE6-8 support of HTML elements
14 | /[if lt IE 9]
15 | = javascript_include_tag "//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js"
16 |
17 | body.profile_page
18 | .container.container-profile
19 | .header.clearfix
20 | nav
21 | ul.nav.nav-pills.pull-right
22 | li role="presentation"
23 | = link_to "Administration", admin_path if current_user.admin?
24 | li role="presentation"
25 | = link_to current_user.name, user_path(current_user.id)
26 | li.active role="presentation"
27 | = link_to "Sign out", users_sign_out_path,:method => :delete
28 | h3.text-muted Gate - Single Sign On
29 | = yield
30 |
31 | footer.footer
32 | p © 2015 Gate-SSO
33 |
--------------------------------------------------------------------------------
/app/views/nss/add_host.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.success true
2 | json.access_key host.access_key
3 | json.host host.name
4 | json.groups host.groups.map(&:name)
5 |
--------------------------------------------------------------------------------
/app/views/organisations/_form.html.slim:
--------------------------------------------------------------------------------
1 | - if flash.key?(:errors)
2 | .alert.alert-danger#organisation_form_errors
3 | b Issue creating application
4 | br
5 | - flash[:errors].each do |msg|
6 | = "- #{msg}"
7 | br
8 | .form-group
9 | = f.label :name
10 | = f.text_field :name, class: 'form-control'
11 | .form-group
12 | = f.label :website
13 | = f.text_field :website, class: 'form-control'
14 | .form-group
15 | = f.label :domain
16 | = f.text_field :domain, class: 'form-control'
17 | .form-group
18 | = f.label :country
19 | = f.collection_select :country, Country.all.sort_by(&:name), :gec, :name, {}, class: 'form-control'
20 | .form-group
21 | = f.label :state
22 | = f.text_field :state, class: 'form-control'
23 | .form-group
24 | = f.label :address
25 | = f.text_field :address, class: 'form-control'
26 | .form-group
27 | = f.label :admin_email_address
28 | = f.text_field :admin_email_address, class: 'form-control'
29 | .form-group
30 | = f.label :slug
31 | = f.text_field :slug, class: 'form-control'
32 | .form-group
33 | = f.label :unit_name
34 | = f.text_field :unit_name, class: 'form-control'
35 |
--------------------------------------------------------------------------------
/app/views/organisations/config_saml_app.html.slim:
--------------------------------------------------------------------------------
1 | .container.col-md-8
2 | .row.mb-3.mt-2
3 | .col-md-12
4 | h5 Configure #{app_name.titleize}
5 | .row.mb-3.mt-2
6 | .col-md-12
7 | = render partial: "organisations/saml_apps/#{app_name}", locals: {org: org, app_name: app_name, saml_config: saml_config, users: users}
8 |
--------------------------------------------------------------------------------
/app/views/organisations/index.html.slim:
--------------------------------------------------------------------------------
1 | .container.col-md-8
2 | .row.mb-3.mt-2
3 | .col-md-8
4 | h5 Organisations
5 | .col-md-4.text-right
6 | = link_to "New Organisation", new_organisation_path, class: "btn btn-primary", id: 'new_organisation_btn'
7 | - if flash.key?(:success)
8 | .alert.alert-success#organisation_form_success
9 | = flash[:success]
10 | - if flash.key?(:errors)
11 | .alert.alert-danger#organisation_form_errors
12 | = flash[:errors]
13 | #organisation_list.table-responsive
14 | table.table.table-striped
15 | thead
16 | tr
17 | th Name
18 | th URL
19 | th Email Domain
20 | th Actions
21 | tbody
22 | - if org_list.present?
23 | - org_list.each do |org|
24 | tr
25 | td = link_to org.name, organisation_path(org)
26 | td = link_to org.website, org.website
27 | td = org.domain
28 | td
29 | - if org.saml_setup?
30 | .dropdown.position-relative#configureAppDropDownMenuContainer
31 | button.btn.btn-primary.btn-sm.dropdown-toggle type="button" id="configureAppDropDownMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-boundary="configureAppDropDownMenuContainer"
32 | = "Configure App"
33 | .dropdown-menu aria-labelledby="configureAppDropDownMenu"
34 | = link_to "Datadog", organisation_config_saml_app_path(organisation_id: org.id, app_name: 'datadog'), class: 'dropdown-item'
35 | - else
36 | = link_to "Setup SAML", organisation_setup_saml_path(org)
37 | - else
38 | td.text-center colspan='3'
39 | p There are no organisations yet, why don't you create an organisation
40 |
--------------------------------------------------------------------------------
/app/views/organisations/new.html.slim:
--------------------------------------------------------------------------------
1 | .container.col-md-8
2 | .row.mb-3.mt-2
3 | .col-md-12
4 | h5 Create Organisation
5 | hr
6 | = form_for(org) do |f|
7 | = render partial: 'form', locals: {f: f}
8 | = f.submit 'Create Organisation', class: 'btn btn-primary mb-2'
9 |
--------------------------------------------------------------------------------
/app/views/organisations/show.html.slim:
--------------------------------------------------------------------------------
1 | .container.col-md-8
2 | .row.mb-3.mt-2
3 | .col-md-12
4 | h5 Update Organisation
5 | hr
6 | = form_for(org) do |f|
7 | = render partial: 'form', locals: {f: f}
8 | = f.submit 'Update Organisation', class: 'btn btn-primary mb-2'
9 |
--------------------------------------------------------------------------------
/app/views/profile/_group_search.html.slim:
--------------------------------------------------------------------------------
1 | .container.container-profile
2 | = form_tag profile_group_admin_path, method: 'get' do
3 | .row
4 | .col-md-8
5 | = text_field_tag :group_search, params[:group_search], class: "form-control" , autofocus: true
6 | .col-md-4
7 | = submit_tag "Search groups", class: "form-control btn btn-sm btn-primary", name: nil
8 |
9 | hr
10 |
11 |
--------------------------------------------------------------------------------
/app/views/profile/_user_search.html.slim:
--------------------------------------------------------------------------------
1 | .container.container-profile
2 | = form_tag profile_user_admin_path, method: 'get' do
3 | .row
4 | .col-md-8
5 | = text_field_tag :user_search, params[:user_search], class: "form-control" , autofocus: true
6 | .col-md-4
7 | = submit_tag "Search Users", class: "form-control btn btn-sm btn-primary", name: nil
8 |
9 | hr
10 |
--------------------------------------------------------------------------------
/app/views/profile/group_admin.html.slim:
--------------------------------------------------------------------------------
1 | = render partial: "group_search"
2 |
--------------------------------------------------------------------------------
/app/views/profile/list.html.slim:
--------------------------------------------------------------------------------
1 | = render partial: "user_search"
2 | - if @users.count > 0
3 | .table-responsive
4 | table.table.table-striped
5 | thead
6 | tr
7 | th Name
8 | th Email
9 | th Is Active?
10 | th Is Admin?
11 | tbody
12 | - @users.each do |user|
13 | tr
14 | td
15 | = link_to "#{user.name}", user_path(user)
16 | td
17 | = "#{user.email}"
18 | td
19 | = "#{user.active.to_s.camelcase}"
20 | td
21 | = "#{user.admin.to_s.camelcase}"
22 |
--------------------------------------------------------------------------------
/app/views/profile/public_key.html.slim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/app/views/profile/public_key.html.slim
--------------------------------------------------------------------------------
/app/views/profile/user_admin.html.slim:
--------------------------------------------------------------------------------
1 | = render partial: "user_search"
2 |
--------------------------------------------------------------------------------
/app/views/users/_search.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-4.col-md-offset-4
2 | = form_tag users_path, method: 'get', class: "p-2" do
3 | .input-group
4 | = text_field_tag :user_search, params[:user_search], class: "form-control" , autofocus: true, placeholder: "Search user name..."
5 | .input-group-append
6 | = submit_tag "Search", class: "button btn btn-secondary", name: nil
7 |
8 |
--------------------------------------------------------------------------------
/app/views/users/index.html.slim:
--------------------------------------------------------------------------------
1 | = render partial: "search"
2 | - if @users.count > 0
3 | .table-responsive
4 | table.table.table-striped
5 | thead
6 | tr
7 | th Name
8 | th Email
9 | th Is Active?
10 | th Is Admin?
11 | tbody
12 | - @users.each do |user|
13 | tr
14 | td
15 | = link_to "#{user.name}", user_path(user)
16 | td
17 | = "#{user.email}"
18 | td
19 | = "#{user.active.to_s.camelcase}"
20 | td
21 | = "#{user.admin.to_s.camelcase}"
22 |
23 | javascript:
24 | $("#user-index").addClass("active");
25 |
--------------------------------------------------------------------------------
/app/views/users/new.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Create User
5 |
6 | <%= form_for(User.new) do |f| %>
7 | <% if flash.key?(:errors) %>
8 |
9 | Issue Creating User
10 | <%= flash[:errors].map { |msg| "- #{msg}".html_safe }.join("
").html_safe %>
11 |
12 | <% end %>
13 |
14 | <%= f.label :first_name %>
15 | <%= f.text_field :first_name, class: 'form-control' %>
16 |
17 |
18 | <%= f.label :last_name %>
19 | <%= f.text_field :last_name, class: 'form-control' %>
20 |
21 |
22 | <%= f.label :mobile %>
23 | <%= f.text_field :mobile, class: 'form-control' %>
24 |
25 |
26 | <%= f.label :alternate_email %>
27 | <%= f.text_field :alternate_email, class: 'form-control' %>
28 |
29 |
30 | <%= f.label :user_role %>
31 | <%= f.select :user_role, add_placeholder_to_list(roles, "Select A Role"), {}, class: 'form-control' %>
32 |
33 |
34 | <%= label_tag :domain %>
35 | <%= select_tag :user_domain, options_for_select(add_placeholder_to_list(domains, "Select A Domain", string_convert: '')), class: 'form-control' %>
36 |
37 | <%= f.submit 'Create User', class: 'btn btn-primary mb-2' %>
38 | <% end %>
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/views/vpns/_form.html.slim:
--------------------------------------------------------------------------------
1 | = form_for @vpn, :class => 'form-horizontal' do |f|
2 | - if @vpn.errors.any?
3 | #error_explanation
4 | h2 = "#{pluralize(@vpn.errors.count, "error")} prohibited this vpn from being saved:"
5 | ul
6 | - @vpn.errors.full_messages.each do |message|
7 | li = message
8 |
9 | hr
10 | .mb-3
11 | label for="name"
12 | | Name
13 | = f.text_field :name, required: true, class: "form-control", placeholder: "VPN Name"
14 | .mb-3
15 | label for="host_name"
16 | | Host name
17 | = f.text_field :host_name, required: true, class: "form-control", placeholder: "Host name"
18 | .invalid-feedback
19 | | Please enter host name.
20 | .mb-3
21 | label for="ip_address"
22 | | IP Address
23 | = f.text_field :ip_address, required: true, class: 'form-control', placeholder: "IP address"
24 | .invalid-feedback
25 | | Please enter IP address.
26 |
27 | .mb-4
28 | = f.submit "Save", class: "btn btn-primary pull-right"
29 |
30 |
--------------------------------------------------------------------------------
/app/views/vpns/edit.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-4.col-md-offset-4
2 | - if notice.present?
3 | .alert.alert-primary role="alert"
4 | #notice
5 | = notice
6 | br
7 | h5 Edit VPN Details
8 | = render "form"
9 |
10 | javascript:
11 | $("#vpn-index").addClass("active");
12 |
13 |
--------------------------------------------------------------------------------
/app/views/vpns/index.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-8.col-md-offset-4
2 | - if notice.present?
3 | .alert.alert-primary role="alert"
4 | #notice
5 | = notice
6 |
7 | - if Vpn.administrator? current_user
8 | h5 Managed VPNs
9 | table.table.responsive
10 | thead
11 | tr
12 | th="Name"
13 | th="Hostname"
14 | th="IP Address"
15 | - Vpn.managed_vpns(current_user).each do |vpn|
16 | tbody
17 | tr
18 | td= link_to vpn.name, vpn
19 | td= vpn.host_name
20 | td= vpn.ip_address
21 |
22 | h5
23 | b Listing VPNs
24 | table.table.responsive
25 | thead
26 | tr
27 | th="Name"
28 | th="Hostname"
29 | th="IP Address"
30 | th
31 |
32 | tbody
33 | - @vpns.each do |vpn|
34 | tr
35 | td= link_to vpn.name, vpn
36 | td= vpn.host_name
37 | td= vpn.ip_address
38 | td= link_to "Delete", vpn, method: :delete, data: {confirm: 'Are you sure to remove this vpn from gate?'} if current_user.admin?
39 |
40 | javascript:
41 | $("#vpn-index").addClass("active");
42 |
--------------------------------------------------------------------------------
/app/views/vpns/new.html.slim:
--------------------------------------------------------------------------------
1 | .container-fluid.col-md-4.col-md-offset-4
2 | - if notice.present?
3 | .alert.alert-primary role="alert"
4 | #notice
5 | = notice
6 | br
7 | h5 Add new VPN
8 | = render "form"
9 |
10 | javascript:
11 | $("#vpn-index").addClass("active");
12 |
--------------------------------------------------------------------------------
/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3 | load Gem.bin_path('bundler', 'bundle')
4 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_PATH = File.expand_path("../config/application", __dir__)
3 | require_relative "../config/boot"
4 | require "rails/commands"
5 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require_relative "../config/boot"
3 | require "rake"
4 | Rake.application.run
5 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require "fileutils"
3 |
4 | # path to your application root.
5 | APP_ROOT = File.expand_path("..", __dir__)
6 |
7 | def system!(*args)
8 | system(*args) || abort("\n== Command #{args} failed ==")
9 | end
10 |
11 | FileUtils.chdir APP_ROOT do
12 | # This script is a way to set up or update your development environment automatically.
13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome.
14 | # Add necessary setup steps to this file.
15 |
16 | puts "== Installing dependencies =="
17 | system! "gem install bundler --conservative"
18 | system("bundle check") || system!("bundle install")
19 |
20 | # puts "\n== Copying sample files =="
21 | # unless File.exist?("config/database.yml")
22 | # FileUtils.cp "config/database.yml.sample", "config/database.yml"
23 | # end
24 |
25 | puts "\n== Preparing database =="
26 | system! "bin/rails db:prepare"
27 |
28 | puts "\n== Removing old logs and tempfiles =="
29 | system! "bin/rails log:clear tmp:clear"
30 |
31 | puts "\n== Restarting application server =="
32 | system! "bin/rails restart"
33 | end
34 |
--------------------------------------------------------------------------------
/bin/update:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'pathname'
3 | require 'fileutils'
4 | include FileUtils
5 |
6 | # path to your application root.
7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
8 |
9 | def system!(*args)
10 | system(*args) || abort("\n== Command #{args} failed ==")
11 | end
12 |
13 | chdir APP_ROOT do
14 | # This script is a way to update your development environment automatically.
15 | # Add necessary update steps to this file.
16 |
17 | puts '== Installing dependencies =='
18 | system! 'gem install bundler --conservative'
19 | system('bundle check') || system!('bundle install')
20 |
21 | puts "\n== Updating database =="
22 | system! 'bin/rails db:migrate'
23 |
24 | puts "\n== Removing old logs and tempfiles =="
25 | system! 'bin/rails log:clear tmp:clear'
26 |
27 | puts "\n== Restarting application server =="
28 | system! 'bin/rails restart'
29 | end
30 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require ::File.expand_path('../config/environment', __FILE__)
4 | run Rails.application
5 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative "boot"
2 |
3 | require "rails/all"
4 |
5 | # Require the gems listed in Gemfile, including any gems
6 | # you've limited to :test, :development, or :production.
7 | Bundler.require(*Rails.groups)
8 |
9 | module Gate
10 | class Application < Rails::Application
11 | # Initialize configuration defaults for originally generated Rails version.
12 | config.load_defaults 5.0
13 |
14 | # Configuration for the application, engines, and railties goes here.
15 | #
16 | # These settings can be overridden in specific environments using the files
17 | # in config/environments, which are processed later.
18 | #
19 | # config.time_zone = "Central Time (US & Canada)"
20 | # config.eager_load_paths << Rails.root.join("extras")
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
2 |
3 | require "bundler/setup" # Set up gems listed in the Gemfile.
4 |
--------------------------------------------------------------------------------
/config/cable.yml:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: async
3 |
4 | test:
5 | adapter: async
6 |
7 | production:
8 | adapter: redis
9 | url: redis://localhost:6379/1
10 |
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | default: &default
2 | adapter: mysql2
3 | pool: 5
4 | timeout: 5000
5 | host: <%= ENV['GATE_DB_HOST'] %>
6 | port: <%= ENV['GATE_DB_PORT'] %>
7 | username: <%= ENV['GATE_DB_USER'] %>
8 | password: <%= ENV['GATE_DB_PASSWORD'] %>
9 |
10 |
11 | development:
12 | <<: *default
13 | database: gate_development
14 | host: localhost
15 | post: 3306
16 | username: gate_development
17 | password: password
18 | properties:
19 | useSSL: false
20 |
21 | test:
22 | <<: *default
23 | database: gate_test
24 | host: localhost
25 | post: 3306
26 | username: gate_test
27 | password: password
28 | properties:
29 | useSSL: false
30 |
31 | integration:
32 | <<: *default
33 | database: <%= ENV['GATE_DB_NAME'] %>
34 |
35 | production:
36 | <<: *default
37 | pool: 16
38 | database: <%= ENV['GATE_DB_NAME'] %>
39 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative "application"
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/config/initializers/application_controller_renderer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # ApplicationController.renderer.defaults.merge!(
4 | # http_host: 'example.org',
5 | # https: false
6 | # )
7 |
--------------------------------------------------------------------------------
/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = "1.0"
5 |
6 | # Add additional assets to the asset load path.
7 | # Rails.application.config.assets.paths << Emoji.images_path
8 |
9 | # Precompile additional assets.
10 | # application.js, application.css, and all non-JS/CSS in the app/assets
11 | # folder are already added.
12 | # Rails.application.config.assets.precompile += %w( admin.js admin.css )
13 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/config/initializers/content_security_policy.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Define an application-wide content security policy.
4 | # See the Securing Rails Applications Guide for more information:
5 | # https://guides.rubyonrails.org/security.html#content-security-policy-header
6 |
7 | # Rails.application.configure do
8 | # config.content_security_policy do |policy|
9 | # policy.default_src :self, :https
10 | # policy.font_src :self, :https, :data
11 | # policy.img_src :self, :https, :data
12 | # policy.object_src :none
13 | # policy.script_src :self, :https
14 | # policy.style_src :self, :https
15 | # # Specify URI for violation reports
16 | # # policy.report_uri "/csp-violation-report-endpoint"
17 | # end
18 | #
19 | # # Generate session nonces for permitted importmap and inline scripts
20 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
21 | # config.content_security_policy_nonce_directives = %w(script-src)
22 | #
23 | # # Report violations without enforcing the policy.
24 | # # config.content_security_policy_report_only = true
25 | # end
26 |
--------------------------------------------------------------------------------
/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Specify a serializer for the signed and encrypted cookie jars.
4 | # Valid options are :json, :marshal, and :hybrid.
5 | Rails.application.config.action_dispatch.cookies_serializer = :json
6 |
--------------------------------------------------------------------------------
/config/initializers/dotenv.rb:
--------------------------------------------------------------------------------
1 | begin
2 | Dotenv.require_keys('GATE_DB_HOST',
3 | 'GATE_DB_PORT',
4 | 'GATE_DB_USER',
5 | 'GATE_DB_PASSWORD',
6 | 'CACHE_HOST',
7 | 'CACHE_PORT',
8 | 'GATE_HOSTED_DOMAINS',
9 | 'GATE_HOSTED_DOMAIN')
10 | rescue => exception
11 | puts exception.to_s
12 | exit(-1)
13 | end
14 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure parameters to be filtered from the log file. Use this to limit dissemination of
4 | # sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
5 | # notations and behaviors.
6 | Rails.application.config.filter_parameters += [
7 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
8 | ]
9 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, "\\1en"
8 | # inflect.singular /^(ox)en/i, "\\1"
9 | # inflect.irregular "person", "people"
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym "RESTful"
16 | # end
17 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/config/initializers/new_framework_defaults.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 | #
3 | # This file contains migration options to ease your Rails 5.0 upgrade.
4 | #
5 | # Once upgraded flip defaults one by one to migrate to the new default.
6 | #
7 | # Read the Rails 5.0 release notes for more info on each option.
8 |
9 | # Enable per-form CSRF tokens. Previous versions had false.
10 | #Rails.application.config.action_controller.per_form_csrf_tokens = false
11 |
12 | # Enable origin-checking CSRF mitigation. Previous versions had false.
13 | #Rails.application.config.action_controller.forgery_protection_origin_check = false
14 |
15 | # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`.
16 | # Previous versions had false.
17 | #ActiveSupport.to_time_preserves_timezone = false
18 |
19 | # Require `belongs_to` associations by default. Previous versions had false.
20 | #Rails.application.config.active_record.belongs_to_required_by_default = false
21 |
22 |
--------------------------------------------------------------------------------
/config/initializers/permissions_policy.rb:
--------------------------------------------------------------------------------
1 | # Define an application-wide HTTP permissions policy. For further
2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy
3 | #
4 | # Rails.application.config.permissions_policy do |f|
5 | # f.camera :none
6 | # f.gyroscope :none
7 | # f.microphone :none
8 | # f.usb :none
9 | # f.fullscreen :self
10 | # f.payment :self, "https://secure.example.com"
11 | # end
12 |
--------------------------------------------------------------------------------
/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Rails.application.config.session_store :active_record_store, key: '_gate_session'
4 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/config/locales/en.bootstrap.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | breadcrumbs:
6 | application:
7 | root: "Index"
8 | pages:
9 | pages: "Pages"
10 | helpers:
11 | actions: "Actions"
12 | links:
13 | back: "Back"
14 | cancel: "Cancel"
15 | confirm: "Are you sure?"
16 | destroy: "Delete"
17 | new: "New"
18 | edit: "Edit"
19 | titles:
20 | edit: "Edit %{model}"
21 | save: "Save %{model}"
22 | new: "New %{model}"
23 | delete: "Delete %{model}"
24 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # To learn more, please read the Rails Internationalization guide
20 | # available at http://guides.rubyonrails.org/i18n.html.
21 |
22 | en:
23 | hello: "Hello world"
24 |
--------------------------------------------------------------------------------
/config/newrelic.yml:
--------------------------------------------------------------------------------
1 | common: &default_settings
2 | # Required license key associated with your New Relic account.
3 | license_key: <%= ENV['NEWRELIC_LICENSE_KEY'] %>
4 |
5 | # Your application name. Renaming here affects where data displays in New
6 | # Relic. For more details, see https://docs.newrelic.com/docs/apm/new-relic-apm/maintenance/renaming-applications
7 | app_name: <%= ENV['NEWRELIC_APP_NAME'] %>
8 |
9 | # To disable the agent regardless of other settings, uncomment the following:
10 | agent_enabled: <%= ENV['NEWRELIC_AGENT_ENABLED'] == 'true' %>
11 |
12 | # Logging level for log/newrelic_agent.log
13 | log_level: info
14 |
15 |
16 | # Environment-specific settings are in this section.
17 | # RAILS_ENV or RACK_ENV (as appropriate) is used to determine the environment.
18 | # If your application has other named environments, configure them here.
19 | development:
20 | <<: *default_settings
21 | app_name: <%= ENV['NEWRELIC_APP_NAME'] + "(Development)" %>
22 |
23 | test:
24 | <<: *default_settings
25 | # It doesn't make sense to report to New Relic from automated test runs.
26 | monitor_mode: false
27 |
28 | production:
29 | <<: *default_settings
30 |
--------------------------------------------------------------------------------
/config/puma.rb:
--------------------------------------------------------------------------------
1 | # Puma can serve each request in a thread from an internal thread pool.
2 | # The `threads` method setting takes two numbers a minimum and maximum.
3 | # Any libraries that use thread pools should be configured to match
4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
5 | # and maximum, this matches the default thread size of Active Record.
6 | #
7 | threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
8 | threads threads_count, threads_count
9 |
10 | # Specifies the `port` that Puma will listen on to receive requests, default is 3000.
11 | #
12 | port ENV.fetch("PORT") { 3000 }
13 |
14 | # Specifies the `environment` that Puma will run in.
15 | #
16 | environment ENV.fetch("RAILS_ENV") { "development" }
17 |
18 | # Specifies the number of `workers` to boot in clustered mode.
19 | # Workers are forked webserver processes. If using threads and workers together
20 | # the concurrency of the application would be max `threads` * `workers`.
21 | # Workers do not work on JRuby or Windows (both of which do not support
22 | # processes).
23 | #
24 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
25 |
26 | # Use the `preload_app!` method when specifying a `workers` number.
27 | # This directive tells Puma to first boot the application and load code
28 | # before forking the application. This takes advantage of Copy On Write
29 | # process behavior so workers use less memory. If you use this option
30 | # you need to make sure to reconnect any threads in the `on_worker_boot`
31 | # block.
32 | #
33 | # preload_app!
34 |
35 | # The code in the `on_worker_boot` will be called if you are using
36 | # clustered mode by specifying a number of `workers`. After each worker
37 | # process is booted this block will be run, if you are using `preload_app!`
38 | # option you will want to use this block to reconnect to any threads
39 | # or connections that may have been created at application boot, Ruby
40 | # cannot share connections between processes.
41 | #
42 | # on_worker_boot do
43 | # ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
44 | # end
45 |
46 | # Allow puma to be restarted by `rails restart` command.
47 | plugin :tmp_restart
48 |
--------------------------------------------------------------------------------
/config/redis.yml:
--------------------------------------------------------------------------------
1 | default: &default
2 | host: <%= ENV['CACHE_HOST'] %>
3 | port: <%= ENV['CACHE_PORT'] %>
4 | limit: 20
5 |
6 | development:
7 | <<: *default
8 |
9 | test:
10 | <<: *default
11 |
12 | integration:
13 | <<: *default
14 |
15 | production:
16 | <<: *default
17 |
--------------------------------------------------------------------------------
/config/schedule.rb:
--------------------------------------------------------------------------------
1 | # Use this file to easily define all of your cron jobs.
2 | #
3 | # It's helpful, but not entirely necessary to understand cron before proceeding.
4 | # http://en.wikipedia.org/wiki/Cron
5 |
6 | # Example:
7 | #
8 | # set :output, "/path/to/my/cron_log.log"
9 | #
10 | # every 2.hours do
11 | # command "/usr/bin/some_great_command"
12 | # runner "MyModel.some_method"
13 | # rake "some:great:rake:task"
14 | # end
15 | #
16 | # every 4.days do
17 | # runner "AnotherModel.prune_old_records"
18 | # end
19 |
20 | # Learn more: http://github.com/javan/whenever
21 |
22 | every 1.day, at: '2:00 am' do
23 | rake 'users:purge_inactive'
24 | rake 'users:revoke_expired_membership'
25 | end
26 |
--------------------------------------------------------------------------------
/config/secrets.yml:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key is used for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 |
6 | # Make sure the secret is at least 30 characters and all random,
7 | # no regular words or you'll be exposed to dictionary attacks.
8 | # You can use `rails secret` to generate a secure secret key.
9 |
10 | # Make sure the secrets in this file are kept private
11 | # if you're sharing your code publicly.
12 |
13 | development:
14 | secret_key_base: 6a4735f30c7ab8c09019b80cbfd60ba2ead1d1c6b2c60632522602f002460d4590741f9e6713b89e67fd298bd155ff4f5d2f010a09c19388b0a209bb4841a2f8
15 |
16 | test:
17 | secret_key_base: b575eb4f653d58f0b666df115bc91026211573c0224a516e0e20d8b2817d268df6183dd4a028a38780c7b5846e255af900de9319e395cc3e004a387fadb99555
18 |
19 | integration:
20 | secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
21 | secret_api_key: <%= ENV['SECRET_API_KEY'] %>
22 |
23 | # Do not keep production secrets in the repository,
24 | # instead read values from the environment.
25 | production:
26 | secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
27 | secret_api_key: <%= ENV['SECRET_API_KEY'] %>
28 |
--------------------------------------------------------------------------------
/config/spring.rb:
--------------------------------------------------------------------------------
1 | %w(
2 | .ruby-version
3 | .rbenv-vars
4 | tmp/restart.txt
5 | tmp/caching-dev.txt
6 | ).each { |path| Spring.watch(path) }
7 |
--------------------------------------------------------------------------------
/config/storage.yml:
--------------------------------------------------------------------------------
1 | test:
2 | service: Disk
3 | root: <%= Rails.root.join("tmp/storage") %>
4 |
5 | local:
6 | service: Disk
7 | root: <%= Rails.root.join("storage") %>
8 |
9 | # Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
10 | # amazon:
11 | # service: S3
12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
14 | # region: us-east-1
15 | # bucket: your_own_bucket-<%= Rails.env %>
16 |
17 | # Remember not to checkin your GCS keyfile to a repository
18 | # google:
19 | # service: GCS
20 | # project: your_project
21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
22 | # bucket: your_own_bucket-<%= Rails.env %>
23 |
24 | # Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
25 | # microsoft:
26 | # service: AzureStorage
27 | # storage_account_name: your_account_name
28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
29 | # container: your_container_name-<%= Rails.env %>
30 |
31 | # mirror:
32 | # service: Mirror
33 | # primary: local
34 | # mirrors: [ amazon, google, microsoft ]
35 |
--------------------------------------------------------------------------------
/db/migrate/20160419122430_devise_create_users.rb:
--------------------------------------------------------------------------------
1 | class DeviseCreateUsers < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :users do |t|
4 | ## Database authenticatable
5 | t.string :email, null: false, default: ""
6 | t.string :encrypted_password, null: false, default: ""
7 |
8 | ## Recoverable
9 | t.string :reset_password_token
10 | t.datetime :reset_password_sent_at
11 |
12 | ## Rememberable
13 | t.datetime :remember_created_at
14 |
15 | ## Trackable
16 | t.integer :sign_in_count, default: 0, null: false
17 | t.datetime :current_sign_in_at
18 | t.datetime :last_sign_in_at
19 | t.string :current_sign_in_ip
20 | t.string :last_sign_in_ip
21 |
22 | ## Confirmable
23 | # t.string :confirmation_token
24 | # t.datetime :confirmed_at
25 | # t.datetime :confirmation_sent_at
26 | # t.string :unconfirmed_email # Only if using reconfirmable
27 |
28 | ## Lockable
29 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
30 | # t.string :unlock_token # Only if unlock strategy is :email or :both
31 | # t.datetime :locked_at
32 |
33 |
34 | t.timestamps null: false
35 | end
36 |
37 | add_index :users, :email, unique: true
38 | add_index :users, :reset_password_token, unique: true
39 | # add_index :users, :confirmation_token, unique: true
40 | # add_index :users, :unlock_token, unique: true
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/db/migrate/20160419132647_add_provider_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddProviderToUsers < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :provider, :string
4 | add_column :users, :uid, :string
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20160419144739_add_name_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddNameToUsers < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :name, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160427123146_add_auth_key_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddAuthKeyToUser < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :auth_key, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160427123233_add_provisioning_uri_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddProvisioningUriToUser < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :provisioning_uri, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160519042340_add_active_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddActiveToUsers < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :active, :boolean
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160519064340_add_default_value_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddDefaultValueToUsers < ActiveRecord::Migration[5.0]
2 | def change
3 | change_column :users, :active, :boolean, default: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160615044834_create_hosts.rb:
--------------------------------------------------------------------------------
1 | class CreateHosts < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :hosts do |t|
4 | t.string :host_pattern
5 |
6 | t.timestamps null: false
7 | end
8 | add_index :hosts, :host_pattern
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20160615045052_add_admin_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddAdminToUser < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :admin, :boolean, default: false
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160615112805_add_user_to_host.rb:
--------------------------------------------------------------------------------
1 | class AddUserToHost < ActiveRecord::Migration[5.0]
2 | def change
3 | add_reference :hosts, :user, index: true, foreign_key: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160628140022_add_deleted_at_to_host.rb:
--------------------------------------------------------------------------------
1 | class AddDeletedAtToHost < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :hosts, :deleted_at, :datetime
4 | add_index :hosts, :deleted_at
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20160628140440_add_deleted_by_to_host.rb:
--------------------------------------------------------------------------------
1 | class AddDeletedByToHost < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :hosts, :deleted_by, :integer
4 | add_index :hosts, :deleted_by
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20160629043358_add_homedir_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddHomedirToUser < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :home_dir, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160629043415_add_shell_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddShellToUser < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :shell, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160629075435_create_groups.rb:
--------------------------------------------------------------------------------
1 | class CreateGroups < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :groups do |t|
4 | t.string :name
5 | t.integer :gid
6 |
7 | t.timestamps null: false
8 | end
9 | add_index :groups, :name
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20160701090045_create_group_associations.rb:
--------------------------------------------------------------------------------
1 | class CreateGroupAssociations < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :group_associations do |t|
4 | t.references :user
5 | t.references :group
6 |
7 | t.timestamps null: false
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20160701112600_add_deleted_properties_to_group.rb:
--------------------------------------------------------------------------------
1 | class AddDeletedPropertiesToGroup < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :groups, :deleted_by, :integer
4 | add_column :groups, :deleted_at, :datetime
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20160707115313_create_access_tokens.rb:
--------------------------------------------------------------------------------
1 | class CreateAccessTokens < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :access_tokens do |t|
4 | t.string :token
5 |
6 | t.timestamps null: false
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20160714115228_add_public_key_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddPublicKeyToUser < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :public_key, :text
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160908081651_create_host_machines.rb:
--------------------------------------------------------------------------------
1 | class CreateHostMachines < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :host_machines do |t|
4 | t.string :name
5 |
6 | t.timestamps null: false
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20161003145832_create_host_access_groups.rb:
--------------------------------------------------------------------------------
1 | class CreateHostAccessGroups < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :host_access_groups do |t|
4 | t.references :host_machine
5 | t.references :group
6 |
7 | t.timestamps null: false
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20170803140620_add_user_login_id_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddUserLoginIdToUser < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :user_login_id, :string
4 | add_index :users, :user_login_id
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20171013115441_create_versions.rb:
--------------------------------------------------------------------------------
1 | # This migration creates the `versions` table, the only schema PT requires.
2 | # All other migrations PT provides are optional.
3 | class CreateVersions < ActiveRecord::Migration[5.0]
4 |
5 | # The largest text column available in all supported RDBMS is
6 | # 1024^3 - 1 bytes, roughly one gibibyte. We specify a size
7 | # so that MySQL will use `longtext` instead of `text`. Otherwise,
8 | # when serializing very large objects, `text` might not be big enough.
9 | TEXT_BYTES = 1_073_741_823
10 |
11 | def change
12 | #create_table :versions, { options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci" } do |t|
13 | create_table :versions do |t|
14 | t.string :item_type, {:null=>false, :limit=>191}
15 | t.integer :item_id, null: false
16 | t.string :event, null: false
17 | t.string :whodunnit
18 | t.text :object, limit: TEXT_BYTES
19 | t.text :object_changes # Optional column-level changes
20 |
21 | # Known issue in MySQL: fractional second precision
22 | # -------------------------------------------------
23 | #
24 | # MySQL timestamp columns do not support fractional seconds unless
25 | # defined with "fractional seconds precision". MySQL users should manually
26 | # add fractional seconds precision to this migration, specifically, to
27 | # the `created_at` column.
28 | # (https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html)
29 | #
30 | # MySQL users should also upgrade to rails 4.2, which is the first
31 | # version of ActiveRecord with support for fractional seconds in MySQL.
32 | # (https://github.com/rails/rails/pull/14359)
33 | #
34 | t.datetime :created_at
35 | end
36 | add_index :versions, %i(item_type item_id)
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/db/migrate/20171016064705_remove_index_group_name.rb:
--------------------------------------------------------------------------------
1 | class RemoveIndexGroupName < ActiveRecord::Migration[5.0]
2 | def change
3 | remove_index :groups, [:name]
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20171016071526_add_unique_index_on_groups_name.rb:
--------------------------------------------------------------------------------
1 | class AddUniqueIndexOnGroupsName < ActiveRecord::Migration[5.0]
2 | def change
3 | add_index :groups, :name, unique: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20171031060034_create_group_admin.rb:
--------------------------------------------------------------------------------
1 | class CreateGroupAdmin < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :group_admins do |t|
4 | t.integer :group_id
5 | t.integer :user_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20171031060217_add_foreign_key_ref_on_group_admin.rb:
--------------------------------------------------------------------------------
1 | class AddForeignKeyRefOnGroupAdmin < ActiveRecord::Migration[5.0]
2 | def change
3 | add_foreign_key :group_admins, :groups
4 | add_foreign_key :group_admins, :users
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20171031100758_create_vpns.rb:
--------------------------------------------------------------------------------
1 | class CreateVpns < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :vpns do |t|
4 | t.string :name
5 | t.string :host_name
6 | t.string :url
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20171031101026_create_vpn_group_association.rb:
--------------------------------------------------------------------------------
1 | class CreateVpnGroupAssociation < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :vpn_group_associations do |t|
4 | t.integer :group_id
5 | t.integer :vpn_id
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20171031103518_add_foreign_key_ref_on_vpn_group_association.rb:
--------------------------------------------------------------------------------
1 | class AddForeignKeyRefOnVpnGroupAssociation < ActiveRecord::Migration[5.0]
2 | def change
3 | add_foreign_key :vpn_group_associations, :groups
4 | add_foreign_key :vpn_group_associations, :vpns
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20171031113123_create_vpn_group_user_association.rb:
--------------------------------------------------------------------------------
1 | class CreateVpnGroupUserAssociation < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :vpn_group_user_associations do |t|
4 | t.integer :user_id
5 | t.integer :vpn_id
6 | t.integer :group_id
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20171031121702_add_foreign_key_ref_on_vpn_group_user_association.rb:
--------------------------------------------------------------------------------
1 | class AddForeignKeyRefOnVpnGroupUserAssociation < ActiveRecord::Migration[5.0]
2 | def change
3 | add_foreign_key :vpn_group_user_associations, :users
4 | add_foreign_key :vpn_group_user_associations, :groups
5 | add_foreign_key :vpn_group_user_associations, :vpns
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20171102071909_add_ip_address_to_vpns.rb:
--------------------------------------------------------------------------------
1 | class AddIpAddressToVpns < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :vpns, :ip_address, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20171107114249_remove_url_from_vpns.rb:
--------------------------------------------------------------------------------
1 | class RemoveUrlFromVpns < ActiveRecord::Migration[5.0]
2 | def change
3 | remove_column :vpns, :url, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20171108130234_add_user_id_to_access_token.rb:
--------------------------------------------------------------------------------
1 | class AddUserIdToAccessToken < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :access_tokens, :user_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20171108130353_add_foreign_key_ref_on_access_tokens.rb:
--------------------------------------------------------------------------------
1 | class AddForeignKeyRefOnAccessTokens < ActiveRecord::Migration[5.0]
2 | def change
3 | add_foreign_key "access_tokens", "users"
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20171124090240_add_uuid_to_vpns.rb:
--------------------------------------------------------------------------------
1 | class AddUuidToVpns < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :vpns, :uuid, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20171124114427_create_vpn_domain_name_servers.rb:
--------------------------------------------------------------------------------
1 | class CreateVpnDomainNameServers < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :vpn_domain_name_servers do |t|
4 | t.integer :vpn_id
5 | t.string :server_address
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20171124114830_create_vpn_search_domains.rb:
--------------------------------------------------------------------------------
1 | class CreateVpnSearchDomains < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :vpn_search_domains do |t|
4 | t.integer :vpn_id
5 | t.string :search_domain
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20171124115925_create_vpn_supplemental_match_domains.rb:
--------------------------------------------------------------------------------
1 | class CreateVpnSupplementalMatchDomains < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :vpn_supplemental_match_domains do |t|
4 | t.integer :vpn_id
5 | t.string :supplemental_match_domain
6 |
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20180104081814_add_product_name_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddProductNameToUsers < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :product_name, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180202102206_create_saml_service_providers.rb:
--------------------------------------------------------------------------------
1 | class CreateSamlServiceProviders < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :saml_service_providers do |t|
4 | t.string :name, null: false, unique: true
5 | t.string :sso_url, null: false, unique: true
6 | t.string :metadata_url, null: false, unique: true
7 |
8 | t.timestamps null: false
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20180214050204_add_api_key_to_host_machines.rb:
--------------------------------------------------------------------------------
1 | class AddApiKeyToHostMachines < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :host_machines, :api_key, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180214052451_create_ip_addresses.rb:
--------------------------------------------------------------------------------
1 | class CreateIpAddresses < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :ip_addresses do |t|
4 | t.string :address
5 | t.string :mac_address
6 |
7 | t.timestamps null: false
8 | end
9 | add_index :ip_addresses, :address
10 | add_index :ip_addresses, :mac_address
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20180214052644_add_host_machine_to_ip_address.rb:
--------------------------------------------------------------------------------
1 | class AddHostMachineToIpAddress < ActiveRecord::Migration[5.0]
2 | def change
3 | add_reference :ip_addresses, :host_machine, index: true, foreign_key: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180219150818_add_description_to_group.rb:
--------------------------------------------------------------------------------
1 | class AddDescriptionToGroup < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :groups, :description, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180222135930_add_access_key_to_host_machine.rb:
--------------------------------------------------------------------------------
1 | class AddAccessKeyToHostMachine < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :host_machines, :access_key, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180222140000_add_access_key_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddAccessKeyToUser < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :access_key, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180227051732_create_api_resources.rb:
--------------------------------------------------------------------------------
1 | class CreateApiResources < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :api_resources do |t|
4 | t.string :name
5 | t.string :description
6 | t.string :access_key
7 |
8 | t.timestamps null: false
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20180301010021_add_user_to_api_resources.rb:
--------------------------------------------------------------------------------
1 | class AddUserToApiResources < ActiveRecord::Migration[5.0]
2 | def change
3 | add_reference :api_resources, :user, index: true, foreign_key: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180301010035_add_group_to_api_resources.rb:
--------------------------------------------------------------------------------
1 | class AddGroupToApiResources < ActiveRecord::Migration[5.0]
2 | def change
3 | add_reference :api_resources, :group, index: true, foreign_key: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180306231200_add_deactivated_at_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddDeactivatedAtToUsers < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :users, :deactivated_at, :datetime
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180311082600_rename_access_key_in_api_resources.rb:
--------------------------------------------------------------------------------
1 | class RenameAccessKeyInApiResources < ActiveRecord::Migration[5.0]
2 | def change
3 | rename_column :api_resources, :access_key, :hashed_access_key
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180311161200_rename_token_in_access_tokens.rb:
--------------------------------------------------------------------------------
1 | class RenameTokenInAccessTokens < ActiveRecord::Migration[5.0]
2 | def change
3 | rename_column :access_tokens, :token, :hashed_token
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180318083000_create_indexes_to_speedup_nss_controller.rb:
--------------------------------------------------------------------------------
1 | class CreateIndexesToSpeedupNssController < ActiveRecord::Migration[5.0]
2 | def change
3 | add_index :users, :uid
4 | add_index :access_tokens, :hashed_token
5 | add_index :host_machines, :access_key
6 | add_index :host_access_groups, [:host_machine_id, :group_id]
7 | add_index :group_associations, [:group_id, :user_id]
8 | add_index :groups, :gid
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20180613074108_create_organisations.rb:
--------------------------------------------------------------------------------
1 | class CreateOrganisations < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :organisations do |t|
4 | t.string :name
5 | t.string :url
6 | t.string :email_domain
7 |
8 | t.timestamps null: false
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20180613165050_drop_saml_service_providers.rb:
--------------------------------------------------------------------------------
1 | class DropSamlServiceProviders < ActiveRecord::Migration[5.0]
2 | def change
3 | drop_table :saml_service_providers
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20180723175600_update_organisations_for_saml.rb:
--------------------------------------------------------------------------------
1 | class UpdateOrganisationsForSaml < ActiveRecord::Migration[5.0]
2 | def change
3 | rename_column :organisations, :url, :website
4 | rename_column :organisations, :email_domain, :domain
5 | add_column :organisations, :country, :string
6 | add_column :organisations, :state, :string
7 | add_column :organisations, :address, :string
8 | add_column :organisations, :unit_name, :string
9 | add_column :organisations, :admin_email_address, :string
10 | add_column :organisations, :slug, :string
11 | add_column :organisations, :cert_fingerprint, :string
12 | add_column :organisations, :cert_key, :text
13 | add_column :organisations, :cert_private_key, :text
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20181002023107_add_default_admins_to_host_machines.rb:
--------------------------------------------------------------------------------
1 | class AddDefaultAdminsToHostMachines < ActiveRecord::Migration[5.0]
2 | def change
3 | add_column :host_machines, :default_admins, :boolean, default: true
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20181016093315_create_saml_app_configs.rb:
--------------------------------------------------------------------------------
1 | class CreateSamlAppConfigs < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :saml_app_configs do |t|
4 | t.references :group, foreign_key: true
5 | t.string :sso_url
6 | t.json :config
7 | t.references :organisation, foreign_key: true
8 | t.string :app_name
9 |
10 | t.timestamps
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/db/migrate/20181208184236_add_fields_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddFieldsToUser < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :users, :first_name, :string
4 | add_column :users, :last_name, :string
5 | add_column :users, :user_role, :string
6 | add_column :users, :mobile, :string
7 | add_column :users, :alternate_email, :string
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20190624024930_add_expiration_date_to_group_associations.rb:
--------------------------------------------------------------------------------
1 | class AddExpirationDateToGroupAssociations < ActiveRecord::Migration[5.1]
2 | def change
3 | add_column :group_associations, :expiration_date, :date
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190820070910_create_endpoints.rb:
--------------------------------------------------------------------------------
1 | class CreateEndpoints < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :endpoints do |t|
4 | t.string :path, null: false
5 | t.string :method, null: false
6 |
7 | t.timestamps null: false
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20190820075040_create_group_endpoints.rb:
--------------------------------------------------------------------------------
1 | class CreateGroupEndpoints < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :group_endpoints do |t|
4 | t.integer :group_id
5 | t.bigint :endpoint_id
6 |
7 | t.timestamps null: false
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20190820080624_add_foreign_key_ref_on_group_endpoints.rb:
--------------------------------------------------------------------------------
1 | class AddForeignKeyRefOnGroupEndpoints < ActiveRecord::Migration[5.1]
2 | def change
3 | add_foreign_key :group_endpoints, :groups
4 | add_foreign_key :group_endpoints, :endpoints
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20200113065717_add_sessions_table.rb:
--------------------------------------------------------------------------------
1 | class AddSessionsTable < ActiveRecord::Migration[5.1]
2 | def change
3 | create_table :sessions do |t|
4 | t.string :session_id, :null => false
5 | t.text :data
6 | t.timestamps
7 | end
8 |
9 | add_index :sessions, :session_id, :unique => true
10 | add_index :sessions, :updated_at
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20220926001848_add_service_name_to_active_storage_blobs.active_storage.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from active_storage (originally 20190112182829)
2 | class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0]
3 | def up
4 | return unless table_exists?(:active_storage_blobs)
5 |
6 | unless column_exists?(:active_storage_blobs, :service_name)
7 | add_column :active_storage_blobs, :service_name, :string
8 |
9 | if configured_service = ActiveStorage::Blob.service.name
10 | ActiveStorage::Blob.unscoped.update_all(service_name: configured_service)
11 | end
12 |
13 | change_column :active_storage_blobs, :service_name, :string, null: false
14 | end
15 | end
16 |
17 | def down
18 | return unless table_exists?(:active_storage_blobs)
19 |
20 | remove_column :active_storage_blobs, :service_name
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/db/migrate/20220926001849_create_active_storage_variant_records.active_storage.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from active_storage (originally 20191206030411)
2 | class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0]
3 | def change
4 | return unless table_exists?(:active_storage_blobs)
5 |
6 | # Use Active Record's configured type for primary key
7 | create_table :active_storage_variant_records, id: primary_key_type, if_not_exists: true do |t|
8 | t.belongs_to :blob, null: false, index: false, type: blobs_primary_key_type
9 | t.string :variation_digest, null: false
10 |
11 | t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true
12 | t.foreign_key :active_storage_blobs, column: :blob_id
13 | end
14 | end
15 |
16 | private
17 | def primary_key_type
18 | config = Rails.configuration.generators
19 | config.options[config.orm][:primary_key_type] || :primary_key
20 | end
21 |
22 | def blobs_primary_key_type
23 | pkey_name = connection.primary_key(:active_storage_blobs)
24 | pkey_column = connection.columns(:active_storage_blobs).find { |c| c.name == pkey_name }
25 | pkey_column.bigint? ? :bigint : pkey_column.type
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/db/migrate/20220926001850_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb:
--------------------------------------------------------------------------------
1 | # This migration comes from active_storage (originally 20211119233751)
2 | class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0]
3 | def change
4 | return unless table_exists?(:active_storage_blobs)
5 |
6 | change_column_null(:active_storage_blobs, :checksum, true)
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | #
5 | # this file loads seeds based on environments - so please be aware to run appropriate seed file
6 | #
7 | load(Rails.root.join( 'db', 'seeds', "#{Rails.env.downcase}.rb"))
8 |
--------------------------------------------------------------------------------
/db/seeds/development.rb:
--------------------------------------------------------------------------------
1 | dev_user = User.create_user('dev', 'dev@a.c')
2 | dev_user.generate_two_factor_auth
3 | (1..6).each do |uid|
4 | user = User.create_user("dev#{uid}", "dev#{uid}@a.c")
5 | user.generate_two_factor_auth
6 | end
7 | group = Group.create(name: 'people')
8 | User.all.each do |user|
9 | user.groups << group
10 | user.save!
11 | end
12 | AccessToken.create(token: 'a')
13 |
14 | vpn = Vpn.create(name: 'dev-vpn', host_name: 'dev-vpn.example.com', ip_address: '1.2.3.4', uuid: 'FC29CB92-FC7E-4F0B-B938-7612DFDECC28')
15 | HostMachine.create(name: 'SampleHost1')
16 | HostMachine.create(name: 'SampleHost2')
17 | vsd = VpnSearchDomain.create(search_domain: 'dev-search.vpn.example.com')
18 | vdns = VpnDomainNameServer.create(server_address: '8.8.8.8')
19 | vsmd = VpnSupplementalMatchDomain.create(supplemental_match_domain: 'match.domains')
20 | vpn.vpn_search_domains << vsd
21 | vpn.vpn_domain_name_servers << vdns
22 | vpn.vpn_supplemental_match_domains << vsmd
23 | vpn.save!
24 |
--------------------------------------------------------------------------------
/db/seeds/production.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 | #
9 | group = Group.where(name: "people").first
10 | group = Group.create(name: "people") if group.blank?
11 |
12 | group = Group.where(name: "devops").first
13 | group = Group.create(name: "devops") if group.blank?
14 |
--------------------------------------------------------------------------------
/db/seeds/test.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 | #
9 |
--------------------------------------------------------------------------------
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | gate-sql:
4 | image: mysql:5.7
5 | volumes:
6 | - ${PWD}/data:/var/lib/mysql
7 | environment:
8 | - MYSQL_ALLOW_EMPTY_PASSWORD=true
9 |
10 | gate:
11 | image: gate
12 | ports:
13 | - "3000:3000"
14 | depends_on:
15 | - gate-sql
16 | env_file:
17 | - .env
18 | command: sh ./setup.sh
19 |
--------------------------------------------------------------------------------
/docs/additional_setup.md:
--------------------------------------------------------------------------------
1 | # Additional Setup
2 |
3 | ### Setting-up Public Key Lookup
4 |
5 | * Ensure user has uploaded their public key into gate.
6 | * Add following lines to your sshd_config - It is located at `/etc/ssh/sshd_config` on most linux distros.
7 |
8 | ```
9 | AuthorizedKeysCommand /usr/bin/gate_ssh.sh
10 | AuthorizedKeysCommandUser nobody
11 | ```
12 |
13 | * Add file with following content to `/usr/bin/` with name `gate_ssh.sh` owned by root
14 |
15 | ```
16 | #!/bin/sh
17 | /usr/bin/curl -k --silent "https:///profile/$1/key"
18 | ```
19 |
20 | > **Please Note:** Point URL to Gate server and test by executing `gate_ssh.sh ` to see if this prints the public key.
21 |
--------------------------------------------------------------------------------
/docs/administration.md:
--------------------------------------------------------------------------------
1 | # Administration
2 |
3 | ### Running Administrative Tasks
4 |
5 | You can open rails console and give one user admin privilege by setting up `user.admin = true` in console. Then when you signed-in as that user, Gate will show you its administration UI. You can do the following with Gate admin UI:
6 |
7 | * Enable/disable user account
8 | * Make user administrator
9 | * Control what host user's are allowed to login via host patterns, by default they are allowed everyhost which starts with `s-*` (we use `s-` for staging and `p-` for production)
10 | * Make user part of group, by default they are part of 'people' group.
11 |
12 | > **DNS Alert** Please note that gate rely heavily on DNS and host supplied IP addresses, so it authenticates against host native IP address rather than NAT'd IP address. It does reverse name lookup on supplied IP address, if that fails then it will be looking at matching IP address itself.
13 |
14 | ### Scheduler
15 |
16 | Gate has some tasks that can be scheduled for maintenance purpose. Please see `config/scheduler.rb` to see the list of available tasks.
17 |
18 | You can run `whenever --update-crontab` to update cronjob so that it run these tasks. Gate utilize `whenever` gem for maintaining scheduled tasks, which in turn utilize cronjob as its backend.
19 |
20 | ### Logs
21 |
22 | Logs are stored here:
23 |
24 | * Puma logs
25 | * `shared/log/puma.stdout.log`
26 | * `shared/log/puma.stderr.log`
27 | * App logs
28 | * `log/.log`
29 |
30 | Some errors may be being written directly to stdout/stderr and may not be available in the application log file.
31 |
--------------------------------------------------------------------------------
/docs/dredd_setup.md:
--------------------------------------------------------------------------------
1 | # Dredd Setup
2 |
3 | Dredd is used to run test, to validate the API Blueprint against Backend Implementation.
4 |
5 | ### Install npm
6 |
7 | On Mac OS
8 |
9 | ```
10 | brew install node
11 | ```
12 |
13 | On Linux
14 |
15 | ```
16 | apt-get install npm
17 | ```
18 |
19 | ### Install dredd
20 |
21 | To install dredd globally run
22 | ```
23 | npm install -g dredd
24 | ```
25 |
26 | Before you run the dredd please make sure you've run the `bundler install` and fill the `env` file
27 |
28 | ### Running dredd
29 |
30 | Running without debug
31 | ```
32 | dredd
33 | ```
34 |
35 | Running with debug mode
36 | ```
37 | dredd --loglevel debug
38 | ```
39 |
--------------------------------------------------------------------------------
/docs/newrelic.md:
--------------------------------------------------------------------------------
1 | # Newrelic Integration
2 |
3 | If you want to enable Newrelic monitoring on your Gate deployment, you just need to fill these additional keys on your environment variables:
4 |
5 | ```
6 | NEWRELIC_LICENSE_KEY - Your Newrelic license key
7 | NEWRELIC_APP_NAME - Your application name (identifer) on Newrelic
8 | NEWRELIC_AGENT_ENABLED - Set it true if you want Newrelic agent to runs
9 | ```
10 |
--------------------------------------------------------------------------------
/docs/oauth_setup.md:
--------------------------------------------------------------------------------
1 | # OAuth Setup
2 |
3 | * Ensure that you have a registered account in Google Cloud Platform.
4 | * Enable `plus.googleapis.com` API at the following URL:
5 |
6 | https://console.developers.google.com/apis/api/plus.googleapis.com/overview?project=[YOUR-PROJECT-NAME]
7 | * Create OAuth Client ID credentials at the following URL (with type `Web Application`):
8 |
9 | https://console.developers.google.com/apis/credentials?project=[YOUR-PROJECT-NAME]
10 | * Configure Restrictions (Origins & Redirect URIs). We cannot use localhost in this section, therefore you can specify any arbitrary domain then configure your computer `/etc/hosts` file.
11 |
12 | Example if you are running on `http://example.com:4000`:
13 | * http://example.com:4000
14 | * http://example.com:4000/users/auth/google_oauth2/callback
15 | * Put client_id and client_secret on `GATE_OAUTH_CLIENT_ID` and `GATE_OAUTH_CLIENT_SECRET` respectively
16 | * Update your `GATE_SERVER_URL` to `http://example.com:4000`
17 | * Specify your e-mail domain on `GATE_HOSTED_DOMAIN` and `GATE_HOSTED_DOMAINS`, for instance if your e-mail address is `test123@gmail.com` then the value should be `gmail.com`
18 | * Leave `SIGN_IN_TYPE` empty
19 |
--------------------------------------------------------------------------------
/dredd.yml:
--------------------------------------------------------------------------------
1 | color: true
2 | dry-run: null
3 | hookfiles: 'api_blueprint/hooks/dredd_hooks.rb'
4 | language: ruby
5 | require: null
6 | server: './api_blueprint/bin/dredd_server.sh'
7 | server-wait: 20
8 | init: false
9 | custom: {}
10 | names: false
11 | only: []
12 | reporter: []
13 | output: []
14 | header: []
15 | sorted: false
16 | user: null
17 | inline-errors: false
18 | details: false
19 | method: []
20 | loglevel: warning
21 | path: []
22 | hooks-worker-timeout: 5000
23 | hooks-worker-connect-timeout: 15000
24 | hooks-worker-connect-retry: 500
25 | hooks-worker-after-connect-wait: 100
26 | hooks-worker-term-timeout: 5000
27 | hooks-worker-term-retry: 500
28 | hooks-worker-handler-host: 127.0.0.1
29 | hooks-worker-handler-port: 61321
30 | config: ./dredd.yml
31 | blueprint: 'api_blueprint/*.apib'
32 | endpoint: 'http://localhost:9865'
33 |
--------------------------------------------------------------------------------
/lib/assets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/lib/assets/.keep
--------------------------------------------------------------------------------
/lib/tasks/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/lib/tasks/.keep
--------------------------------------------------------------------------------
/lib/tasks/app.rake:
--------------------------------------------------------------------------------
1 | namespace :app do
2 | desc "Common app related tasks"
3 |
4 | task :init do
5 | cp '.env.example', '.env'
6 | p 'Please read information @ README.md - Setting up Environment Variables'
7 | end
8 |
9 | task :setup do
10 | sh "bundle install"
11 | sh "bundle exec rake db:drop db:create db:migrate"
12 | sh "RAILS_ENV=test bundle exec rake db:migrate"
13 | sh "RAILS_ENV=test bundle exec rspec"
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/tasks/setup.rake:
--------------------------------------------------------------------------------
1 | namespace :setup do
2 | desc "Setup open vpn config"
3 |
4 | task :openvpn => [:key_dir, :certificate_authority] do
5 | end
6 |
7 | task :key_dir do
8 | key_dir = Net::Openvpn::Generators::Keys::Directory.new
9 | key_dir.generate
10 | puts "#{key_dir} successfully generated" if key_dir.exist?
11 | end
12 |
13 | task :certificate_authority do
14 | ca = Net::Openvpn::Generators::Keys::Authority.new
15 | ca.generate
16 | ca.exist?
17 | puts "#{ca} successfully generated" if ca.exist?
18 | end
19 |
20 | task :server do
21 | keys = Net::Openvpn::Generators::Keys::Server.new("swzvpn04")
22 | keys.generate
23 | keys.exist?
24 | keys.valid?
25 | end
26 |
27 | # example rake setup:client['ajey']
28 | task :client , [:name] => :environment do |task, args|
29 | puts "generating key for #{args.name}"
30 | keys = Net::Openvpn::Generators::Keys::Client.new(args.name)
31 | keys.generate
32 | keys.exist?
33 | keys.valid?
34 | puts "key for #{args.name} successfully generated" if keys.valid?
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/lib/tasks/vpn.rake:
--------------------------------------------------------------------------------
1 | namespace :users do
2 |
3 | desc "migrate vpn user from old group to new groups"
4 | task migrate_vpns: :environment do
5 |
6 | vpns = Vpn.all
7 |
8 | vpns.each do |vpn|
9 | admin_groups = vpn.groups
10 | #create a new group for VPN
11 | group = Group.create(name: "#{vpn.name}_access_group", description: "VPN Access group")
12 | #Assign VPN to group
13 | #get all vpn administrators
14 | admins = []
15 | admin_groups.each do |admin_group|
16 | admin_group.group_admins.each do |group_admin|
17 | admins << group_admin.user
18 | end
19 | end
20 |
21 | #add all vpn administrators to new group as admin
22 | admins.each do |user|
23 | group.add_admin user
24 | end
25 | #get all vpn users
26 | #add all vpn users to new group
27 | vpn.users.each do |user|
28 | user.groups << group
29 | end
30 | group.save!
31 |
32 | @vpn.groups << group
33 | end
34 | end
35 | end
36 |
37 |
--------------------------------------------------------------------------------
/lib/vpn/mobileconfig.rb:
--------------------------------------------------------------------------------
1 | require 'erb'
2 | require 'vpn/namespace'
3 | require 'openssl'
4 |
5 | class Mobileconfig
6 | def generate (vpns, user)
7 | mobileconfig_template = File.read("#{Rails.root}/lib/vpn/mobileconfig.erb")
8 |
9 | vpn_hash = []
10 | vpns.each do |vpn|
11 | vpn_hash << {
12 | "payload_identifier" => "#{vpn.host_name.split('.').reverse.join('.')}.conf",
13 | "payload_uuid" => vpn.uuid,
14 | "user_defined_name" => vpn.name,
15 | "ikev2" => {
16 | "remote_address" => vpn.host_name,
17 | "remote_identifier" => vpn.host_name,
18 | "auth_name" => user.email.split('@').first
19 | },
20 | "dns" => {
21 | "server_addresses" => vpn.vpn_domain_name_servers.collect{ |vdns| vdns.server_address },
22 | "search_domains" => vpn.vpn_search_domains.collect{ |vsd| vsd.search_domain },
23 | "supplemental_match_domains" => vpn.vpn_supplemental_match_domains.collect{ |vsmd| vsmd.supplemental_match_domain },
24 | }
25 | }
26 | end
27 |
28 | confighash = {
29 | organization_name: ENV['GATE_ORGANIZATION_NAME'] + ' IKEv2 VPN Configuration',
30 | reverse_vpn_url: ENV['GATE_SERVER_URL'].split('.').reverse.join('.'),
31 | organization_static: ENV['GATE_ORGANIZATION_STATIC'],
32 | payload_content: vpn_hash,
33 | }
34 |
35 | namespace = Namespace.new(confighash)
36 |
37 | mobileconfig_unsigned = ERB.new(mobileconfig_template).result(namespace.get_binding)
38 |
39 | sign_mobileconfig(mobileconfig_unsigned)
40 | end
41 |
42 | private
43 |
44 | def sign_mobileconfig(mobileconfig)
45 | private_key = Base64.decode64(ENV['GATE_VPN_SSL_PVTKEY'])
46 | signing_cert = Base64.decode64(ENV['GATE_VPN_SSL_CERT'])
47 | cross_signed_cert = Base64.decode64(ENV['GATE_VPN_SSL_XSIGNED'])
48 |
49 | key = OpenSSL::PKey::RSA.new private_key
50 | cert = OpenSSL::X509::Certificate.new signing_cert
51 | cross_signed = OpenSSL::X509::Certificate.new cross_signed_cert
52 |
53 | OpenSSL::PKCS7.sign(cert, key, mobileconfig, [cross_signed]).to_der
54 | end
55 | end
56 |
--------------------------------------------------------------------------------
/lib/vpn/namespace.rb:
--------------------------------------------------------------------------------
1 | class Namespace
2 | def initialize(hash)
3 | hash.each do |key, value|
4 | singleton_class.send(:define_method, key) { value }
5 | end
6 | end
7 | def get_binding
8 | binding
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/node_modules/.yarn-integrity:
--------------------------------------------------------------------------------
1 | {
2 | "systemParams": "darwin-arm64-108",
3 | "modulesFolders": [],
4 | "flags": [],
5 | "linkedModules": [],
6 | "topLevelPatterns": [],
7 | "lockfileEntries": {},
8 | "files": [],
9 | "artifacts": {}
10 | }
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The change you wanted was rejected.
62 |
Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/public/favicon.ico
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | User-agent: *
5 | Disallow: /
6 |
--------------------------------------------------------------------------------
/scripts/gen-client-conf:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [[ $# -lt 1 ]]; then
4 | echo "$0 "
5 | exit 1
6 | fi
7 |
8 | cd /etc/openvpn/keys
9 | cp /opt/vpnkeys/$1.tar.gz ./
10 | tar -xf $1.tar.gz
11 | rm $1.ovpn
12 | touch $1.ovpn
13 |
14 | cat > /etc/openvpn/keys/$1.ovpn <> 1194
19 | resolv-retry infinite
20 | nobind
21 | persist-key
22 | persist-tun
23 | ca ca.crt
24 | cert $1.crt
25 | key $1.key
26 | comp-lzo
27 | verb 3
28 | auth-user-pass
29 | auth-nocache
30 | tun-mtu 1400
31 | mssfix 1400
32 |
33 | #add your routes here
34 | route <>
35 | route <>
36 | EOF
37 |
38 | tar zcf $1.tar.gz ca.crt $1.crt $1.key $1.ovpn
39 | chmod 0600 $1.tar.gz
40 |
41 | mkdir -p /opt/vpnkeys/
42 | cp $1.tar.gz /opt/vpnkeys/
43 | rm $1.*
44 |
--------------------------------------------------------------------------------
/scripts/gen-client-keys:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | if [[ $# -lt 1 ]]; then
6 | echo "$0 "
7 | exit 1
8 | fi
9 |
10 | source vars
11 |
12 | touch /etc/openvpn/keys/$1.ovpn
13 |
14 | cat > /etc/openvpn/keys/$1.ovpn <> 1194
19 | resolv-retry infinite
20 | nobind
21 | persist-key
22 | persist-tun
23 | ca ca.crt
24 | cert $1.crt
25 | key $1.key
26 | comp-lzo
27 | verb 3
28 | auth-user-pass
29 | auth-nocache
30 | tun-mtu 1400
31 | mssfix 1400
32 | #Add your routes
33 | route <>
34 | route <>
35 | EOF
36 |
37 | ./pkitool $1
38 | cd /etc/openvpn/keys/ && tar zcf $1.tar.gz ca.crt $1.crt $1.key $1.ovpn
39 | chmod 0600 $1.tar.gz
40 |
41 | mkdir -p /opt/vpnkeys/
42 | cp $1.tar.gz /opt/vpnkeys/
43 | rm $1.*
44 |
--------------------------------------------------------------------------------
/setup.sh:
--------------------------------------------------------------------------------
1 | rake db:setup && rails s
2 |
--------------------------------------------------------------------------------
/spec/controllers/admin_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe AdminController, type: :controller do
4 |
5 | end
6 |
--------------------------------------------------------------------------------
/spec/controllers/api/v1/api_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe ::Api::V1::BaseController, type: :controller do
4 |
5 | controller(::Api::V1::BaseController) do
6 | def index
7 | head :ok
8 | end
9 | end
10 |
11 | describe 'Authentication' do
12 | before(:each) do
13 | @user = build(:user)
14 | @user.access_token = build(:access_token)
15 | @user.save
16 | @token = @user.access_token.token
17 | end
18 | it 'gives 200 when access token is valid' do
19 | get :index, params: { access_token: @token }
20 | expect(response.status).to eq(200)
21 | end
22 |
23 | it 'gives 401 when access token is in valid' do
24 | get :index, params: { access_token: "foo" }
25 | expect(response.status).to eq(401)
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/controllers/api/v1/vpns_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe ::Api::V1::VpnsController, type: :controller do
4 | let(:valid_attributes) {
5 | {name: 'jumbo'}
6 | }
7 |
8 | before(:each) do
9 | @user = build(:user)
10 | @user.access_token = build(:access_token)
11 | @user.save
12 | @token = @user.access_token.token
13 | end
14 |
15 | describe 'Authenticated' do
16 | describe 'Create Vpn' do
17 | context 'with valid_attributes' do
18 | it 'should create vpns' do
19 | post :create, params: {vpn: valid_attributes, access_token: @token}
20 | vpn = Vpn.where(name: valid_attributes[:name]).first
21 | expect(vpn.blank?).to eq(false)
22 | expect(vpn.name).to eq(valid_attributes[:name])
23 | expect(UUID.validate(vpn.uuid)).to eq(true)
24 | end
25 |
26 | it 'should return proper response' do
27 | post :create, params: {vpn: valid_attributes, access_token: @token}
28 | expect(response.status).to eq(200)
29 | vpn = Vpn.where(name: valid_attributes[:name]).first
30 | obj = JSON.parse(response.body)
31 | expect(obj['id']).to eq vpn.id
32 | expect(obj['name']).to eq vpn.name
33 | expect(obj['host_name']).to eq vpn.host_name
34 | expect(obj['ip_address']).to eq vpn.ip_address
35 | end
36 | end
37 | end
38 |
39 | describe 'Assign Group to VPN' do
40 | it 'should replace existing vpn group with new group' do
41 | vpn = create(:vpn)
42 | group_1 = create(:group)
43 | group_2 = create(:group)
44 | vpn.groups << group_1
45 | vpn.groups << group_2
46 | group_3 = create(:group)
47 | post :assign_group, params: {access_token: @token, id: vpn.id, group_id: group_3.id}
48 | expect(vpn.groups.count).to eq 1
49 | expect(vpn.groups.first).to eq group_3
50 | end
51 | end
52 | end
53 |
54 | describe 'Unauthenticated' do
55 | it 'gives 401 when access token is invalid' do
56 | post :create, params: {vpn: valid_attributes, access_token: 'foo'}
57 | expect(response.status).to eq(401)
58 | end
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/spec/controllers/home_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe HomeController, type: :controller do
4 |
5 | end
6 |
--------------------------------------------------------------------------------
/spec/controllers/host_machine_groups_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe HostMachineGroupsController, type: :controller do
4 |
5 | end
6 |
--------------------------------------------------------------------------------
/spec/controllers/omniauth_callbacks_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe Users::OmniauthCallbacksController, type: :controller do
4 |
5 | end
6 |
--------------------------------------------------------------------------------
/spec/controllers/profile_controller_spec.rb:
--------------------------------------------------------------------------------
1 | describe ProfileController, type: :controller do
2 | let!(:admin) { create(:admin_user) }
3 | let(:user) { create(:user, admin: false) }
4 |
5 | describe '#update' do
6 | context 'unauthenticated' do
7 | it 'should return status 302' do
8 | post :update, params: { id: user.id }
9 |
10 | expect(response).to have_http_status(302)
11 | end
12 | end
13 |
14 | context 'authenticated as admin' do
15 | it 'should update user' do
16 | new_user = create(:user, active: true, admin: true)
17 | sign_in admin
18 |
19 | post :update, params: { id: new_user.id, user: { admin: false, active: false } }
20 | new_user.reload
21 |
22 | expect(new_user).to have_attributes(active: false, admin: false)
23 | end
24 |
25 | it 'should revoke admin when deactivate user' do
26 | new_user = create(:user, active: true, admin: true)
27 | sign_in admin
28 |
29 | post :update, params: { id: new_user.id, user: { active: false } }
30 | new_user.reload
31 |
32 | expect(new_user).to have_attributes(active: false, admin: false)
33 | end
34 |
35 | it 'should redirect to user_path after update' do
36 | sign_in admin
37 |
38 | post :update, params: { id: user.id, user: { admin: false, active: false } }
39 |
40 | expect(response).to redirect_to(user_path)
41 | end
42 | end
43 |
44 | context 'authenticated as non admin' do
45 | it 'should not update user' do
46 | new_user = create(:user, active: true, admin: true)
47 | sign_in user
48 |
49 | post :update, params: { id: new_user.id, user: { admin: false, active: false } }
50 | new_user.reload
51 |
52 | expect(new_user).to have_attributes(active: true, admin: true)
53 | end
54 | end
55 | end
56 |
57 | describe '#download_vpn_for_ios_and_mac' do
58 | context "user doesn't have vpn" do
59 | it 'should return status 200' do
60 | sign_in user
61 |
62 | get :download_vpn_for_ios_and_mac
63 |
64 | expect(response).to have_http_status(200)
65 | end
66 | end
67 | end
68 | end
69 |
--------------------------------------------------------------------------------
/spec/controllers/users/auth_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe Users::AuthController, type: :controller do
4 | let(:user) { FactoryBot.create(:user, name: 'foobar', email: 'foobar@foobar.com') }
5 |
6 | context 'sign in' do
7 | before(:each) do
8 | @cached_domain_env = ENV['GATE_HOSTED_DOMAINS']
9 | @cached_sign_in_type = ENV['SIGN_IN_TYPE']
10 | ENV['GATE_HOSTED_DOMAINS'] = 'foobar.com'
11 | ENV['SIGN_IN_TYPE'] = 'form'
12 | end
13 |
14 | after(:each) do
15 | ENV['GATE_HOSTED_DOMAINS'] = @cached_domain_env
16 | ENV['SIGN_IN_TYPE'] = @cached_sign_in_type
17 | end
18 |
19 | it 'should redirect to home when success' do
20 | post :log_in, params: { name: user.name, email: user.email }
21 |
22 | expect(response).to redirect_to(root_path)
23 | end
24 |
25 | it 'should produce error and unauthorized status when email domain is unsupported' do
26 | post :log_in, params: { name: user.name, email: 'foobar@notfoobar.com' }
27 |
28 | expect(response).to have_http_status(401)
29 | expect(response.body).to eq('Your domain is unauthorized')
30 | end
31 |
32 | it 'should generate two factor auth when success' do
33 | post :log_in, params: { name: user.name, email: user.email }
34 |
35 | user.reload
36 | expect(user.auth_key).not_to be_nil
37 | end
38 |
39 | it 'should set user session when success' do
40 | post :log_in, params: { name: user.name, email: user.email }
41 |
42 | expect(subject.current_user).to eq(user)
43 | end
44 |
45 | it 'should redirect to home when sign in type is not form' do
46 | ENV['SIGN_IN_TYPE'] = 'not_form'
47 |
48 | post :log_in, params: { name: user.name, email: user.email }
49 |
50 | expect(response).to redirect_to(root_path)
51 | end
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/spec/factories/access_tokens.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :access_token do
3 | token { SecureRandom.uuid }
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/factories/api_resources.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :api_resource do
3 | sequence(:name, 1000) { |n| "API#{n}" }
4 | description { "MyString" }
5 | access_key { "MyString" }
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/factories/endpoints.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :endpoint do
3 | path { '/' }
4 | add_attribute(:method) { ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].sample }
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/factories/group_associations.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :group_association do
3 | user { "" }
4 | group { "" }
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/factories/groups.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :group do
3 | sequence(:name, 1000) { |n| "People#{n}" }
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/factories/host_access_groups.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :host_access_group do
3 | references { "" }
4 | references { "" }
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/factories/host_machine_groups.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :host_machine_group do
3 | user { nil }
4 | host_machine { nil }
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/factories/host_machines.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :host_machine do
3 | sequence(:name) { |n| "host-#{n}" }
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/factories/ip_addresses.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :ip_address do
3 | address { "MyString" }
4 | mac_address { "MyString" }
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/factories/organisations.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | #country = Country.find_country_by_name(Country.all.map(&:name).sort.sample)
3 | factory :organisation do
4 | sequence(:slug) { |n| "#{Faker::Lorem.word}_#{n}" }
5 | name { Faker::Lorem.word }
6 | website { Faker::Internet.url }
7 | domain { Faker::Internet.email.split('@').last }
8 | country { country.gec }
9 | state { Faker::Address.state }
10 | address { Faker::Lorem.words(number: 3).join(' ') }
11 | unit_name { 'IT' }
12 | admin_email_address { Faker::Internet.email }
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/spec/factories/saml_app_configs.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :saml_app_config do
3 | sso_url { Faker::Internet.url }
4 | group { create(:group, name: "saml_#{Faker::Lorem.word}_datadog_users") }
5 | config { { app_key: Faker::Internet.password(min_length: 8), api_key: Faker::Internet.password(min_length: 8) } }
6 | organisation { build(:organisation) }
7 | app_name { 'datadog' }
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/spec/factories/user_host_access_groups.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :user_host_access_group do
3 | user { nil }
4 | host_access_group { nil }
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/factories/vpns.rb:
--------------------------------------------------------------------------------
1 | FactoryBot.define do
2 | factory :vpn do
3 | sequence(:name) { |n| "VPN#{n}" }
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/features/layout_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'Layout', type: :feature do
3 | let(:user) { create(:user) }
4 | let(:group_admin) { create(:group_admin) }
5 | let(:admin) { create(:admin_user) }
6 | scenario 'Access to user links' do
7 | sign_in(user)
8 | visit profile_path
9 | links = {
10 | 'APIs' => api_resources_path,
11 | 'VPNs' => vpns_path,
12 | 'API' => new_api_resource_path,
13 | }
14 | links.each do |link_text, link_href|
15 | expect(page).to have_xpath(
16 | "//div[@id='main-navigation']//a[@href='#{link_href}' and .='#{link_text}']"
17 | )
18 | end
19 | end
20 | scenario 'Access to group admin links' do
21 | sign_in(group_admin)
22 | visit profile_path
23 | links = {
24 | 'APIs' => api_resources_path,
25 | 'Groups' => groups_path,
26 | 'VPNs' => vpns_path,
27 | 'API' => new_api_resource_path,
28 | }
29 | links.each do |link_text, link_href|
30 | expect(page).to have_xpath(
31 | "//div[@id='main-navigation']//a[@href='#{link_href}' and .='#{link_text}']"
32 | )
33 | end
34 | end
35 | scenario 'Access to admin links' do
36 | sign_in(admin)
37 | visit root_path
38 | links = {
39 | 'Users' => users_path,
40 | 'Hosts' => host_machines_path,
41 | 'Organisations' => organisations_path,
42 | 'Groups' => groups_path,
43 | 'APIs' => api_resources_path,
44 | 'VPNs' => vpns_path,
45 | 'API' => new_api_resource_path,
46 | 'Group' => new_group_path,
47 | 'VPN' => new_vpn_path,
48 | 'Organisation' => new_organisation_path,
49 | }
50 | links.each do |link_text, link_href|
51 | expect(page).to have_xpath(
52 | "//div[@id='main-navigation']//a[@href='#{link_href}' and .='#{link_text}']"
53 | )
54 | end
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/spec/features/organisations/add_user_saml_app_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'Config Saml App', type: :feature do
3 | let(:user) { create(:user) }
4 | let(:users) { create_list(:user, 10) }
5 | let(:org) { create(:organisation) }
6 |
7 | before do
8 | sign_in(user)
9 | end
10 |
11 | scenario 'Add user to group' do
12 | create(
13 | :saml_app_config,
14 | organisation: org,
15 | group: Group.new(name: "#{org.slug}_saml_datadog_users")
16 | )
17 | allow_any_instance_of(Group).to receive(:users).and_return(users)
18 | home_path = organisation_config_saml_app_path(
19 | organisation_id: org.id, app_name: 'datadog'
20 | )
21 | visit home_path
22 | page.find('#manage-users-tab').click
23 | page.find_field('email').set(user.email)
24 | expect_any_instance_of(Datadog).
25 | to receive(:add_user).with(user.email)
26 | page.find('#add_user_to_app').click
27 | expect(current_path).to eq(home_path)
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/features/organisations/create_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'Create Organisation', type: :feature do
3 | let(:org_data) { attributes_for(:organisation) }
4 | let(:user) { create(:user) }
5 | scenario 'Create an organisation successfully' do
6 | sign_in(user)
7 | visit new_organisation_path
8 | select Country.all.sample.name, from: 'organisation_country'
9 | %w(name website domain state address admin_email_address slug unit_name).each do |key|
10 | fill_in "organisation_#{key}", with: org_data[key.to_sym]
11 | end
12 | click_button('Create Organisation')
13 | expect(current_path).to eq(organisations_path)
14 | expect(page).to have_xpath(
15 | "//div[@id='organisation_form_success' and .='Successfully created organisation']"
16 | )
17 | end
18 | scenario 'Display Errors on Creating Organisation' do
19 | sign_in(user)
20 | visit new_organisation_path
21 | fill_in 'organisation_name', with: org_data[:name]
22 | click_button('Create Organisation')
23 | expect(current_path).to eq(organisations_path)
24 | expect(page).to have_xpath(
25 | "//div[@id='organisation_form_errors']"
26 | )
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/features/organisations/list_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'List Organisations', type: :feature do
3 | let!(:orgs) { create_list(:organisation, 5) }
4 | let(:user) { create(:user) }
5 | scenario 'Can create an organisation' do
6 | sign_in(user)
7 | visit organisations_path
8 | expect(page).to have_xpath("//a[@id='new_organisation_btn']")
9 | end
10 | scenario 'View list of organisations' do
11 | sign_in(user)
12 | visit organisations_path
13 | table_xpath = "//div[@id='organisation_list']/table"
14 | orgs.each do |org|
15 | expect(page).to have_xpath(
16 | "#{table_xpath}//td/a[@href='#{organisation_path(org)}' and .='#{org.name}']"
17 | )
18 | expect(page).to have_xpath(
19 | "#{table_xpath}//td/a[@href='#{org.website}' and .='#{org.website}']"
20 | )
21 | expect(page).to have_xpath(
22 | "#{table_xpath}//td[.='#{org.domain}']"
23 | )
24 | expect(page).to have_xpath(
25 | "#{table_xpath}//td/a[@href='#{organisation_setup_saml_path(org)}' and .='Setup SAML']"
26 | )
27 | end
28 | end
29 | scenario 'Ability to see organsiation details' do
30 | sign_in(user)
31 | visit organisations_path
32 | table_xpath = "//div[@id='organisation_list']/table"
33 | orgs.each do |org|
34 | expect(page).to have_xpath(
35 | "#{table_xpath}//td/a[@href='#{organisation_path(org)}' and .='#{org.name}']"
36 | )
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/spec/features/organisations/remove_user_saml_app_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'Config Saml App', type: :feature do
3 | let(:user) { create(:user) }
4 | let(:users) { create_list(:user, 10) }
5 | let(:org) { create(:organisation) }
6 |
7 | before do
8 | sign_in(user)
9 | end
10 |
11 | scenario 'Remove user from group' do
12 | create(
13 | :saml_app_config,
14 | organisation: org,
15 | group: Group.new(name: "#{org.slug}_saml_datadog_users")
16 | )
17 | allow_any_instance_of(Group).to receive(:users).and_return(users)
18 | home_path = organisation_config_saml_app_path(
19 | organisation_id: org.id, app_name: 'datadog'
20 | )
21 | visit home_path
22 | page.find('#manage-users-tab').click
23 | expect_any_instance_of(Datadog).
24 | to receive(:remove_user).with(users.first.email)
25 | page.find("#saml_user_remove_#{users.first.id}").click
26 | expect(current_path).to eq(home_path)
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/features/organisations/save_config_saml_app_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'Save Config Saml App', type: :feature do
3 | let(:org) { create(:organisation) }
4 | let(:user) { create(:user) }
5 | let(:app_name) { 'datadog' }
6 |
7 | before do
8 | sign_in(user)
9 | end
10 |
11 | scenario 'Load Present Configuration' do
12 | url = Faker::Internet.url
13 | saml_app = Datadog.new(org.id)
14 | app_key = Faker::Internet.password(min_length: 8)
15 | api_key = Faker::Internet.password(min_length: 8)
16 | saml_app.save_config(url, app_key: app_key, api_key: api_key)
17 | visit organisation_config_saml_app_path(
18 | organisation_id: org.id, app_name: app_name
19 | )
20 | page.find('#settings-tab').click
21 | expect(page.find_field('saml_app_config_sso_url').value).to eq(url)
22 | expect(page.find_field('config_app_key').value).to eq(app_key)
23 | expect(page.find_field('config_api_key').value).to eq(api_key)
24 | end
25 |
26 | scenario 'Load New Configuration If Not Saved' do
27 | visit organisation_config_saml_app_path(
28 | organisation_id: org.id, app_name: app_name
29 | )
30 | page.find('#settings-tab').click
31 | expect(page.find_field('saml_app_config_sso_url').value.blank?).to eq(true)
32 | expect(page.find_field('config_app_key').value.blank?).to eq(true)
33 | expect(page.find_field('config_api_key').value.blank?).to eq(true)
34 | end
35 |
36 | scenario 'Save Configuration' do
37 | url = Faker::Internet.url
38 | app_key = Faker::Internet.password(min_length: 8)
39 | api_key = Faker::Internet.password(min_length: 8)
40 | path = organisation_config_saml_app_path(
41 | organisation_id: org.id, app_name: app_name
42 | )
43 | visit path
44 | page.find('#settings-tab').click
45 | page.find_field('saml_app_config_sso_url').set(url)
46 | page.find_field('config_app_key').set(app_key)
47 | page.find_field('config_api_key').set(api_key)
48 | page.find('#new_saml_app_config').click
49 | expect(current_path).to eq(path)
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/spec/features/organisations/setup_saml_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'Setup SAML', type: :feature do
3 | let!(:org) { create(:organisation) }
4 | let(:user) { create(:user) }
5 | scenario 'Should show a success message if SAML is setup' do
6 | sign_in(user)
7 | allow_any_instance_of(Organisation).to receive(:setup_saml_certs).and_return(true)
8 | visit organisation_setup_saml_path(org)
9 | expect(current_path).to eq(organisations_path)
10 | expect(page).to have_xpath(
11 | "//div[@id='organisation_form_success' and .='Successfully setup SAML Certificates']"
12 | )
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/spec/features/organisations/update_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'Update Organisation', type: :feature do
3 | let!(:org) { create(:organisation) }
4 | let(:org_data) { attributes_for(:organisation) }
5 | let(:user) { create(:user) }
6 | scenario 'Create an organisation successfully' do
7 | sign_in(user)
8 | visit organisation_path(org)
9 | select Country.all.sample.name, from: 'organisation_country'
10 | %w(name website domain state address admin_email_address slug unit_name).each do |key|
11 | fill_in "organisation_#{key}", with: org_data[key.to_sym]
12 | end
13 | click_button('Update Organisation')
14 | expect(current_path).to eq(organisations_path)
15 | expect(page).to have_xpath(
16 | "//div[@id='organisation_form_success' and .='Successfully updated organisation']"
17 | )
18 | end
19 | scenario 'Display Errors on Creating Organisation' do
20 | sign_in(user)
21 | visit organisation_path(org)
22 | fill_in 'organisation_name', with: ''
23 | click_button('Update Organisation')
24 | expect(current_path).to eq(organisation_path(org))
25 | expect(page).to have_xpath(
26 | "//div[@id='organisation_form_errors']"
27 | )
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/features/saml/show_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'Config Saml App', type: :feature do
3 | let(:org) { create(:organisation) }
4 | let(:user) { create(:user) }
5 | let(:saml_apps) { ENV['SAML_APPS'].split(',') }
6 | let(:xml_content) { Nokogiri::XML::Builder.new { |xml| xml.foo_bar 'hello' }.to_xml }
7 |
8 | before do
9 | sign_in(user)
10 | allow(SamlIdp.metadata).to receive(:signed).and_return(xml_content)
11 | end
12 |
13 | scenario 'Show metadata when no download flag' do
14 | visit metadata_path(slug: org.slug, app: saml_apps.sample)
15 | expect(page.body).to eq(xml_content)
16 | end
17 |
18 | scenario 'Download metadata with download flag' do
19 | visit metadata_path(slug: org.slug, app: saml_apps.sample, download: true)
20 | expect(page.response_headers['Content-Type']).to eq('text/xml')
21 | expect(page.response_headers['Content-Disposition']).to include('metadata.xml')
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/features/users/regenerate_auth_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | RSpec.feature 'Rengenerate Auth Token', type: :feature do
3 | let(:user) { create(:user) }
4 | let(:rotp_key) { ROTP::Base32.random_base32 }
5 | before(:each) do
6 | allow(ROTP::Base32).to receive(:random_base32).and_return(rotp_key)
7 | end
8 | scenario 'Create an organisation successfully' do
9 | sign_in user
10 | expect(user).to receive(:generate_two_factor_auth).with(true)
11 | visit regenerate_authentication_path
12 | expect(current_path).to eq(profile_path)
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/spec/helpers/application_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | describe ApplicationHelper, type: :helper do
4 | describe '.add_placeholder_to_list' do
5 | let (:placeholder) { 'placeholder' }
6 | let(:list) { (1..5).map { |ix| "row#{ix}" } }
7 |
8 | it 'returns list with first element of every array titleized and adds placeholder' do
9 | titleized_list = list.map { |row| [row.titleize, row] }.insert(0, [placeholder, ''])
10 | expect(helper.add_placeholder_to_list(list, placeholder)).to eq(titleized_list)
11 | end
12 |
13 | it 'returns list with first element of every array with string function and adds placeholder' do
14 | titleized_list = list.map { |row| [row.capitalize, row] }.insert(0, [placeholder, ''])
15 | expect(helper.add_placeholder_to_list(list, placeholder, string_convert: 'capitalize')).to eq(titleized_list)
16 | end
17 |
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/lib/tasks/users_rake_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | describe "users:purge_inactive" do
4 | before(:each) do
5 | create(:user)
6 | @user = create(:user)
7 | @user.update!(active: false)
8 | end
9 |
10 | it "purge users whom have been deactivated for more than certain time" do
11 | Gate::Application.load_tasks
12 | @user.update_column(:deactivated_at, Time.now - 16.days)
13 | Rake::Task['users:purge_inactive'].invoke
14 | @user.reload
15 | expect(@user.group_associations.length).to eq 0
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/spec/models/access_token_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe AccessToken, type: :model do
4 | let(:user) {
5 | FactoryBot.create(:user,
6 | name: "foobar",
7 | admin: true,
8 | user_login_id: "foobar",
9 | email: "foobar@foobar.com"
10 | )
11 | }
12 |
13 | before(:each) do
14 | @access_token = AccessToken.new
15 | @access_token.token = ROTP::Base32.random_base32
16 | @access_token.user = user
17 | @access_token.save!
18 | end
19 |
20 | describe "self.find_token" do
21 | it "should return access token object if it finds matching token" do
22 | expect(AccessToken.find_token(@access_token.token)).to eq @access_token
23 | end
24 | end
25 |
26 | describe "self.valid_token" do
27 | it "should return true if it finds matching token" do
28 | expect(AccessToken.valid_token(@access_token.token)).to eq true
29 | end
30 | end
31 |
32 | describe "hash_token! before_save" do
33 | it "should hash token and put it into hashed_token" do
34 | expect(@access_token.hashed_token).to eq(
35 | Digest::SHA512.hexdigest(@access_token.token))
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/spec/models/api_resource_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe ApiResource, type: :model do
4 | let(:user) {
5 | FactoryBot.create(:user,
6 | name: "foobar",
7 | admin: true,
8 | user_login_id: "foobar",
9 | email: "foobar@foobar.com"
10 | )
11 | }
12 | let(:group) { FactoryBot.create(:group, name: "foobar_group") }
13 | let(:valid_attributes) do
14 | {
15 | name: "sample_api",
16 | description: "sample_api_description",
17 | access_key: "xcz",
18 | user_id: user.id,
19 | group_id: group.id
20 | }
21 | end
22 |
23 | describe "self.authenticate" do
24 | it "should return true if it finds matching access_key and the user is member of the group" do
25 | api_resource = ApiResource.create(valid_attributes)
26 | group.users << user
27 | access_token = AccessToken.new
28 | access_token.token = ROTP::Base32.random_base32
29 | access_token.user = user
30 | access_token.save!
31 | expect(ApiResource.authenticate(valid_attributes[:access_key], access_token.token)).to eq true
32 | end
33 | end
34 |
35 | describe "hash_access_key! before_save" do
36 | it "should hash access_key and put it into hashed_access_key" do
37 | api_resource = ApiResource.create(valid_attributes)
38 | expect(api_resource.hashed_access_key).to eq(
39 | Digest::SHA512.hexdigest(valid_attributes[:access_key]))
40 | end
41 |
42 | it "shouldn't change hashed_access_key if access_key isn't supplied" do
43 | api_resource = ApiResource.create(valid_attributes)
44 | api_resource.update(description: "Change Description")
45 | expect(api_resource.hashed_access_key).to eq(
46 | Digest::SHA512.hexdigest(valid_attributes[:access_key]))
47 | end
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/spec/models/endpoint_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | describe Endpoint, type: :model do
4 | describe 'validations' do
5 | describe 'path' do
6 | context 'when given nil path' do
7 | it 'should not valid' do
8 | endpoint = build(:endpoint, path: nil)
9 | expect(endpoint).not_to be_valid
10 | end
11 | end
12 |
13 | context 'when given path with parameter' do
14 | it 'should valid' do
15 | endpoint = build(:endpoint, path: '/users/:id')
16 | expect(endpoint).to be_valid
17 | end
18 | end
19 |
20 | context 'when given invalid path' do
21 | it 'should not valid' do
22 | endpoint = build(:endpoint, path: '/users/::id')
23 | expect(endpoint).not_to be_valid
24 | end
25 | end
26 |
27 | context 'when given path ended with /' do
28 | it 'should not valid' do
29 | endpoint = build(:endpoint, path: '/users/')
30 | expect(endpoint).not_to be_valid
31 | end
32 | end
33 | end
34 |
35 | describe 'method' do
36 | context 'when given nil method' do
37 | it 'should not valid' do
38 | endpoint = build(:endpoint, method: nil)
39 | expect(endpoint).not_to be_valid
40 | end
41 | end
42 |
43 | context 'when given unknown method' do
44 | it 'should not valid' do
45 | endpoint = build(:endpoint, method: 'JUMP')
46 | expect(endpoint).not_to be_valid
47 | end
48 | end
49 | end
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/spec/models/group_association_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | describe GroupAssociation, type: :model do
4 | describe '.revoke_expired' do
5 | let(:user) { create(:user) }
6 | let(:group) { create(:group) }
7 |
8 | context 'when found expired associations' do
9 | it 'should revoke associations' do
10 | group.add_user_with_expiration(user, Date.today - 1)
11 |
12 | GroupAssociation.revoke_expired
13 |
14 | expired_association = GroupAssociation.where('expiration_date < ?', Date.today).count
15 | expect(expired_association).to eq 0
16 | end
17 |
18 | it 'should create paper trail with event destroy' do
19 | group_association = group.add_user_with_expiration(user, Date.today - 1)
20 |
21 | GroupAssociation.revoke_expired
22 |
23 | versions = PaperTrail::Version.
24 | with_item_keys(GroupAssociation.name, group_association.id).
25 | where(event: 'destroy')
26 | expect(versions.length).to eq(1)
27 | end
28 | end
29 |
30 | it 'should not revoke associations that not expired yet' do
31 | group.add_user_with_expiration(user, Date.today)
32 |
33 | GroupAssociation.revoke_expired
34 |
35 | unexpired_association = GroupAssociation.where('expiration_date >= ?', Date.today).count
36 | expect(unexpired_association).to eq 1
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/spec/models/group_endpoint_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | describe GroupEndpoint, type: :model do
4 | let(:group) { create(:group) }
5 | let(:endpoint) { create(:endpoint) }
6 |
7 | describe 'validations' do
8 | context 'given duplicate group with endpoint' do
9 | it 'should not valid' do
10 | GroupEndpoint.create(group: group, endpoint: endpoint)
11 | group_endpoint = GroupEndpoint.new(group: group, endpoint: endpoint)
12 | expect(group_endpoint).not_to be_valid
13 | end
14 | end
15 |
16 | context 'given nil group' do
17 | it 'should not valid' do
18 | group_endpoint = GroupEndpoint.new(group: nil, endpoint: endpoint)
19 | expect(group_endpoint).not_to be_valid
20 | end
21 | end
22 |
23 | context 'given nil endpoint' do
24 | it 'should not valid' do
25 | group_endpoint = GroupEndpoint.new(group: group, endpoint: nil)
26 | expect(group_endpoint).not_to be_valid
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/models/host_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe Host, type: :model do
4 | end
5 |
--------------------------------------------------------------------------------
/spec/models/ip_address_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe IpAddress, type: :model do
4 | end
5 |
--------------------------------------------------------------------------------
/spec/models/vpn_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe Vpn, type: :model do
4 | context "vpn administration" do
5 | it "should test user and vpn management" do
6 | vpn = Vpn.create(name: "X")
7 | group = create(:group)
8 | vpn.groups << group
9 | vpn.save!
10 |
11 | user = create(:user)
12 |
13 | group.users << user
14 | group.save!
15 |
16 | expect(Vpn.administrator? user).to eq false
17 |
18 | group.add_admin user
19 |
20 | expect(Vpn.administrator? user).to eq true
21 | expect(Vpn.managed_vpns(user).count).to eq 1
22 | vpn = Vpn.create(name: :"Y")
23 | vpn.groups << group
24 | vpn.save!
25 | expect(Vpn.managed_vpns(user).count).to eq 2
26 | vpn = Vpn.create(name: :"Z")
27 | expect(Vpn.managed_vpns(user).count).to eq 2
28 | vpn = Vpn.create(name: :"Z1")
29 | group = create(:group)
30 | vpn.groups << group
31 | vpn.save!
32 | expect(Vpn.managed_vpns(user).count).to eq 2
33 | group.users << user
34 | group.save!
35 | group.add_admin user
36 | expect(Vpn.managed_vpns(user).count).to eq 3
37 | end
38 |
39 | it "should list all vpns for given user" do
40 |
41 |
42 | vpn = Vpn.create(name: :"X")
43 | group = create(:group)
44 | vpn.groups << group
45 | vpn.save!
46 |
47 | user = create(:user)
48 |
49 | if !group.member? user
50 | group.users << user
51 | group.save!
52 | end
53 |
54 | expect(Vpn.user_vpns(user).count).to eq 1
55 | vpn = Vpn.create(name: :"Y")
56 | vpn.groups << group
57 | vpn.save!
58 | expect(Vpn.user_vpns(user).count).to eq 2
59 | vpn = Vpn.create(name: :"Z")
60 | expect(Vpn.user_vpns(user).count).to eq 2
61 | vpn = Vpn.create(name: :"Z1")
62 | group = create(:group)
63 | group.users << user
64 | vpn.groups << group
65 | vpn.save!
66 | expect(Vpn.user_vpns(user).count).to eq 3
67 |
68 |
69 | end
70 | end
71 | end
72 |
73 |
--------------------------------------------------------------------------------
/spec/routing/api_resources_routing_spec.rb:
--------------------------------------------------------------------------------
1 | require "rails_helper"
2 |
3 | RSpec.describe ApiResourcesController, type: :routing do
4 | describe "routing" do
5 |
6 | it "routes to #index" do
7 | expect(:get => "/api_resources").to route_to("api_resources#index")
8 | end
9 |
10 | it "routes to #new" do
11 | expect(:get => "/api_resources/new").to route_to("api_resources#new")
12 | end
13 |
14 | it "routes to #show" do
15 | expect(:get => "/api_resources/1").to route_to("api_resources#show", :id => "1")
16 | end
17 |
18 | it "routes to #edit" do
19 | expect(:get => "/api_resources/1/edit").to route_to("api_resources#edit", :id => "1")
20 | end
21 |
22 | it "routes to #create" do
23 | expect(:post => "/api_resources").to route_to("api_resources#create")
24 | end
25 |
26 | it "routes to #update via PUT" do
27 | expect(:put => "/api_resources/1").to route_to("api_resources#update", :id => "1")
28 | end
29 |
30 | it "routes to #update via PATCH" do
31 | expect(:patch => "/api_resources/1").to route_to("api_resources#update", :id => "1")
32 | end
33 |
34 | it "routes to #destroy" do
35 | expect(:delete => "/api_resources/1").to route_to("api_resources#destroy", :id => "1")
36 | end
37 |
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # This file was generated by the `rails generate rspec:install` command.
2 | # Conventionally, all specs live under a `spec` directory, which RSpec adds to
3 | # the `$LOAD_PATH`.
4 | # The generated `.rspec` file contains `--require spec_helper` which will cause
5 | # this file to always be loaded, without a need to explicitly require it in any
6 | # files.
7 | #
8 | # Given that it is always loaded, you are encouraged to keep this file as
9 | # light-weight as possible. Requiring heavyweight dependencies from this file
10 | # will add to the boot time of your test suite on EVERY test run, even for an
11 | # individual file that may not need all of that loaded. Instead, consider making
12 | # a separate helper file that requires the additional dependencies and performs
13 | # the additional setup, and require it from the spec files that actually need
14 | # it.
15 | #
16 | # The `.rspec` file also contains a few flags that are not defaults but that
17 | # users commonly want.
18 | #
19 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
20 | RSpec.configure do |config|
21 | # rspec-expectations config goes here. You can use an alternate
22 | # assertion/expectation library such as wrong or the stdlib/minitest
23 | # assertions if you prefer.
24 | config.expect_with :rspec do |expectations|
25 | # This option will default to `true` in RSpec 4. It makes the `description`
26 | # and `failure_message` of custom matchers include text for helper methods
27 | # defined using `chain`, e.g.:
28 | # be_bigger_than(2).and_smaller_than(4).description
29 | # # => "be bigger than 2 and smaller than 4"
30 | # ...rather than:
31 | # # => "be bigger than 2"
32 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true
33 | end
34 | # rspec-mocks config goes here. You can use an alternate test double
35 | # library (such as bogus or mocha) by changing the `mock_with` option here.
36 | config.mock_with :rspec do |mocks|
37 | # Prevents you from mocking or stubbing a method that does not exist on
38 | # a real object. This is generally recommended, and will default to
39 | # `true` in RSpec 4.
40 | mocks.verify_partial_doubles = true
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/spec/support/helpers/x509_certificate_helper.rb:
--------------------------------------------------------------------------------
1 | class CertificateHelper
2 | def initialize
3 | @key = OpenSSL::PKey::RSA.new(1024)
4 | @public_key = @key.public_key
5 |
6 | subject = "/C=BE/O=Test/OU=Test/CN=Test"
7 |
8 | @cert = OpenSSL::X509::Certificate.new
9 | @cert.subject = @cert.issuer = OpenSSL::X509::Name.parse(subject)
10 | @cert.not_before = Time.now
11 | @cert.not_after = Time.now + 1 * 24 * 60 * 60
12 | @cert.public_key = @public_key
13 | @cert.serial = 0x0
14 | @cert.version = 2
15 |
16 | @cert.sign @key, OpenSSL::Digest::SHA256.new
17 | end
18 |
19 | def get_cert
20 | @cert.to_pem
21 | end
22 |
23 | def get_private_key
24 | @key.to_s
25 | end
26 |
27 | def get_fingerprint
28 | OpenSSL::Digest::SHA256.new(@cert.to_der).to_s
29 | end
30 |
31 | end
32 |
33 |
--------------------------------------------------------------------------------
/spec/views/api_resources/edit.html.slim_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe "api_resources/edit", type: :view do
4 | before(:each) do
5 | @api_resource = assign(:api_resource, ApiResource.create!(
6 | :name => "MyString",
7 | :description => "MyString",
8 | :access_key => "MyString"
9 | ))
10 | end
11 |
12 | it "renders the edit api_resource form" do
13 | render
14 |
15 | assert_select "form[action=?][method=?]", api_resource_path(@api_resource), "post" do
16 |
17 | assert_select "input#api_resource_name[name=?]", "api_resource[name]"
18 |
19 | assert_select "input#api_resource_description[name=?]", "api_resource[description]"
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/spec/views/api_resources/index.html.slim_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe "api_resources/index", type: :view do
4 | before(:each) do
5 | assign(:api_resources, [
6 | ApiResource.create!(
7 | :name => "Name",
8 | :description => "Description",
9 | :access_key => "Access Key"
10 | ),
11 | ApiResource.create!(
12 | :name => "Name2",
13 | :description => "Description",
14 | :access_key => "Access Key"
15 | )
16 | ])
17 | end
18 |
19 | it "renders a list of api_resources" do
20 | render
21 | assert_select "tr>td", :text => "Name".to_s, :count => 1
22 | assert_select "tr>td", :text => "Description".to_s, :count => 2
23 | assert_select "tr>td", :text => "Regenerate".to_s, :count => 2
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/spec/views/api_resources/new.html.slim_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe "api_resources/new", type: :view do
4 | before(:each) do
5 | assign(:api_resource, ApiResource.new(
6 | :name => "MyString",
7 | :description => "MyString",
8 | :access_key => "MyString"
9 | ))
10 | end
11 |
12 | it "renders new api_resource form" do
13 | render
14 |
15 | assert_select "form[action=?][method=?]", api_resources_path, "post" do
16 |
17 | assert_select "input#api_resource_name[name=?]", "api_resource[name]"
18 |
19 | assert_select "input#api_resource_description[name=?]", "api_resource[description]"
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/spec/views/api_resources/show.html.slim_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe "api_resources/show", type: :view do
4 | before(:each) do
5 | @api_resource = assign(:api_resource, ApiResource.create!(
6 | :name => "Name",
7 | :description => "Description",
8 | :access_key => "Access Key"
9 | ))
10 | end
11 |
12 | it "renders attributes in " do
13 | render
14 | expect(rendered).to match(/Name/)
15 | expect(rendered).to match(/Description/)
16 | expect(rendered).to match(/Access Key/)
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/spec/views/groups/show.html.slim_spec.rb:
--------------------------------------------------------------------------------
1 | RSpec.describe 'groups/show', type: :view do
2 | let(:admin) { create(:admin_user) }
3 | let(:group) { create(:group) }
4 |
5 | context 'authorized as admin' do
6 | it 'should renders form to add user to group' do
7 | sign_in admin
8 | assign(:group, group)
9 | assign(:group_users, [])
10 |
11 | render
12 |
13 | assert_select 'form[action=?][method=?]', add_user_to_group_path(group.id), 'post' do
14 | assert_select 'input#add_user_user_id[name=user_id]'
15 | assert_select 'input#expiration_date[name=expiration_date][type=date]'
16 | end
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/views/layouts/home.html.slim_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe 'layouts/home', type: :view do
4 | before(:each) do
5 | @cached_sign_in_type = ENV['SIGN_IN_TYPE']
6 | end
7 |
8 | after(:each) do
9 | ENV['SIGN_IN_TYPE'] = @cached_sign_in_type
10 | end
11 |
12 | it 'should renders google auth link when use default sign in type' do
13 | ENV['SIGN_IN_TYPE'] = ''
14 |
15 | render
16 |
17 | assert_select "a[href$='#{user_google_oauth2_omniauth_authorize_path}']"
18 | end
19 |
20 | it 'should not renders google auth link when sign in type form' do
21 | ENV['SIGN_IN_TYPE'] = 'form'
22 |
23 | render
24 |
25 | assert_select "a[href$='#{user_google_oauth2_omniauth_authorize_path}']", 0
26 | end
27 |
28 | it 'renders sign in form' do
29 | ENV['SIGN_IN_TYPE'] = 'form'
30 |
31 | render
32 |
33 | assert_select 'form[action=?][method=?]', user_sign_in_path, 'post' do
34 | assert_select 'input#name[name=name]'
35 | assert_select 'input#email[name=email]'
36 | end
37 | end
38 |
39 | it 'should not renders sign in form when sign in type is not form' do
40 | ENV['SIGN_IN_TYPE'] = 'not_form'
41 |
42 | render
43 |
44 | assert_select 'form[action=?][method=?]', user_sign_in_path, 'post', 0
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/vendor/assets/javascripts/.keep
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gate-sso/gate/958d5b920b07a23a7e7d0dbf76e1ad783dc11009/vendor/assets/stylesheets/.keep
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 |
--------------------------------------------------------------------------------