gitlab-cloud-connector 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1c5bb789b8f217dd5b85dea32aa05101ece88b73ec439d68a5ef42b5bc362c5f
4
+ data.tar.gz: 6121096669714066e395e6e7e820f55a81f2787cfabb21d895c110a4ddc5aa9d
5
+ SHA512:
6
+ metadata.gz: 1a26a433e6339d320825260377887ce161803403f7dee582abef232ac86ce164145672c91b539a944731f7152e168afa15ba5c8f39f189ae954f0bca937e2ef3
7
+ data.tar.gz: 9406ef59e2f255065f2f84160e316e7e34f715bada69dd943e40af35eaea0eae642481499135bd52e62213636798800689dc0d8d00214a5da008327e2d853174
data/.idea/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
@@ -0,0 +1,127 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="FacetManager">
4
+ <facet type="RailsFacetType" name="Ruby on Rails">
5
+ <configuration>
6
+ <RAILS_FACET_CONFIG_ID NAME="RAILS_FACET_SUPPORT_REMOVED" VALUE="false" />
7
+ <RAILS_FACET_CONFIG_ID NAME="RAILS_TESTS_SOURCES_PATCHED" VALUE="true" />
8
+ <RAILS_FACET_CONFIG_ID NAME="RAILS_FACET_APPLICATION_ROOT" VALUE="$MODULE_DIR$" />
9
+ </configuration>
10
+ </facet>
11
+ </component>
12
+ <component name="ModuleRunConfigurationManager">
13
+ <shared />
14
+ </component>
15
+ <component name="NewModuleRootManager">
16
+ <content url="file://$MODULE_DIR$">
17
+ <sourceFolder url="file://$MODULE_DIR$/features" isTestSource="true" />
18
+ <sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
19
+ <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
20
+ <excludeFolder url="file://$MODULE_DIR$/.bundle" />
21
+ <excludeFolder url="file://$MODULE_DIR$/public/packs" />
22
+ <excludeFolder url="file://$MODULE_DIR$/vendor/bundle" />
23
+ <excludeFolder url="file://$MODULE_DIR$/vendor/cache" />
24
+ <excludeFolder url="file://$MODULE_DIR$/log" />
25
+ <excludeFolder url="file://$MODULE_DIR$/tmp" />
26
+ <excludeFolder url="file://$MODULE_DIR$/public/system" />
27
+ <excludeFolder url="file://$MODULE_DIR$/components" />
28
+ </content>
29
+ <orderEntry type="inheritedJdk" />
30
+ <orderEntry type="sourceFolder" forTests="false" />
31
+ <orderEntry type="library" scope="PROVIDED" name="ast (v2.4.2, asdf: 3.2.1) [gem]" level="application" />
32
+ <orderEntry type="library" scope="PROVIDED" name="crass (v1.0.6, asdf: 3.2.1) [gem]" level="application" />
33
+ <orderEntry type="library" scope="PROVIDED" name="mail (v2.8.1, asdf: 3.2.1) [gem]" level="application" />
34
+ <orderEntry type="library" scope="PROVIDED" name="net-pop (v0.1.2, asdf: 3.2.1) [gem]" level="application" />
35
+ <orderEntry type="library" scope="PROVIDED" name="rack-test (v2.1.0, asdf: 3.2.1) [gem]" level="application" />
36
+ <orderEntry type="library" scope="PROVIDED" name="rails-html-sanitizer (v1.6.0, asdf: 3.2.1) [gem]" level="application" />
37
+ <orderEntry type="library" scope="PROVIDED" name="rainbow (v3.1.1, asdf: 3.2.1) [gem]" level="application" />
38
+ <orderEntry type="library" scope="PROVIDED" name="rubocop-rails (v2.18.0, asdf: 3.2.1) [gem]" level="application" />
39
+ <orderEntry type="library" scope="PROVIDED" name="tzinfo (v2.0.6, asdf: 3.2.1) [gem]" level="application" />
40
+ <orderEntry type="library" scope="PROVIDED" name="websocket-extensions (v0.1.5, asdf: 3.2.1) [gem]" level="application" />
41
+ </component>
42
+ <component name="RModuleSettingsStorage">
43
+ <LOAD_PATH number="0" />
44
+ <I18N_FOLDERS number="1" string0="$MODULE_DIR$/config/locales" />
45
+ </component>
46
+ <component name="RailsGeneratorsCache">
47
+ <option name="generators">
48
+ <list>
49
+ <option value="active_record:migration" />
50
+ <option value="active_record:model" />
51
+ <option value="active_record:observer" />
52
+ <option value="active_record:session_migration" />
53
+ <option value="controller" />
54
+ <option value="erb:controller" />
55
+ <option value="erb:mailer" />
56
+ <option value="erb:scaffold" />
57
+ <option value="generator" />
58
+ <option value="helper" />
59
+ <option value="integration_test" />
60
+ <option value="mailer" />
61
+ <option value="metal" />
62
+ <option value="migration" />
63
+ <option value="model" />
64
+ <option value="model_subclass" />
65
+ <option value="observer" />
66
+ <option value="performance_test" />
67
+ <option value="plugin" />
68
+ <option value="resource" />
69
+ <option value="scaffold" />
70
+ <option value="scaffold_controller" />
71
+ <option value="session_migration" />
72
+ <option value="stylesheets" />
73
+ <option value="test_unit:controller" />
74
+ <option value="test_unit:helper" />
75
+ <option value="test_unit:integration" />
76
+ <option value="test_unit:mailer" />
77
+ <option value="test_unit:model" />
78
+ <option value="test_unit:observer" />
79
+ <option value="test_unit:performance" />
80
+ <option value="test_unit:plugin" />
81
+ <option value="test_unit:scaffold" />
82
+ </list>
83
+ </option>
84
+ <option name="myGenerators">
85
+ <list>
86
+ <option value="active_record:migration" />
87
+ <option value="active_record:model" />
88
+ <option value="active_record:observer" />
89
+ <option value="active_record:session_migration" />
90
+ <option value="controller" />
91
+ <option value="erb:controller" />
92
+ <option value="erb:mailer" />
93
+ <option value="erb:scaffold" />
94
+ <option value="generator" />
95
+ <option value="helper" />
96
+ <option value="integration_test" />
97
+ <option value="mailer" />
98
+ <option value="metal" />
99
+ <option value="migration" />
100
+ <option value="model" />
101
+ <option value="model_subclass" />
102
+ <option value="observer" />
103
+ <option value="performance_test" />
104
+ <option value="plugin" />
105
+ <option value="resource" />
106
+ <option value="scaffold" />
107
+ <option value="scaffold_controller" />
108
+ <option value="session_migration" />
109
+ <option value="stylesheets" />
110
+ <option value="test_unit:controller" />
111
+ <option value="test_unit:helper" />
112
+ <option value="test_unit:integration" />
113
+ <option value="test_unit:mailer" />
114
+ <option value="test_unit:model" />
115
+ <option value="test_unit:observer" />
116
+ <option value="test_unit:performance" />
117
+ <option value="test_unit:plugin" />
118
+ <option value="test_unit:scaffold" />
119
+ </list>
120
+ </option>
121
+ </component>
122
+ <component name="RakeTasksCache">
123
+ <option name="myRootTask">
124
+ <RakeTaskImpl id="rake" />
125
+ </option>
126
+ </component>
127
+ </module>
@@ -0,0 +1,9 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="Rubocop" enabled="true" level="WARNING" enabled_by_default="true">
5
+ <option name="myUseStandardGemIfPossible" value="true" />
6
+ <option name="myRunRubocopOnSave" value="true" />
7
+ </inspection_tool>
8
+ </profile>
9
+ </component>
data/.idea/misc.xml ADDED
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectRootManager" version="2" project-jdk-name="asdf: 3.2.1" project-jdk-type="RUBY_SDK" />
4
+ </project>
data/.idea/modules.xml ADDED
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/gitlab-cloud-connector.iml" filepath="$PROJECT_DIR$/.idea/gitlab-cloud-connector.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
data/.idea/vcs.xml ADDED
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="" vcs="Git" />
5
+ <mapping directory="$PROJECT_DIR$/gitlab-cloud-connector" vcs="Git" />
6
+ </component>
7
+ </project>
data/.rspec ADDED
File without changes
data/.rubocop.yml ADDED
@@ -0,0 +1,3 @@
1
+ inherit_gem:
2
+ gitlab-styles:
3
+ - rubocop-default.yml
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2024-06-11
4
+
5
+ - Initial release
data/Dangerfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gitlab-dangerfiles'
4
+
5
+ Gitlab::Dangerfiles.for_project(self, 'gitlab-cloud-connector', &:import_defaults)
data/README.md ADDED
@@ -0,0 +1,231 @@
1
+ # Gitlab::Cloud::Connector
2
+
3
+ TODO: Delete this and the text below, and describe your gem
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/gitlab/cloud/connector`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ ## Installation
8
+
9
+ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
+
11
+ Install the gem and add to the application's Gemfile by executing:
12
+
13
+ $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
14
+
15
+ If bundler is not being used to manage dependencies, install the gem by executing:
16
+
17
+ $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
18
+
19
+ ## Usage
20
+
21
+ You need to configure the Gitlab Cloud Connector gem first.
22
+ Create a class that inherits `Gitlab::CloudConnector::PurchasableDecorator` class and overrides the `available_for?` method.
23
+
24
+ Example:
25
+
26
+ ```ruby
27
+ require 'gitlab/cloud_connector/unit_primitives'
28
+
29
+
30
+ class CustomPurchasableDecorator < Gitlab::CloudConnector::PurchasableDecorator
31
+ extend ::Gitlab::Utils::Override
32
+
33
+ override :available_for?
34
+ def available_for?(namespace)
35
+ add_on_purchases(namespace).any?
36
+ end
37
+
38
+ private
39
+
40
+ def add_on_purchases(namespace = nil)
41
+ results = GitlabSubscriptions::AddOnPurchase
42
+ .by_add_on_name(add_ons)
43
+ .active
44
+ results = results.by_namespace_id(namespace.self_and_ancestor_ids) if namespace
45
+
46
+ results
47
+ end
48
+ end
49
+ ```
50
+
51
+ Create `config/initializers/cloud_connector.rb` initializer
52
+
53
+ ```ruby
54
+ # config/initializers/cloud_connector.rb
55
+
56
+ require 'gitlab/cloud_connector'
57
+ require 'custom_purchasable_decorator'
58
+
59
+ Gitlab::CloudConnector.configure do |config|
60
+ config.purchasable_decorator_class = CustomPurchasableDecorator
61
+ config.token_issuer = -> { Doorkeeper::OpenidConnect.configuration.issuer }
62
+ config.token_subject = Gitlab::CurrentSettings.uuid
63
+ config.gitlab_version = Gitlab::VERSION
64
+ config.gitlab_realm = 'self-managed'
65
+ end
66
+ ```
67
+
68
+ The CloudConnector unit primitives are grouped by `backend_services` and by the way how they are delivered: `delivered_by` (trough common interface i.e Duo Chat).
69
+
70
+ ```ruby
71
+ Gitlab::CloudConnector.unit_primitives
72
+ ```
73
+
74
+ To access specific unit primitive:
75
+
76
+ ```ruby
77
+ code_suggestions = Gitlab::CloudConnector.unit_primitives[:code_suggestions]
78
+ code_suggestions.min_gitlab_version
79
+ code_suggestions.cut_off_date
80
+ code_suggestions.add_ons
81
+ code_suggestions.feature_categories
82
+ code_suggestions.free_access?
83
+ code_suggestions.supported_gitlab_version?('16.8')
84
+ ```
85
+
86
+ You can group unit primitives by backend service that is hosting the unit primitive.
87
+
88
+ ```ruby
89
+ ai_gateway = Gitlab::CloudConnector.backend_services[:ai_gateway]
90
+ ai_gateway.min_gitlab_version # returns the smallest required gitlab version from all grouped unit primitives
91
+ ai_gateway.cut_off_date # returns the latest cut-off-date from all grouped unit primitives
92
+ ai_gateway.add_ons # returns uniq union of all add-on names bundled with grouped unit primitives
93
+ ai_gateway.feature_categories # returns uniq union of all feature-categories that introduced grouped unit primitives
94
+ ai_gateway.delivered_by # return groups of unit primitives that are delivered together and hosted by this backend service
95
+ ai_gateway.unit_primitives # return list of unit primitives that are hosted by this backend service
96
+ ```
97
+
98
+ You can group unit primitives that are delivered together. The unit primitives can share common user interface. (i.e. Duo Chat)
99
+
100
+ ```ruby
101
+ delivered_by = Gitlab::CloudConnector.delivered_by[:duo_chat]
102
+ delivered_by.min_gitlab_version # returns the smallest required gitlab version from all grouped unit primitives
103
+ delivered_by.cut_off_date # returns the latest cut-off-date from all grouped unit primitives
104
+ delivered_by.add_ons # returns uniq union of all add-on names bundled with grouped unit primitives
105
+ delivered_by.feature_categories # returns uniq union of all feature-categories that introduced grouped unit primitives
106
+ delivered_by.free_access? # checks if at least one UP in the group has free access
107
+ delivered_by.supported_gitlab_version?('16.8') # checks if at least one UP in the group is supported by provided gitlab version
108
+ delivered_by.unit_primitives # return list of unit primitives that are delivered together via duo_chat
109
+ ```
110
+
111
+ To list all available add-ons for the instance:
112
+
113
+ ```ruby
114
+ Gitlab::CloudConnector.add_ons
115
+ ```
116
+
117
+ ### AccessTokens
118
+
119
+ You can issue an isntance access token that will contain all allowed scopes across all backend services.
120
+ Note that audience header will contain the list of audiences, containing multiple supported backends,
121
+ that can authenticate this JWT token.
122
+
123
+ ```ruby
124
+ Gitlab::CloudConnector.instance_access_token(License.last, gitlab_version: '16.8')
125
+ ```
126
+
127
+ You can issue a token per backend service, that will contain all allowed scopes for unit primitives that are hosted by specified backend service.
128
+
129
+ ```ruby
130
+ Gitlab::CloudConnector.backend_services[:ai_gateway].access_token(License.last, gitlab_version: '16.8')
131
+ ```
132
+
133
+ You can issue a token per delivered_by group, that will contain all allowed scopes for unit primitives that are delivered by a common user interface (i.e. Duo Chat)
134
+
135
+ ```ruby
136
+ Gitlab::CloudConnector.delivered_by[:duo_chat].access_token(License.last, gitlab_version: '16.8')
137
+ ```
138
+
139
+ ### Permission checks
140
+
141
+ You can call all public methods implemented in PurchasableDecorator on delivered_by group or on unit primitive level
142
+
143
+ If you want to check if the access to the group has free access
144
+
145
+ ```ruby
146
+ Gitlab::CloudConnector.delivered_by[:duo_chat].free_access?
147
+ ```
148
+
149
+ You can also call any other public method that is implemented by `CloudConnector::PurchasableInterface`
150
+
151
+
152
+ Or you can check for specific unit primitive:
153
+
154
+ ```ruby
155
+ Gitlab::CloudConnector.unit_primitives[:documentation_search].free_access?
156
+ ```
157
+
158
+
159
+
160
+ ## Development
161
+
162
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
163
+
164
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
165
+
166
+ ## Contributing
167
+
168
+ Bug reports and pull requests are welcome on GitLab: []() # TODO add link
169
+
170
+ ### Introduce new unit primitive
171
+
172
+ The GitLab codebase provides bin/unit-primitive, a dedicated tool to create new unit primitive definitions.
173
+ The tool asks various questions about the new unit primitive, then creates a YAML definition in config/backend_services/[backend_service]/unit_primitives/[unit_primitive_name].yml file.
174
+
175
+ ```sh
176
+ bin/unit_primitive new_feature
177
+
178
+ >> Description of the unit primitive (enter to skip):
179
+ ?>
180
+ You picked the bakcend 'ai_gateway'
181
+
182
+ >> Cut off date when the service is no longer available for free (enter to skip):
183
+ ?> 2024-12-22 00:00
184
+
185
+ >>Minimum gitlab version (enter to skip):
186
+ ?> 16.7
187
+
188
+ >>Minimum gitlab version when feature has free access (enter to skip):
189
+ ?> 16.8
190
+
191
+ >>Minimum backend service version (enter to skip):
192
+ ?> 2.3
193
+
194
+ You picked the add_ons '["duo_enterprise", "duo_pro"]'
195
+ You picked the delivered_by '["duo_chat"]'
196
+ You picked the group 'group::cloud connector'
197
+ You picked the feature_category 'cloud_connector'
198
+
199
+ >> URL of the original unit primitive issue (enter to skip):
200
+ ?>
201
+
202
+ >> URL of the MR introducing the unit primitive (enter to skip):
203
+ ?>
204
+
205
+ You picked the gitlab_realms '["saas", "self-managed"]'
206
+
207
+ create config/cloud_connector/backend_services/ai_gateway/unit_primitives/new_feature.yml
208
+ ---
209
+ name: new_feature
210
+ description:
211
+ cut_off_date: 2024-12-22 00:00
212
+ minumum_gitlab_version: '16.7'
213
+ min_gitlab_version_for_free_access: '16.8'
214
+ min_backend_version: '2.3'
215
+ bundled_with:
216
+ - duo_enterprise
217
+ - duo_pro
218
+ delivered_by:
219
+ - duo_chat
220
+ unit_primitive_issue_url:
221
+ introduced_by_url:
222
+ group: group::cloud connector
223
+ feature_category: cloud_connector
224
+ milestone: 16.7
225
+ gitlab_realms:
226
+ - saas
227
+ - self-managed
228
+ ```
229
+
230
+
231
+
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: code_suggestions
3
+ description:
4
+ backend: 'gitlab-ai-gateway'
5
+ cut_off_date: 2024-02-15 00:00:00 UTC
6
+ min_gitlab_version_for_free_access:
7
+ min_gitlab_version: '16.8'
8
+ min_backend_version:
9
+ delivered_by:
10
+ - code_suggestions
11
+ bundled_with:
12
+ - duo_pro
13
+ - duo_enterprise
14
+ introduced_by_url:
15
+ group: group::code suggestions
16
+ feature_category: code_suggestions
17
+ gitlab_realms:
18
+ - saas
19
+ - self-managed
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: documentation_search
3
+ description:
4
+ backend: 'gitlab-ai-gateway'
5
+ cut_off_date:
6
+ min_gitlab_version_for_free_access: '16.8'
7
+ min_gitlab_version: '16.9'
8
+ min_backend_version:
9
+ delivered_by:
10
+ - duo_chat
11
+ bundled_with:
12
+ - duo_pro
13
+ - duo_enterprise
14
+ introduced_by_url:
15
+ group: group::duo_chat
16
+ feature_category: duo_chat
17
+ gitlab_realms:
18
+ - saas
19
+ - self-managed
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: duo_chat
3
+ description:
4
+ backend: 'gitlab-ai-gateway'
5
+ cut_off_date:
6
+ min_gitlab_version_for_free_access: '16.8'
7
+ min_gitlab_version: '16.9'
8
+ min_backend_version:
9
+ delivered_by:
10
+ - duo_chat
11
+ bundled_with:
12
+ - duo_pro
13
+ - duo_enterprise
14
+ introduced_by_url:
15
+ group: group::duo_chat
16
+ feature_category: duo_chat
17
+ gitlab_realms:
18
+ - saas
19
+ - self-managed
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+ require "active_support/all"
5
+
6
+ module Gitlab
7
+ module CloudConnector
8
+ module Auth
9
+ class JsonWebToken
10
+ NOT_BEFORE_TIME = 5.seconds.to_i.freeze
11
+ DEFAULT_EXPIRES_IN = 3.days.to_i.freeze
12
+ NoSigningKeyError = Class.new(StandardError)
13
+
14
+ attr_reader :expires_at, :scopes
15
+
16
+ def initialize(audience:, subject:, scopes:, expires_at: nil, extra_claims: nil, gitlab_realm: nil)
17
+ @id = SecureRandom.uuid
18
+ @audience = audience
19
+ @subject = subject
20
+ @scopes = Array.wrap(scopes)
21
+ @issuer = issuer
22
+ @issued_at = Time.current.to_i
23
+ @not_before = @issued_at - NOT_BEFORE_TIME
24
+ @expires_at = expires_at || (@issued_at + expires_in)
25
+ @extra_claims = extra_claims
26
+ @gitlab_realm = gitlab_realm || ::Gitlab::CloudConnector.gitlab_realm
27
+ end
28
+
29
+ def encode
30
+ headers = { typ: 'JWT' }
31
+
32
+ JWT.encode(payload, key, 'RS256', headers)
33
+ end
34
+
35
+ def payload
36
+ reserved_claims = {
37
+ jti: @id,
38
+ aud: @audience,
39
+ sub: @subject,
40
+ iss: @issuer,
41
+ iat: @issued_at,
42
+ nbf: @not_before,
43
+ exp: @expires_at
44
+ }
45
+
46
+ custom_claims = {
47
+ gitlab_realm: @gitlab_realm,
48
+ scopes: @scopes,
49
+ extra_claims: @extra_claims
50
+ }
51
+
52
+ reserved_claims.merge(custom_claims)
53
+ end
54
+
55
+ private
56
+
57
+ def expires_in
58
+ ::Gitlab::CloudConnector.token_expires_in || DEFAULT_EXPIRES_IN
59
+ end
60
+
61
+ def issuer
62
+ issuer = Gitlab::CloudConnector.token_issuer
63
+
64
+ if issuer.is_a?(Proc)
65
+ p "lambda?"
66
+ issuer.call
67
+ else
68
+ issuer
69
+ end
70
+ end
71
+
72
+ def key
73
+ key_data = Settings.value(:jwt_signing_key)
74
+
75
+ raise NoSigningKeyError unless key_data
76
+
77
+ OpenSSL::PKey::RSA.new(key_data)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module CloudConnector
5
+ class BackendService < BaseGroup
6
+ include Deliverable
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'token_issuer'
4
+
5
+ module Gitlab
6
+ module CloudConnector
7
+ class BaseGroup
8
+ include TokenIssuer
9
+
10
+ attr_reader :name, :unit_primitives
11
+
12
+ def initialize(name, unit_primitives)
13
+ @name = name
14
+ @unit_primitives = unit_primitives
15
+ end
16
+
17
+ def cut_off_date
18
+ unit_primitives.values.map(&:cut_off_date).compact.max
19
+ end
20
+
21
+ def bundled_with
22
+ unit_primitives.values.flat_map(&:bundled_with).uniq
23
+ end
24
+ alias :add_ons :bundled_with
25
+
26
+ def feature_categories
27
+ unit_primitives.values.map(&:feature_category).uniq
28
+ end
29
+
30
+ def min_gitlab_version
31
+ unit_primitives.values.flat_map(&:min_gitlab_version).compact.min
32
+ end
33
+
34
+ def min_gitlab_version_for_free_access
35
+ unit_primitives.values.flat_map(&:min_gitlab_version_for_free_access).compact.min
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'unit_primitives'
4
+ require_relative 'purchasable_decorator'
5
+
6
+ module Gitlab
7
+ module CloudConnector
8
+ class Configuration
9
+ attr_reader :purchasable_decorator_class
10
+ attr_accessor :token_issuer, :token_subject, :gitlab_version, :token_expires_in, :gitlab_realm
11
+
12
+ def purchasable_decorator_class=(purchasable_decorator_class)
13
+ raise ArgumentError, 'Must be a class inheriting from Gitlab::CloudConnector::PurchasableDecorator' unless
14
+ purchasable_decorator_class < Gitlab::CloudConnector::PurchasableDecorator
15
+
16
+ @purchasable_decorator_class = purchasable_decorator_class
17
+ end
18
+
19
+ def purchasable_decorator_class
20
+ @purchasable_decorator_class ||= Gitlab::CloudConnector::PurchasableDecorator
21
+ end
22
+ end
23
+ end
24
+ end