summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-02-04 06:15:28 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-02-04 06:15:28 +0000
commit1a1473f44731b3f78a8485337abd3d14833efb4a (patch)
treef6e650301bc6a85242684518a91b20aee0f5f691
parent9f7f0ef116cd8f57446e1e395d8c2d6c88148096 (diff)
downloadgitlab-ce-1a1473f44731b3f78a8485337abd3d14833efb4a.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/security_configuration/components/training_provider_list.vue34
-rw-r--r--app/assets/javascripts/security_configuration/resolver.js12
-rw-r--r--app/helpers/application_settings_helper.rb2
-rw-r--r--app/models/application_setting_implementation.rb2
-rw-r--r--app/workers/loose_foreign_keys/cleanup_worker.rb2
-rw-r--r--config/feature_flags/development/loose_foreign_key_cleanup.yml8
-rw-r--r--db/migrate/20220128093756_add_ecdsa_sk_and_ed25519_sk_key_restrictions_to_application_settings.rb10
-rw-r--r--db/schema_migrations/202201280937561
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/auth/oidc.md59
-rw-r--r--doc/administration/gitaly/configure_gitaly.md6
-rw-r--r--doc/administration/gitaly/praefect.md9
-rw-r--r--doc/api/index.md9
-rw-r--r--doc/api/settings.md6
-rw-r--r--doc/push_rules/push_rules.md18
-rw-r--r--doc/security/ssh_keys_restrictions.md8
-rw-r--r--doc/security/two_factor_authentication.md6
-rw-r--r--doc/ssh/index.md85
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md2
-rw-r--r--lib/gitlab/audit/ci_runner_token_author.rb (renamed from lib/gitlab/audit/runner_registration_token_author.rb)2
-rw-r--r--lib/gitlab/audit/null_author.rb4
-rw-r--r--lib/gitlab/ssh_public_key.rb8
-rw-r--r--locale/gitlab.pot21
-rw-r--r--spec/factories/keys.rb19
-rw-r--r--spec/features/admin/admin_settings_spec.rb4
-rw-r--r--spec/features/profiles/keys_spec.rb7
-rw-r--r--spec/frontend/security_configuration/components/training_provider_list_spec.js105
-rw-r--r--spec/frontend/security_configuration/mock_data.js24
-rw-r--r--spec/helpers/ssh_keys_helper_spec.rb6
-rw-r--r--spec/lib/gitlab/audit/ci_runner_token_author_spec.rb (renamed from spec/lib/gitlab/audit/runner_registration_token_author_spec.rb)2
-rw-r--r--spec/lib/gitlab/audit/null_author_spec.rb4
-rw-r--r--spec/lib/gitlab/ssh_public_key_spec.rb34
-rw-r--r--spec/models/audit_event_spec.rb6
-rw-r--r--spec/models/key_spec.rb28
-rw-r--r--spec/requests/api/settings_spec.rb6
-rw-r--r--spec/views/profiles/keys/_key.html.haml_spec.rb4
-rw-r--r--spec/workers/loose_foreign_keys/cleanup_worker_spec.rb10
37 files changed, 492 insertions, 83 deletions
diff --git a/app/assets/javascripts/security_configuration/components/training_provider_list.vue b/app/assets/javascripts/security_configuration/components/training_provider_list.vue
index c289df9f1f4..7a4c0205569 100644
--- a/app/assets/javascripts/security_configuration/components/training_provider_list.vue
+++ b/app/assets/javascripts/security_configuration/components/training_provider_list.vue
@@ -1,6 +1,8 @@
<script>
import { GlAlert, GlCard, GlToggle, GlLink, GlSkeletonLoader } from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
import { __ } from '~/locale';
+import dismissUserCalloutMutation from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql';
import securityTrainingProvidersQuery from '../graphql/security_training_providers.query.graphql';
import configureSecurityTrainingProvidersMutation from '../graphql/configure_security_training_providers.mutation.graphql';
@@ -43,6 +45,7 @@ export default {
errorMessage: '',
toggleLoading: false,
securityTrainingProviders: [],
+ hasTouchedConfiguration: false,
};
},
computed: {
@@ -50,7 +53,36 @@ export default {
return this.$apollo.queries.securityTrainingProviders.loading;
},
},
+ created() {
+ const unwatchConfigChance = this.$watch('hasTouchedConfiguration', () => {
+ this.dismissFeaturePromotionCallout();
+ unwatchConfigChance();
+ });
+ },
methods: {
+ async dismissFeaturePromotionCallout() {
+ try {
+ const {
+ data: {
+ userCalloutCreate: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: dismissUserCalloutMutation,
+ variables: {
+ input: {
+ featureName: 'security_training_feature_promotion',
+ },
+ },
+ });
+
+ // handle errors reported from the backend
+ if (errors?.length > 0) {
+ throw new Error(errors[0]);
+ }
+ } catch (e) {
+ Sentry.captureException(e);
+ }
+ },
toggleProvider(selectedProviderId) {
const toggledProviders = this.securityTrainingProviders.map((provider) => ({
...provider,
@@ -85,6 +117,8 @@ export default {
// throwing an error here means we can handle scenarios within the `catch` block below
throw new Error();
}
+
+ this.hasTouchedConfiguration = true;
} catch {
this.errorMessage = this.$options.i18n.configMutationErrorMessage;
} finally {
diff --git a/app/assets/javascripts/security_configuration/resolver.js b/app/assets/javascripts/security_configuration/resolver.js
index 93175d4a3d1..51c02839a47 100644
--- a/app/assets/javascripts/security_configuration/resolver.js
+++ b/app/assets/javascripts/security_configuration/resolver.js
@@ -32,24 +32,28 @@ export default {
Mutation: {
configureSecurityTrainingProviders: (
_,
- { input: { enabledProviders, primaryProvider } },
+ { input: { enabledProviders, primaryProvider, fullPath } },
{ cache },
) => {
const sourceData = cache.readQuery({
query: securityTrainingProvidersQuery,
+ variables: {
+ fullPath,
+ },
});
- const data = produce(sourceData.securityTrainingProviders, (draftData) => {
+ const data = produce(sourceData.project, (draftData) => {
/* eslint-disable no-param-reassign */
- draftData.forEach((provider) => {
+ draftData.securityTrainingProviders.forEach((provider) => {
provider.isPrimary = provider.id === primaryProvider;
provider.isEnabled =
provider.id === primaryProvider || enabledProviders.includes(provider.id);
});
});
+
return {
__typename: 'configureSecurityTrainingProvidersPayload',
- securityTrainingProviders: data,
+ securityTrainingProviders: data.securityTrainingProviders,
};
},
},
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 7541247b19f..f90cc85ba67 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -234,7 +234,9 @@ module ApplicationSettingsHelper
:outbound_local_requests_allowlist_raw,
:dsa_key_restriction,
:ecdsa_key_restriction,
+ :ecdsa_sk_key_restriction,
:ed25519_key_restriction,
+ :ed25519_sk_key_restriction,
:eks_integration_enabled,
:eks_account_id,
:eks_access_key_id,
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 25198178f69..4bdeceb7c25 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -69,7 +69,9 @@ module ApplicationSettingImplementation
domain_allowlist: Settings.gitlab['domain_allowlist'],
dsa_key_restriction: 0,
ecdsa_key_restriction: 0,
+ ecdsa_sk_key_restriction: 0,
ed25519_key_restriction: 0,
+ ed25519_sk_key_restriction: 0,
eks_access_key_id: nil,
eks_account_id: nil,
eks_integration_enabled: false,
diff --git a/app/workers/loose_foreign_keys/cleanup_worker.rb b/app/workers/loose_foreign_keys/cleanup_worker.rb
index c3492fed77b..ecece92ec1b 100644
--- a/app/workers/loose_foreign_keys/cleanup_worker.rb
+++ b/app/workers/loose_foreign_keys/cleanup_worker.rb
@@ -12,8 +12,6 @@ module LooseForeignKeys
idempotent!
def perform
- return if Feature.disabled?(:loose_foreign_key_cleanup, default_enabled: :yaml)
-
in_lock(self.class.name.underscore, ttl: ModificationTracker::MAX_RUNTIME, retries: 0) do
stats = {}
diff --git a/config/feature_flags/development/loose_foreign_key_cleanup.yml b/config/feature_flags/development/loose_foreign_key_cleanup.yml
deleted file mode 100644
index 915ed662333..00000000000
--- a/config/feature_flags/development/loose_foreign_key_cleanup.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: loose_foreign_key_cleanup
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69165
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343545
-milestone: '14.4'
-type: development
-group: group::sharding
-default_enabled: true
diff --git a/db/migrate/20220128093756_add_ecdsa_sk_and_ed25519_sk_key_restrictions_to_application_settings.rb b/db/migrate/20220128093756_add_ecdsa_sk_and_ed25519_sk_key_restrictions_to_application_settings.rb
new file mode 100644
index 00000000000..1acd9599da4
--- /dev/null
+++ b/db/migrate/20220128093756_add_ecdsa_sk_and_ed25519_sk_key_restrictions_to_application_settings.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddEcdsaSkAndEd25519SkKeyRestrictionsToApplicationSettings < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :application_settings, :ecdsa_sk_key_restriction, :integer, default: 0, null: false
+ add_column :application_settings, :ed25519_sk_key_restriction, :integer, default: 0, null: false
+ end
+end
diff --git a/db/schema_migrations/20220128093756 b/db/schema_migrations/20220128093756
new file mode 100644
index 00000000000..fd24b6cd4cd
--- /dev/null
+++ b/db/schema_migrations/20220128093756
@@ -0,0 +1 @@
+787b1be4b69ef0eeb049ee6a3d7126dc75094b79fba18f469fffe78b16fce6a3 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 2bc680d509b..f76f7cfd3d2 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -10617,6 +10617,8 @@ CREATE TABLE application_settings (
runner_token_expiration_interval integer,
group_runner_token_expiration_interval integer,
project_runner_token_expiration_interval integer,
+ ecdsa_sk_key_restriction integer DEFAULT 0 NOT NULL,
+ ed25519_sk_key_restriction integer DEFAULT 0 NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)),
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index 0a307f4813e..a099b9c76f8 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -461,6 +461,65 @@ To use symmetric key encryption:
If after reconfiguring, you see the error `JSON::JWS::VerificationFailed` error message, this means
the incorrect secret was specified.
+#### Casdoor
+
+GitLab works with OpenID providers that use HTTPS. To connect to GitLab using OpenID with Casdoor, use HTTPS instead of HTTP.
+
+For your app, complete the following steps on Casdoor:
+
+1. Get a client ID and a client secret.
+1. Add your GitLab redirect URL. For example, if your GitLab domain is `gitlab.example.com`, ensure the Casdoor app has the following
+ `Redirect URI`: `https://gitlab.example.com/users/auth/openid_connect/callback`.
+
+See the [Casdoor documentation](https://casdoor.org/docs/integration/gitlab) for more details.
+
+Example Omnibus GitLab configuration (file path: `/etc/gitlab/gitlab.rb`):
+
+```ruby
+gitlab_rails['omniauth_providers'] = [
+ {
+ name: "openid_connect",
+ label: "Casdoor", # optional label for login button, defaults to "Openid Connect"
+ args: {
+ name: "openid_connect",
+ scope: ["openid", "profile", "email"],
+ response_type: "code",
+ issuer: "https://<CASDOOR_HOSTNAME>",
+ client_auth_method: "query",
+ discovery: true,
+ uid_field: "sub",
+ client_options: {
+ identifier: "<YOUR CLIENT ID>",
+ secret: "<YOUR CLIENT SECRET>",
+ redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
+ }
+ }
+ }
+]
+```
+
+Example installations from source configuration (file path: `config/gitlab.yml`):
+
+```yaml
+ - { name: 'openid_connect',
+ label: 'Casdoor', # optional label for login button, defaults to "Openid Connect"
+ args: {
+ name: 'openid_connect',
+ scope: ['openid','profile','email'],
+ response_type: 'code',
+ issuer: 'https://<CASDOOR_HOSTNAME>',
+ discovery: true,
+ client_auth_method: 'query',
+ uid_field: 'sub',
+ client_options: {
+ identifier: '<YOUR CLIENT ID>',
+ secret: '<YOUR CLIENT SECRET>',
+ redirect_uri: 'https://gitlab.example.com/users/auth/openid_connect/callback'
+ }
+ }
+ }
+```
+
## General troubleshooting
If you're having trouble, here are some tips:
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index deb2aba840b..88efd1885db 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -566,12 +566,6 @@ Note the following:
- You can configure Gitaly servers with both an unencrypted listening address `listen_addr` and an
encrypted listening address `tls_listen_addr` at the same time. This allows you to gradually
transition from unencrypted to encrypted traffic if necessary.
-- When running Praefect sub-commands such as `dial-nodes` and `list-untracked-repositories` from the command line with Gitaly TLS enabled, you must set
- the `SSL_CERT_DIR` or `SSL_CERT_FILE` environment variable so that the Gitaly certificate is trusted. For example:
-
- ```shell
- sudo SSL_CERT_DIR=/etc/gitlab/trusted_certs /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
- ```
To configure Gitaly with TLS:
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index e2db30b8358..9b55cbb660c 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -570,7 +570,7 @@ On the **Praefect** node:
edit `/etc/gitlab/gitlab.rb`, remember to run `sudo gitlab-ctl reconfigure`
again before trying the `sql-ping` command.
-#### Enabling TLS support
+#### Enable TLS support
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/1698) in GitLab 13.2.
@@ -594,6 +594,13 @@ Note the following:
- Hostname, you can either use the Common Name field for this, or add it as a Subject
Alternative Name.
- IP address, you must add it as a Subject Alternative Name to the certificate.
+- When running Praefect sub-commands such as `dial-nodes` and `list-untracked-repositories` from the command line with
+ [Gitaly TLS enabled](configure_gitaly.md#enable-tls-support), you must set the `SSL_CERT_DIR` or `SSL_CERT_FILE`
+ environment variable so that the Gitaly certificate is trusted. For example:
+
+ ```shell
+ sudo SSL_CERT_DIR=/etc/gitlab/trusted_certs /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
+ ```
- You can configure Praefect servers with both an unencrypted listening address
`listen_addr` and an encrypted listening address `tls_listen_addr` at the same time.
diff --git a/doc/api/index.md b/doc/api/index.md
index 471fad9443c..589bc0416a1 100644
--- a/doc/api/index.md
+++ b/doc/api/index.md
@@ -12,6 +12,9 @@ Use the GitLab APIs to automate GitLab.
A REST API is available in GitLab.
Usage instructions are below.
+
+For examples, see [How to use the API](#how-to-use-the-api).
+
For a list of the available resources and their endpoints, see
[REST API resources](api_resources.md).
@@ -76,7 +79,7 @@ For example, the root of the v4 API is at `/api/v4`.
### Valid API request
-If you have a GitLab instance at `gitlab.example.com`:
+The following is a basic example of a request to the fictional `gitlab.example.com` endpoint:
```shell
curl "https://gitlab.example.com/api/v4/projects"
@@ -85,6 +88,10 @@ curl "https://gitlab.example.com/api/v4/projects"
The API uses JSON to serialize data. You don't need to specify `.json` at the
end of the API URL.
+NOTE:
+In the example above, replace `gitlab.example.com` with `gitlab.com` to query GitLab.com (GitLab SaaS).
+Access can be denied due to authentication. For more information, see [Authentication](#authentication).
+
### API request to expose HTTP response headers
If you want to expose HTTP response headers, use the `--include` option:
diff --git a/doc/api/settings.md b/doc/api/settings.md
index b4fe22cf997..4246c7a46f1 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -65,6 +65,8 @@ Example response:
"dsa_key_restriction": 0,
"ecdsa_key_restriction": 0,
"ed25519_key_restriction": 0,
+ "ecdsa_sk_key_restriction": 0,
+ "ed25519_sk_key_restriction": 0,
"first_day_of_week": 0,
"enforce_terms": true,
"terms": "Hello world!",
@@ -166,6 +168,8 @@ Example response:
"dsa_key_restriction": 0,
"ecdsa_key_restriction": 0,
"ed25519_key_restriction": 0,
+ "ecdsa_sk_key_restriction": 0,
+ "ed25519_sk_key_restriction": 0,
"first_day_of_week": 0,
"enforce_terms": true,
"terms": "Hello world!",
@@ -268,7 +272,9 @@ listed in the descriptions of the relevant settings.
| `domain_allowlist` | array of strings | no | Force people to use only corporate emails for sign-up. Default is `null`, meaning there is no restriction. |
| `dsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded DSA key. Default is `0` (no restriction). `-1` disables DSA keys. |
| `ecdsa_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA key. Default is `0` (no restriction). `-1` disables ECDSA keys. |
+| `ecdsa_sk_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA_SK key. Default is `0` (no restriction). `-1` disables ECDSA_SK keys. |
| `ed25519_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ED25519 key. Default is `0` (no restriction). `-1` disables ED25519 keys. |
+| `ed25519_sk_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ED25519_SK key. Default is `0` (no restriction). `-1` disables ED25519_SK keys. |
| `eks_access_key_id` | string | no | AWS IAM access key ID. |
| `eks_account_id` | string | no | Amazon account ID. |
| `eks_integration_enabled` | boolean | no | Enable integration with Amazon EKS. |
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index 7a3af50af8d..2fb04d98d34 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -172,7 +172,7 @@ Files blocked by this rule are listed below. For a complete list of criteria, se
- `id_dsa`
- `.id_dsa`
-- Private ed25519 SSH keys:
+- Private ED25519 SSH keys:
- `/ssh/id_ed25519`
- `/.ssh/personal_ed25519`
@@ -188,6 +188,22 @@ Files blocked by this rule are listed below. For a complete list of criteria, se
- `id_ecdsa`
- `.id_ecdsa`
+- Private ECDSA_SK SSH keys (GitLab 14.8 and later):
+
+ - `/ssh/id_ecdsa_sk`
+ - `/.ssh/personal_ecdsa_sk`
+ - `/config/server_ecdsa_sk`
+ - `id_ecdsa_sk`
+ - `.id_ecdsa_sk`
+
+- Private ED25519_SK SSH keys (GitLab 14.8 and later):
+
+ - `/ssh/id_ed25519_sk`
+ - `/.ssh/personal_ed25519_sk`
+ - `/config/server_ed25519_sk`
+ - `id_ed25519_sk`
+ - `.id_ed25519_sk`
+
- Any files ending with these suffixes:
- `*.pem`
diff --git a/doc/security/ssh_keys_restrictions.md b/doc/security/ssh_keys_restrictions.md
index 1b3d33c56c7..2e4a737f9aa 100644
--- a/doc/security/ssh_keys_restrictions.md
+++ b/doc/security/ssh_keys_restrictions.md
@@ -13,9 +13,9 @@ NIST). Some organizations deploying GitLab need to enforce minimum key
strength, either to satisfy internal security policy or for regulatory
compliance.
-Similarly, certain standards groups recommend using RSA, ECDSA, or ED25519 over
-the older DSA, and administrators may need to limit the allowed SSH key
-algorithms.
+Similarly, certain standards groups recommend using RSA, ECDSA, ED25519,
+ECDSA_SK, or ED25519_SK over the older DSA, and administrators may need to
+limit the allowed SSH key algorithms.
GitLab allows you to restrict the allowed SSH key technology as well as specify
the minimum key length for each technology:
@@ -45,6 +45,8 @@ By default, the GitLab.com and self-managed settings for the
- DSA SSH keys are forbidden ([since GitLab 11.0](https://about.gitlab.com/releases/2018/06/22/gitlab-11-0-released/#support-for-dsa-ssh-keys)).
- ECDSA SSH keys are allowed.
- ED25519 SSH keys are allowed.
+- ECDSA_SK SSH keys are allowed (GitLab 14.8 and later).
+- ED25519_SK SSH keys are allowed (GitLab 14.8 and later).
<!-- ## Troubleshooting
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index aad2af11f2f..e8bb627ccbd 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -116,8 +116,10 @@ reactivate 2FA from scratch if they want to use it again.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
-Two-factor authentication can be enforced for Git over SSH operations. The one-time password (OTP)
-verification can be done via a GitLab Shell command:
+Two-factor authentication can be enforced for Git over SSH operations. However, we recommend using
+[ED25519_SK](../ssh/index.md#ed25519_sk-ssh-keys) or [ECDSA_SK](../ssh/index.md#ecdsa_sk-ssh-keys) SSH keys instead.
+
+The one-time password (OTP) verification can be done using a command:
```shell
ssh git@<hostname> 2fa_verify
diff --git a/doc/ssh/index.md b/doc/ssh/index.md
index 1991063ade0..35ca9a23179 100644
--- a/doc/ssh/index.md
+++ b/doc/ssh/index.md
@@ -28,6 +28,8 @@ To view the version of SSH installed on your system, run `ssh -V`.
To communicate with GitLab, you can use the following SSH key types:
- [ED25519](#ed25519-ssh-keys)
+- [ED25519_SK](#ed25519_sk-ssh-keys) (Available in GitLab 14.8 and later.)
+- [ECDSA_SK](#ecdsa_sk-ssh-keys) (Available in GitLab 14.8 and later.)
- [RSA](#rsa-ssh-keys)
- DSA ([Deprecated](https://about.gitlab.com/releases/2018/06/22/gitlab-11-0-released/#support-for-dsa-ssh-keys) in GitLab 11.0.)
- ECDSA (As noted in [Practical Cryptography With Go](https://leanpub.com/gocrypto/read#leanpub-auto-ecdsa), the security issues related to DSA also apply to ECDSA.)
@@ -42,6 +44,20 @@ suggests that [ED25519](https://ed25519.cr.yp.to/) keys are more secure and perf
OpenSSH 6.5 introduced ED25519 SSH keys in 2014 and they should be available on most
operating systems.
+### ED25519_SK SSH keys
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78934) in GitLab 14.8.
+
+To use ED25519_SK SSH keys on GitLab, your local client and GitLab server
+must have [OpenSSH 8.2](https://www.openssh.com/releasenotes.html#8.2) or later installed.
+
+### ECDSA_SK SSH keys
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78934) in GitLab 14.8.
+
+To use ECDSA_SK SSH keys on GitLab, your local client and GitLab server
+must have [OpenSSH 8.2](https://www.openssh.com/releasenotes.html#8.2) or later installed.
+
### RSA SSH keys
Available documentation suggests that ED25519 is more secure than RSA.
@@ -64,6 +80,8 @@ Before you create a key pair, see if a key pair already exists.
| Algorithm | Public key | Private key |
| --------- | ---------- | ----------- |
| ED25519 (preferred) | `id_ed25519.pub` | `id_ed25519` |
+ | ED25519_SK | `id_ed25519_sk.pub` | `id_ed25519_sk` |
+ | ECDSA_SK | `id_ecdsa_sk.pub` | `id_ecdsa_sk` |
| RSA (at least 2048-bit key size) | `id_rsa.pub` | `id_rsa` |
| DSA (deprecated) | `id_dsa.pub` | `id_dsa` |
| ECDSA | `id_ecdsa.pub` | `id_ecdsa` |
@@ -177,6 +195,67 @@ OpenSSH format.
ssh-keygen -o -t rsa -b 4096 -C "<comment>"
```
+## Generate an SSH key pair for a FIDO/U2F hardware security key
+
+To generate ED25519_SK or ECDSA_SK SSH keys, you must use OpenSSH 8.2 or later.
+
+1. Insert a hardware security key into your computer.
+1. Open a terminal.
+1. Type `ssh-keygen -t` followed by the key type and an optional comment.
+ This comment is included in the `.pub` file that's created.
+ You may want to use an email address for the comment.
+
+ For example, for ED25519_SK:
+
+ ```shell
+ ssh-keygen -t ed25519-sk -C "<comment>"
+ ```
+
+ For ECDSA_SK:
+
+ ```shell
+ ssh-keygen -t ecdsa-sk -C "<comment>"
+ ```
+
+ If your security key supports FIDO2 resident keys, you can enable this when
+ creating your SSH key:
+
+ ```shell
+ ssh-keygen -t ed25519-sk -O resident -C "<comment>"
+ ```
+
+ `-O resident` indicates that the key should be stored on the FIDO authenticator itself.
+ Resident key is easier to import to a new computer because it can be loaded directly
+ from the security key by [`ssh-add -K`](https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/ssh-add.1#K)
+ or [`ssh-keygen -K`](https://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/ssh-keygen#K).
+
+1. Select Enter. Output similar to the following is displayed:
+
+ ```plaintext
+ Generating public/private ed25519-sk key pair.
+ You may need to touch your authenticator to authorize key generation.
+ ```
+
+1. Touch the button on the hardware security key.
+
+1. Accept the suggested filename and directory:
+
+ ```plaintext
+ Enter file in which to save the key (/home/user/.ssh/id_ed25519_sk):
+ ```
+
+1. Specify a [passphrase](https://www.ssh.com/academy/ssh/passphrase):
+
+ ```plaintext
+ Enter passphrase (empty for no passphrase):
+ Enter same passphrase again:
+ ```
+
+1. A confirmation is displayed, including information about where your files are stored.
+
+A public and private key are generated.
+[Add the public SSH key to your GitLab account](#add-an-ssh-key-to-your-gitlab-account).
+
## Add an SSH key to your GitLab account
To use SSH with GitLab, copy your public key to your GitLab account.
@@ -210,7 +289,8 @@ To use SSH with GitLab, copy your public key to your GitLab account.
1. On the left sidebar, select **SSH Keys**.
1. In the **Key** box, paste the contents of your public key.
If you manually copied the key, make sure you copy the entire key,
- which starts with `ssh-ed25519` or `ssh-rsa`, and may end with a comment.
+ which starts with `ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, `ecdsa-sha2-nistp521`,
+ `ssh-ed25519`, `sk-ecdsa-sha2-nistp256@openssh.com`, or `sk-ssh-ed25519@openssh.com`, and may end with a comment.
1. In the **Title** box, type a description, like `Work Laptop` or
`Home Workstation`.
1. Optional. In the **Expires at** box, select an expiration date. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36243) in GitLab 12.9.)
@@ -318,7 +398,8 @@ on the files make them readable to you but not accessible to others.
## Configure two-factor authentication (2FA)
You can set up two-factor authentication (2FA) for
-[Git over SSH](../security/two_factor_authentication.md#2fa-for-git-over-ssh-operations).
+[Git over SSH](../security/two_factor_authentication.md#2fa-for-git-over-ssh-operations). We recommend using
+[ED25519_SK](#ed25519_sk-ssh-keys) or [ECDSA_SK](#ecdsa_sk-ssh-keys) SSH keys.
## Use EGit on Eclipse
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index a6f7eccffe4..c38b2455a8d 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -280,7 +280,7 @@ NOTE:
SSH clone URLs can be customized in `gitlab.rb` by setting `gitlab_rails['gitlab_ssh_host']` and
other related settings.
-## Configure defaults for RSA, DSA, ECDSA, ED25519 SSH keys
+## Configure defaults for RSA, DSA, ECDSA, ED25519, ECDSA_SK, ED25519_SK SSH keys
These options specify the permitted types and lengths for SSH keys.
diff --git a/lib/gitlab/audit/runner_registration_token_author.rb b/lib/gitlab/audit/ci_runner_token_author.rb
index 53785236f72..cc140a29260 100644
--- a/lib/gitlab/audit/runner_registration_token_author.rb
+++ b/lib/gitlab/audit/ci_runner_token_author.rb
@@ -2,7 +2,7 @@
module Gitlab
module Audit
- class RunnerRegistrationTokenAuthor < Gitlab::Audit::NullAuthor
+ class CiRunnerTokenAuthor < Gitlab::Audit::NullAuthor
def initialize(token:, entity_type:, entity_path:)
super(id: -1, name: "Registration token: #{token}")
diff --git a/lib/gitlab/audit/null_author.rb b/lib/gitlab/audit/null_author.rb
index 254d3f1c7ac..64aec51471a 100644
--- a/lib/gitlab/audit/null_author.rb
+++ b/lib/gitlab/audit/null_author.rb
@@ -14,12 +14,12 @@ module Gitlab
# @param [Integer] id
# @param [String] name
#
- # @return [Gitlab::Audit::UnauthenticatedAuthor, Gitlab::Audit::DeletedAuthor, Gitlab::Audit::RunnerRegistrationTokenAuthor]
+ # @return [Gitlab::Audit::UnauthenticatedAuthor, Gitlab::Audit::DeletedAuthor, Gitlab::Audit::CiRunnerTokenAuthor]
def self.for(id, audit_event)
name = audit_event[:author_name] || audit_event.details[:author_name]
if audit_event.details.include?(:runner_registration_token)
- ::Gitlab::Audit::RunnerRegistrationTokenAuthor.new(
+ ::Gitlab::Audit::CiRunnerTokenAuthor.new(
token: audit_event.details[:runner_registration_token],
entity_type: audit_event.entity_type || audit_event.details[:entity_type],
entity_path: audit_event.entity_path || audit_event.details[:entity_path]
diff --git a/lib/gitlab/ssh_public_key.rb b/lib/gitlab/ssh_public_key.rb
index 677a2cef73f..8a2f3bbe0ee 100644
--- a/lib/gitlab/ssh_public_key.rb
+++ b/lib/gitlab/ssh_public_key.rb
@@ -10,7 +10,9 @@ module Gitlab
Technology.new(:rsa, SSHData::PublicKey::RSA, [1024, 2048, 3072, 4096], %w(ssh-rsa)),
Technology.new(:dsa, SSHData::PublicKey::DSA, [1024, 2048, 3072], %w(ssh-dss)),
Technology.new(:ecdsa, SSHData::PublicKey::ECDSA, [256, 384, 521], %w(ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521)),
- Technology.new(:ed25519, SSHData::PublicKey::ED25519, [256], %w(ssh-ed25519))
+ Technology.new(:ed25519, SSHData::PublicKey::ED25519, [256], %w(ssh-ed25519)),
+ Technology.new(:ecdsa_sk, SSHData::PublicKey::SKECDSA, [256], %w(sk-ecdsa-sha2-nistp256@openssh.com)),
+ Technology.new(:ed25519_sk, SSHData::PublicKey::SKED25519, [256], %w(sk-ssh-ed25519@openssh.com))
].freeze
def self.technology(name)
@@ -98,6 +100,10 @@ module Gitlab
key.openssl.group.order.num_bits
when :ed25519
256
+ when :ecdsa_sk
+ 256
+ when :ed25519_sk
+ 256
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index a52f514af33..d2a5afa4ad8 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -510,6 +510,12 @@ msgstr[1] ""
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
+msgid "%{completed} of %{total} issues closed"
+msgstr ""
+
+msgid "%{completed} of %{total} weight completed"
+msgstr ""
+
msgid "%{cores} cores"
msgstr ""
@@ -858,6 +864,9 @@ msgstr ""
msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr ""
+msgid "%{percentage}%% issues closed"
+msgstr ""
+
msgid "%{percentage}%% weight completed"
msgstr ""
@@ -1287,6 +1296,9 @@ msgid_plural "- Users"
msgstr[0] ""
msgstr[1] ""
+msgid "- of - issues closed"
+msgstr ""
+
msgid "- of - weight completed"
msgstr ""
@@ -27709,6 +27721,9 @@ msgstr ""
msgid "Progress"
msgstr ""
+msgid "Progress tracking"
+msgstr ""
+
msgid "Project"
msgstr ""
@@ -38998,6 +39013,12 @@ msgstr ""
msgid "Use hashed storage paths for newly created and renamed repositories. Always enabled since 13.0."
msgstr ""
+msgid "Use issue count"
+msgstr ""
+
+msgid "Use issue weight"
+msgstr ""
+
msgid "Use one line per URI"
msgstr ""
diff --git a/spec/factories/keys.rb b/spec/factories/keys.rb
index cf52e772ae0..bedfa71207f 100644
--- a/spec/factories/keys.rb
+++ b/spec/factories/keys.rb
@@ -148,5 +148,24 @@ FactoryBot.define do
KEY
end
end
+
+ factory :ecdsa_sk_key_256 do
+ key do
+ <<~KEY.delete("\n")
+ sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyN
+ TZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBDZ+f5tSRhlB7EN39f93SscTN5PUv
+ bD3UQsNrlE1ZdbwPMMRul2zlPiUvwAvnJitW0jlD/vwZOW2YN+q+iZ5c0MAAAAEc3NoOg== dummy@gitlab.com
+ KEY
+ end
+ end
+
+ factory :ed25519_sk_key_256 do
+ key do
+ <<~KEY.delete("\n")
+ sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tA
+ AAAIEX/dQ0v4127bEo8eeG1EV0ApO2lWbSnN6RWusn/NjqIAAAABHNzaDo= dummy@gitlab.com
+ KEY
+ end
+ end
end
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 21ef56f4ae4..aa396d10074 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -85,6 +85,8 @@ RSpec.describe 'Admin updates settings' do
select 'Are allowed', from: 'DSA SSH keys'
select 'Must be at least 384 bits', from: 'ECDSA SSH keys'
select 'Are forbidden', from: 'ED25519 SSH keys'
+ select 'Are forbidden', from: 'ECDSA_SK SSH keys'
+ select 'Are forbidden', from: 'ED25519_SK SSH keys'
click_on 'Save changes'
end
@@ -95,6 +97,8 @@ RSpec.describe 'Admin updates settings' do
expect(find_field('DSA SSH keys').value).to eq('0')
expect(find_field('ECDSA SSH keys').value).to eq('384')
expect(find_field('ED25519 SSH keys').value).to eq(forbidden)
+ expect(find_field('ECDSA_SK SSH keys').value).to eq(forbidden)
+ expect(find_field('ED25519_SK SSH keys').value).to eq(forbidden)
end
it 'change Account and Limit Settings' do
diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb
index b9e59a0239b..fde85a731a1 100644
--- a/spec/features/profiles/keys_spec.rb
+++ b/spec/features/profiles/keys_spec.rb
@@ -49,7 +49,12 @@ RSpec.describe 'Profile > SSH Keys' do
context 'when only DSA and ECDSA keys are allowed' do
before do
forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE
- stub_application_setting(rsa_key_restriction: forbidden, ed25519_key_restriction: forbidden)
+ stub_application_setting(
+ rsa_key_restriction: forbidden,
+ ed25519_key_restriction: forbidden,
+ ecdsa_sk_key_restriction: forbidden,
+ ed25519_sk_key_restriction: forbidden
+ )
end
it 'shows a validation error' do
diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js
index f225c135d49..ef850c33d6e 100644
--- a/spec/frontend/security_configuration/components/training_provider_list_spec.js
+++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js
@@ -1,3 +1,4 @@
+import * as Sentry from '@sentry/browser';
import { GlAlert, GlLink, GlToggle, GlCard, GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
@@ -6,8 +7,11 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
import securityTrainingProvidersQuery from '~/security_configuration/graphql/security_training_providers.query.graphql';
import configureSecurityTrainingProvidersMutation from '~/security_configuration/graphql/configure_security_training_providers.mutation.graphql';
+import dismissUserCalloutMutation from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql';
import waitForPromises from 'helpers/wait_for_promises';
import {
+ dismissUserCalloutResponse,
+ dismissUserCalloutErrorResponse,
securityTrainingProviders,
securityTrainingProvidersResponse,
testProjectPath,
@@ -20,13 +24,18 @@ describe('TrainingProviderList component', () => {
let wrapper;
let apolloProvider;
- const createApolloProvider = ({ resolvers, queryHandler } = {}) => {
- const defaultQueryHandler = jest.fn().mockResolvedValue(securityTrainingProvidersResponse);
+ const createApolloProvider = ({ resolvers, handlers = [] } = {}) => {
+ const defaultHandlers = [
+ [
+ securityTrainingProvidersQuery,
+ jest.fn().mockResolvedValue(securityTrainingProvidersResponse),
+ ],
+ ];
- apolloProvider = createMockApollo(
- [[securityTrainingProvidersQuery, queryHandler || defaultQueryHandler]],
- resolvers,
- );
+ // make sure we don't have any duplicate handlers to avoid 'Request handler already defined for query` errors
+ const mergedHandlers = [...new Map([...defaultHandlers, ...handlers])];
+
+ apolloProvider = createMockApollo(mergedHandlers, resolvers);
};
const createComponent = () => {
@@ -60,7 +69,7 @@ describe('TrainingProviderList component', () => {
const pendingHandler = () => new Promise(() => {});
createApolloProvider({
- queryHandler: pendingHandler,
+ handlers: [[securityTrainingProvidersQuery, pendingHandler]],
});
createComponent();
});
@@ -76,7 +85,20 @@ describe('TrainingProviderList component', () => {
describe('with a successful response', () => {
beforeEach(() => {
- createApolloProvider();
+ createApolloProvider({
+ handlers: [
+ [dismissUserCalloutMutation, jest.fn().mockResolvedValue(dismissUserCalloutResponse)],
+ ],
+ resolvers: {
+ Mutation: {
+ configureSecurityTrainingProviders: () => ({
+ errors: [],
+ securityTrainingProviders: [],
+ }),
+ },
+ },
+ });
+
createComponent();
});
@@ -143,6 +165,37 @@ describe('TrainingProviderList component', () => {
}),
);
});
+
+ it('dismisses the callout when the feature gets first enabled', async () => {
+ // wait for configuration update mutation to complete
+ await waitForMutationToBeLoaded();
+
+ // both the config and dismiss mutations have been called
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledTimes(2);
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenNthCalledWith(
+ 2,
+ expect.objectContaining({
+ mutation: dismissUserCalloutMutation,
+ variables: {
+ input: {
+ featureName: 'security_training_feature_promotion',
+ },
+ },
+ }),
+ );
+
+ toggleFirstProvider();
+ await waitForMutationToBeLoaded();
+
+ // the config mutation has been called again but not the dismiss mutation
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledTimes(3);
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenNthCalledWith(
+ 3,
+ expect.objectContaining({
+ mutation: configureSecurityTrainingProvidersMutation,
+ }),
+ );
+ });
});
});
@@ -157,7 +210,7 @@ describe('TrainingProviderList component', () => {
describe('when fetching training providers', () => {
beforeEach(async () => {
createApolloProvider({
- queryHandler: jest.fn().mockReturnValue(new Error()),
+ handlers: [[securityTrainingProvidersQuery, jest.fn().mockRejectedValue()]],
});
createComponent();
@@ -200,5 +253,39 @@ describe('TrainingProviderList component', () => {
expect(findErrorAlert().text()).toBe(TrainingProviderList.i18n.configMutationErrorMessage);
});
});
+
+ describe.each`
+ errorType | mutationHandler
+ ${'backend error'} | ${jest.fn().mockReturnValue(dismissUserCalloutErrorResponse)}
+ ${'network error'} | ${jest.fn().mockRejectedValue()}
+ `('when dismissing the callout and a "$errorType" happens', ({ mutationHandler }) => {
+ beforeEach(async () => {
+ jest.spyOn(Sentry, 'captureException').mockImplementation();
+
+ createApolloProvider({
+ handlers: [[dismissUserCalloutMutation, mutationHandler]],
+ resolvers: {
+ Mutation: {
+ configureSecurityTrainingProviders: () => ({
+ errors: [],
+ securityTrainingProviders: [],
+ }),
+ },
+ },
+ });
+ createComponent();
+
+ await waitForQueryToBeLoaded();
+ toggleFirstProvider();
+ });
+
+ it('logs the error to sentry', async () => {
+ expect(Sentry.captureException).not.toHaveBeenCalled();
+
+ await waitForMutationToBeLoaded();
+
+ expect(Sentry.captureException).toHaveBeenCalled();
+ });
+ });
});
});
diff --git a/spec/frontend/security_configuration/mock_data.js b/spec/frontend/security_configuration/mock_data.js
index 07c292020a3..e47a255fbac 100644
--- a/spec/frontend/security_configuration/mock_data.js
+++ b/spec/frontend/security_configuration/mock_data.js
@@ -27,3 +27,27 @@ export const securityTrainingProvidersResponse = {
},
},
};
+
+export const dismissUserCalloutResponse = {
+ data: {
+ userCalloutCreate: {
+ errors: [],
+ userCallout: {
+ dismissedAt: '2022-02-02T04:36:57Z',
+ featureName: 'SECURITY_TRAINING_FEATURE_PROMOTION',
+ },
+ },
+ },
+};
+
+export const dismissUserCalloutErrorResponse = {
+ data: {
+ userCalloutCreate: {
+ errors: ['Something went wrong'],
+ userCallout: {
+ dismissedAt: '',
+ featureName: 'SECURITY_TRAINING_FEATURE_PROMOTION',
+ },
+ },
+ },
+};
diff --git a/spec/helpers/ssh_keys_helper_spec.rb b/spec/helpers/ssh_keys_helper_spec.rb
index 1aa604f19be..522331090e4 100644
--- a/spec/helpers/ssh_keys_helper_spec.rb
+++ b/spec/helpers/ssh_keys_helper_spec.rb
@@ -17,9 +17,9 @@ RSpec.describe SshKeysHelper do
end
it 'returns only allowed algorithms' do
- expect(ssh_key_allowed_algorithms).to match('ed25519')
- stub_application_setting(ed25519_key_restriction: ApplicationSetting::FORBIDDEN_KEY_VALUE)
- expect(ssh_key_allowed_algorithms).not_to match('ed25519')
+ expect(ssh_key_allowed_algorithms).to match('rsa')
+ stub_application_setting(rsa_key_restriction: ApplicationSetting::FORBIDDEN_KEY_VALUE)
+ expect(ssh_key_allowed_algorithms).not_to match('rsa')
end
end
end
diff --git a/spec/lib/gitlab/audit/runner_registration_token_author_spec.rb b/spec/lib/gitlab/audit/ci_runner_token_author_spec.rb
index 1c26b7b5857..4d2356fc58e 100644
--- a/spec/lib/gitlab/audit/runner_registration_token_author_spec.rb
+++ b/spec/lib/gitlab/audit/ci_runner_token_author_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::Audit::RunnerRegistrationTokenAuthor do
+RSpec.describe Gitlab::Audit::CiRunnerTokenAuthor do
describe '#initialize' do
it 'sets correct attributes' do
expect(described_class.new(token: 'abc1234567', entity_type: 'Project', entity_path: 'd/e'))
diff --git a/spec/lib/gitlab/audit/null_author_spec.rb b/spec/lib/gitlab/audit/null_author_spec.rb
index 8bbe75b10d7..51e4a744111 100644
--- a/spec/lib/gitlab/audit/null_author_spec.rb
+++ b/spec/lib/gitlab/audit/null_author_spec.rb
@@ -23,14 +23,14 @@ RSpec.describe Gitlab::Audit::NullAuthor do
expect(subject.for(-1, audit_event)).to have_attributes(id: -1, name: 'Frank')
end
- it 'returns an RunnerRegistrationTokenAuthor when details contain runner registration token', :aggregate_failures do
+ it 'returns a CiRunnerTokenAuthor when details contain runner registration token', :aggregate_failures do
allow(audit_event).to receive(:[]).with(:author_name).and_return('cde456')
allow(audit_event).to receive(:entity_type).and_return('User')
allow(audit_event).to receive(:entity_path).and_return('/a/b')
allow(audit_event).to receive(:details)
.and_return({ runner_registration_token: 'cde456', author_name: 'cde456', entity_type: 'User', entity_path: '/a/b' })
- expect(subject.for(-1, audit_event)).to be_a(Gitlab::Audit::RunnerRegistrationTokenAuthor)
+ expect(subject.for(-1, audit_event)).to be_a(Gitlab::Audit::CiRunnerTokenAuthor)
expect(subject.for(-1, audit_event)).to have_attributes(id: -1, name: 'Registration token: cde456')
end
end
diff --git a/spec/lib/gitlab/ssh_public_key_spec.rb b/spec/lib/gitlab/ssh_public_key_spec.rb
index 131cf572308..cf5d2c3b455 100644
--- a/spec/lib/gitlab/ssh_public_key_spec.rb
+++ b/spec/lib/gitlab/ssh_public_key_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
end
where(:name) do
- [:rsa, :dsa, :ecdsa, :ed25519]
+ [:rsa, :dsa, :ecdsa, :ed25519, :ecdsa_sk, :ed25519_sk]
end
with_them do
@@ -24,7 +24,7 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
describe '.supported_types' do
it 'returns array with the names of supported technologies' do
expect(described_class.supported_types).to eq(
- [:rsa, :dsa, :ecdsa, :ed25519]
+ [:rsa, :dsa, :ecdsa, :ed25519, :ecdsa_sk, :ed25519_sk]
)
end
end
@@ -35,7 +35,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa, [1024, 2048, 3072, 4096]],
[:dsa, [1024, 2048, 3072]],
[:ecdsa, [256, 384, 521]],
- [:ed25519, [256]]
+ [:ed25519, [256]],
+ [:ecdsa_sk, [256]],
+ [:ed25519_sk, [256]]
]
end
@@ -53,6 +55,8 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
ssh-dss
ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521
ssh-ed25519
+ sk-ecdsa-sha2-nistp256@openssh.com
+ sk-ssh-ed25519@openssh.com
)
)
end
@@ -64,7 +68,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa, %w(ssh-rsa)],
[:dsa, %w(ssh-dss)],
[:ecdsa, %w(ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521)],
- [:ed25519, %w(ssh-ed25519)]
+ [:ed25519, %w(ssh-ed25519)],
+ [:ecdsa_sk, %w(sk-ecdsa-sha2-nistp256@openssh.com)],
+ [:ed25519_sk, %w(sk-ssh-ed25519@openssh.com)]
]
end
@@ -122,7 +128,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
rsa_key_8192
dsa_key_2048
ecdsa_key_256
- ed25519_key_256)
+ ed25519_key_256
+ ecdsa_sk_key_256
+ ed25519_sk_key_256)
end
with_them do
@@ -201,7 +209,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa_key_2048, :rsa],
[:dsa_key_2048, :dsa],
[:ecdsa_key_256, :ecdsa],
- [:ed25519_key_256, :ed25519]
+ [:ed25519_key_256, :ed25519],
+ [:ecdsa_sk_key_256, :ecdsa_sk],
+ [:ed25519_sk_key_256, :ed25519_sk]
]
end
@@ -231,7 +241,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa_key_8192, 8192],
[:dsa_key_2048, 2048],
[:ecdsa_key_256, 256],
- [:ed25519_key_256, 256]
+ [:ed25519_key_256, 256],
+ [:ecdsa_sk_key_256, 256],
+ [:ed25519_sk_key_256, 256]
]
end
@@ -261,7 +273,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa_key_8192, 'fb:53:7f:e9:2f:f7:17:aa:c8:32:52:06:8e:05:e2:82'],
[:dsa_key_2048, 'c8:85:1e:df:44:0f:20:00:3c:66:57:2b:21:10:5a:27'],
[:ecdsa_key_256, '67:a3:a9:7d:b8:e1:15:d4:80:40:21:34:bb:ed:97:38'],
- [:ed25519_key_256, 'e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73']
+ [:ed25519_key_256, 'e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73'],
+ [:ecdsa_sk_key_256, '56:b9:bc:99:3d:2f:cf:63:6b:70:d8:f9:40:7e:09:4c'],
+ [:ed25519_sk_key_256, 'f9:a0:64:0b:4b:72:72:0e:62:92:d7:04:14:74:1c:c9']
]
end
@@ -289,7 +303,9 @@ RSpec.describe Gitlab::SSHPublicKey, lib: true do
[:rsa_key_8192, 'SHA256:CtHFQAS+9Hb8z4vrv4gVQPsHjNN0WIZhWODaB1mQLs4'],
[:dsa_key_2048, 'SHA256:+a3DQ7cU5GM+gaYOfmc0VWNnykHQSuth3VRcCpWuYNI'],
[:ecdsa_key_256, 'SHA256:C+I5k3D+IGeM6k5iBR1ZsphqTKV+7uvL/XZ5hcrTr7g'],
- [:ed25519_key_256, 'SHA256:DCKAjzxWrdOTjaGKBBjtCW8qY5++GaiAJflrHPmp6W0']
+ [:ed25519_key_256, 'SHA256:DCKAjzxWrdOTjaGKBBjtCW8qY5++GaiAJflrHPmp6W0'],
+ [:ecdsa_sk_key_256, 'SHA256:N0sNKBgWKK8usPuPegtgzHQQA9vQ/dRhAEhwFDAnLA4'],
+ [:ed25519_sk_key_256, 'SHA256:U8IKRkIHed6vFMTflwweA3HhIf2DWgZ8EFTm9fgwOUk']
]
end
diff --git a/spec/models/audit_event_spec.rb b/spec/models/audit_event_spec.rb
index ddf52582dbf..957813ec3a0 100644
--- a/spec/models/audit_event_spec.rb
+++ b/spec/models/audit_event_spec.rb
@@ -112,13 +112,13 @@ RSpec.describe AuditEvent do
context "when a runner_registration_token's present" do
let(:audit_event) { build(:project_audit_event, details: { target_id: 678, runner_registration_token: 'abc123' }) }
- it 'returns a RunnerRegistrationTokenAuthor' do
- expect(::Gitlab::Audit::RunnerRegistrationTokenAuthor).to receive(:new)
+ it 'returns a CiRunnerTokenAuthor' do
+ expect(::Gitlab::Audit::CiRunnerTokenAuthor).to receive(:new)
.with({ token: 'abc123', entity_type: 'Project', entity_path: audit_event.entity_path })
.and_call_original
.once
- is_expected.to be_an_instance_of(::Gitlab::Audit::RunnerRegistrationTokenAuthor)
+ is_expected.to be_an_instance_of(::Gitlab::Audit::CiRunnerTokenAuthor)
end
it 'name consists of prefix and token' do
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index 19459561edf..6cf73de6cef 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -20,6 +20,8 @@ RSpec.describe Key, :mailer do
it { is_expected.to allow_value(attributes_for(:dsa_key_2048)[:key]).for(:key) }
it { is_expected.to allow_value(attributes_for(:ecdsa_key_256)[:key]).for(:key) }
it { is_expected.to allow_value(attributes_for(:ed25519_key_256)[:key]).for(:key) }
+ it { is_expected.to allow_value(attributes_for(:ecdsa_sk_key_256)[:key]).for(:key) }
+ it { is_expected.to allow_value(attributes_for(:ed25519_sk_key_256)[:key]).for(:key) }
it { is_expected.not_to allow_value('foo-bar').for(:key) }
context 'key format' do
@@ -187,10 +189,12 @@ RSpec.describe Key, :mailer do
forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE
[
- [:rsa_key_2048, 0, true],
- [:dsa_key_2048, 0, true],
- [:ecdsa_key_256, 0, true],
- [:ed25519_key_256, 0, true],
+ [:rsa_key_2048, 0, true],
+ [:dsa_key_2048, 0, true],
+ [:ecdsa_key_256, 0, true],
+ [:ed25519_key_256, 0, true],
+ [:ecdsa_sk_key_256, 0, true],
+ [:ed25519_sk_key_256, 0, true],
[:rsa_key_2048, 1024, true],
[:rsa_key_2048, 2048, true],
@@ -206,10 +210,18 @@ RSpec.describe Key, :mailer do
[:ed25519_key_256, 256, true],
[:ed25519_key_256, 384, false],
- [:rsa_key_2048, forbidden, false],
- [:dsa_key_2048, forbidden, false],
- [:ecdsa_key_256, forbidden, false],
- [:ed25519_key_256, forbidden, false]
+ [:ecdsa_sk_key_256, 256, true],
+ [:ecdsa_sk_key_256, 384, false],
+
+ [:ed25519_sk_key_256, 256, true],
+ [:ed25519_sk_key_256, 384, false],
+
+ [:rsa_key_2048, forbidden, false],
+ [:dsa_key_2048, forbidden, false],
+ [:ecdsa_key_256, forbidden, false],
+ [:ed25519_key_256, forbidden, false],
+ [:ecdsa_sk_key_256, forbidden, false],
+ [:ed25519_sk_key_256, forbidden, false]
]
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 7e940d52a41..ea7fee1c6f0 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -32,6 +32,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['dsa_key_restriction']).to eq(0)
expect(json_response['ecdsa_key_restriction']).to eq(0)
expect(json_response['ed25519_key_restriction']).to eq(0)
+ expect(json_response['ecdsa_sk_key_restriction']).to eq(0)
+ expect(json_response['ed25519_sk_key_restriction']).to eq(0)
expect(json_response['performance_bar_allowed_group_id']).to be_nil
expect(json_response['allow_local_requests_from_hooks_and_services']).to be(false)
expect(json_response['allow_local_requests_from_web_hooks_and_services']).to be(false)
@@ -111,6 +113,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
dsa_key_restriction: 2048,
ecdsa_key_restriction: 384,
ed25519_key_restriction: 256,
+ ecdsa_sk_key_restriction: 256,
+ ed25519_sk_key_restriction: 256,
enforce_terms: true,
terms: 'Hello world!',
performance_bar_allowed_group_path: group.full_path,
@@ -163,6 +167,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
expect(json_response['dsa_key_restriction']).to eq(2048)
expect(json_response['ecdsa_key_restriction']).to eq(384)
expect(json_response['ed25519_key_restriction']).to eq(256)
+ expect(json_response['ecdsa_sk_key_restriction']).to eq(256)
+ expect(json_response['ed25519_sk_key_restriction']).to eq(256)
expect(json_response['enforce_terms']).to be(true)
expect(json_response['terms']).to eq('Hello world!')
expect(json_response['performance_bar_allowed_group_id']).to eq(group.id)
diff --git a/spec/views/profiles/keys/_key.html.haml_spec.rb b/spec/views/profiles/keys/_key.html.haml_spec.rb
index bb101198ac3..ed8026d2453 100644
--- a/spec/views/profiles/keys/_key.html.haml_spec.rb
+++ b/spec/views/profiles/keys/_key.html.haml_spec.rb
@@ -90,8 +90,8 @@ RSpec.describe 'profiles/keys/_key.html.haml' do
using RSpec::Parameterized::TableSyntax
where(:valid, :expiry, :result) do
- false | 2.days.from_now | 'Key type is forbidden. Must be DSA, ECDSA, or ED25519'
- false | 2.days.ago | 'Key type is forbidden. Must be DSA, ECDSA, or ED25519'
+ false | 2.days.from_now | 'Key type is forbidden. Must be DSA, ECDSA, ED25519, ECDSA_SK, or ED25519_SK'
+ false | 2.days.ago | 'Key type is forbidden. Must be DSA, ECDSA, ED25519, ECDSA_SK, or ED25519_SK'
true | 2.days.ago | 'Key usable beyond expiration date.'
true | 2.days.from_now | ''
end
diff --git a/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb b/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
index 497f95cf34d..6f4389a7541 100644
--- a/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
+++ b/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
@@ -141,16 +141,6 @@ RSpec.describe LooseForeignKeys::CleanupWorker do
end
end
- context 'when the loose_foreign_key_cleanup feature flag is off' do
- before do
- stub_feature_flags(loose_foreign_key_cleanup: false)
- end
-
- it 'does nothing' do
- expect { described_class.new.perform }.not_to change { LooseForeignKeys::DeletedRecord.status_processed.count }
- end
- end
-
describe 'multi-database support' do
where(:current_minute, :configured_base_models, :expected_connection) do
2 | { main: ApplicationRecord, ci: Ci::ApplicationRecord } | ApplicationRecord.connection