Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/auth/otp')
-rw-r--r--lib/gitlab/auth/otp/fortinet.rb20
-rw-r--r--lib/gitlab/auth/otp/session_enforcer.rb36
-rw-r--r--lib/gitlab/auth/otp/strategies/base.rb4
-rw-r--r--lib/gitlab/auth/otp/strategies/forti_authenticator.rb7
-rw-r--r--lib/gitlab/auth/otp/strategies/forti_token_cloud.rb72
5 files changed, 137 insertions, 2 deletions
diff --git a/lib/gitlab/auth/otp/fortinet.rb b/lib/gitlab/auth/otp/fortinet.rb
new file mode 100644
index 00000000000..a561e97dfcd
--- /dev/null
+++ b/lib/gitlab/auth/otp/fortinet.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+module Gitlab
+ module Auth
+ module Otp
+ module Fortinet
+ private
+
+ def forti_authenticator_enabled?(user)
+ ::Gitlab.config.forti_authenticator.enabled &&
+ Feature.enabled?(:forti_authenticator, user)
+ end
+
+ def forti_token_cloud_enabled?(user)
+ ::Gitlab.config.forti_token_cloud.enabled &&
+ Feature.enabled?(:forti_token_cloud, user)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth/otp/session_enforcer.rb b/lib/gitlab/auth/otp/session_enforcer.rb
new file mode 100644
index 00000000000..8cc280756cc
--- /dev/null
+++ b/lib/gitlab/auth/otp/session_enforcer.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Auth
+ module Otp
+ class SessionEnforcer
+ OTP_SESSIONS_NAMESPACE = 'session:otp'
+ DEFAULT_EXPIRATION = 15.minutes.to_i
+
+ def initialize(key)
+ @key = key
+ end
+
+ def update_session
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.setex(key_name, DEFAULT_EXPIRATION, true)
+ end
+ end
+
+ def access_restricted?
+ Gitlab::Redis::SharedState.with do |redis|
+ !redis.get(key_name)
+ end
+ end
+
+ private
+
+ attr_reader :key
+
+ def key_name
+ @key_name ||= "#{OTP_SESSIONS_NAMESPACE}:#{key.id}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth/otp/strategies/base.rb b/lib/gitlab/auth/otp/strategies/base.rb
index 718630e0e31..7d8513642c4 100644
--- a/lib/gitlab/auth/otp/strategies/base.rb
+++ b/lib/gitlab/auth/otp/strategies/base.rb
@@ -25,6 +25,10 @@ module Gitlab
result
end
+
+ def error_from_response(response)
+ error(response.message, response.code)
+ end
end
end
end
diff --git a/lib/gitlab/auth/otp/strategies/forti_authenticator.rb b/lib/gitlab/auth/otp/strategies/forti_authenticator.rb
index fbcb9fd8cdb..c1433f05db2 100644
--- a/lib/gitlab/auth/otp/strategies/forti_authenticator.rb
+++ b/lib/gitlab/auth/otp/strategies/forti_authenticator.rb
@@ -17,7 +17,10 @@ module Gitlab
# Successful authentication results in HTTP 200: OK
# https://docs.fortinet.com/document/fortiauthenticator/6.2.0/rest-api-solution-guide/704555/authentication-auth
- response.ok? ? success : error(message: response.message, http_status: response.code)
+ response.ok? ? success : error_from_response(response)
+ rescue StandardError => ex
+ Gitlab::AppLogger.error(ex)
+ error(ex.message)
end
private
@@ -32,7 +35,7 @@ module Gitlab
def api_credentials
{ username: ::Gitlab.config.forti_authenticator.username,
- password: ::Gitlab.config.forti_authenticator.token }
+ password: ::Gitlab.config.forti_authenticator.access_token }
end
end
end
diff --git a/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb b/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb
new file mode 100644
index 00000000000..d7506eca242
--- /dev/null
+++ b/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Auth
+ module Otp
+ module Strategies
+ class FortiTokenCloud < Base
+ include Gitlab::Utils::StrongMemoize
+ BASE_API_URL = 'https://ftc.fortinet.com:9696/api/v1'
+
+ def validate(otp_code)
+ if access_token_create_response.created?
+ otp_verification_response = verify_otp(otp_code)
+
+ otp_verification_response.ok? ? success : error_from_response(otp_verification_response)
+ else
+ error_from_response(access_token_create_response)
+ end
+ end
+
+ private
+
+ # TODO: Cache the access token: https://gitlab.com/gitlab-org/gitlab/-/issues/292437
+ def access_token_create_response
+ # Returns '201 CREATED' on successful creation of a new access token.
+ strong_memoize(:access_token_create_response) do
+ post(
+ url: url('/login'),
+ body: {
+ client_id: ::Gitlab.config.forti_token_cloud.client_id,
+ client_secret: ::Gitlab.config.forti_token_cloud.client_secret
+ }.to_json
+ )
+ end
+ end
+
+ def access_token
+ Gitlab::Json.parse(access_token_create_response)['access_token']
+ end
+
+ def verify_otp(otp_code)
+ # Returns '200 OK' on successful verification.
+ # Uses the access token created via `access_token_create_response` as the auth token.
+ post(
+ url: url('/auth'),
+ headers: { 'Authorization': "Bearer #{access_token}" },
+ body: {
+ username: user.username,
+ token: otp_code
+ }.to_json
+ )
+ end
+
+ def url(path)
+ BASE_API_URL + path
+ end
+
+ def post(url:, body:, headers: {})
+ Gitlab::HTTP.post(
+ url,
+ headers: {
+ 'Content-Type': 'application/json'
+ }.merge(headers),
+ body: body,
+ verify: false # FTC API Docs specifically mentions to turn off SSL Verification while making requests.
+ )
+ end
+ end
+ end
+ end
+ end
+end