Commit 4adfcbe6 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch...

Merge branch '214809-highlight-expired-ssh-or-pat-credentials-in-the-credential-inventory' into 'master'

Highlight expired SSH or PAT credentials in the credential inventory

See merge request gitlab-org/gitlab!35229
parents 8c5ecfa0 e17aa20d
- if credential.expires?
- expiry_date = credential.expires_at.to_date
- date_classes = 'gl-display-flex gl-align-items-center has-tooltip gl-w-full gl-justify-content-end gl-justify-content-md-start'
- if credential.expired?
%span{ class: date_classes + ' gl-text-red-500', title: _('This credential has expired'), data: { testid: 'expiry-date-icon' } }
= sprite_icon('error', size: 16, css_class: "gl-icon gl-mr-2")
= expiry_date
- elsif credential.expires_soon?
%span{ class: date_classes + ' gl-text-orange-500', data: { testid: 'expiry-date-icon' } }
= sprite_icon('warning', size: 16, css_class: "gl-icon gl-mr-2")
= expiry_date
- else
= expiry_date
- else
= _('Never')
.table-holder .table-holder
.thead-white.text-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' } .thead-white.gl-white-space-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-40{ role: 'rowheader' }= _('Owner') .table-section.section-40{ role: 'rowheader' }= _('Owner')
.table-section.section-30{ role: 'rowheader' }= _('Scope') .table-section.section-20{ role: 'rowheader' }= _('Scope')
.table-section.section-10{ role: 'rowheader' }= _('Created On') .table-section.section-15{ role: 'rowheader' }= _('Created On')
.table-section.section-10{ role: 'rowheader' }= _('Expiration') .table-section.section-15{ role: 'rowheader' }= _('Expiration')
.table-section.section-10{ role: 'rowheader' }= _('Revoked') .table-section.section-10{ role: 'rowheader' }= _('Revoked')
= render partial: 'shared/credentials_inventory/personal_access_tokens/personal_access_token', collection: credentials = render partial: 'shared/credentials_inventory/personal_access_tokens/personal_access_token', collection: credentials
.table-holder .table-holder
.thead-white.text-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' } .thead-white.gl-white-space-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-40{ role: 'rowheader' }= _('Owner') .table-section.section-40{ role: 'rowheader' }= _('Owner')
.table-section.section-15{ role: 'rowheader' }= _('Created On') .table-section.section-15{ role: 'rowheader' }= _('Created On')
.table-section.section-15{ role: 'rowheader' }= _('Last Accessed On') .table-section.section-15{ role: 'rowheader' }= _('Last Accessed On')
.table-section.section-15{ role: 'rowheader' }= _('Expiration')
= render partial: 'shared/credentials_inventory/ssh_keys/ssh_key', collection: credentials = render partial: 'shared/credentials_inventory/ssh_keys/ssh_key', collection: credentials
...@@ -4,25 +4,22 @@ ...@@ -4,25 +4,22 @@
= _('Owner') = _('Owner')
.table-mobile-content .table-mobile-content
= render 'shared/credentials_inventory/users/user_detail', user: personal_access_token.user = render 'shared/credentials_inventory/users/user_detail', user: personal_access_token.user
.table-section.section-30 .table-section.section-20
.table-mobile-header{ role: 'rowheader' } .table-mobile-header{ role: 'rowheader' }
= _('Scope') = _('Scope')
.table-mobile-content.ws-normal .table-mobile-content.gl-white-space-normal
- scopes = personal_access_token.scopes - scopes = personal_access_token.scopes
= scopes.present? ? scopes.join(", ") : _('No Scopes') = scopes.present? ? scopes.join(", ") : _('No Scopes')
.table-section.section-10 .table-section.section-15
.table-mobile-header{ role: 'rowheader' } .table-mobile-header{ role: 'rowheader' }
= _('Created On') = _('Created On')
.table-mobile-content .table-mobile-content
= personal_access_token.created_at.to_date = personal_access_token.created_at.to_date
.table-section.section-10 .table-section.section-15
.table-mobile-header{ role: 'rowheader' } .table-mobile-header{ role: 'rowheader' }
= _('Expiration') = _('Expiration')
.table-mobile-content .table-mobile-content.gl-w-full
- if personal_access_token.expires? = render 'shared/credentials_inventory/expiry_date', credential: personal_access_token
= personal_access_token.expires_at
- else
= _('Never')
.table-section.section-10 .table-section.section-10
.table-mobile-header{ role: 'rowheader' } .table-mobile-header{ role: 'rowheader' }
= _('Revoked') = _('Revoked')
......
...@@ -14,3 +14,8 @@ ...@@ -14,3 +14,8 @@
= _('Last Accessed On') = _('Last Accessed On')
.table-mobile-content .table-mobile-content
= (last_used_at = ssh_key.last_used_at).present? ? last_used_at.to_date : _('Never') = (last_used_at = ssh_key.last_used_at).present? ? last_used_at.to_date : _('Never')
.table-section.section-15
.table-mobile-header{ role: 'rowheader' }
= _('Expiration')
.table-mobile-content.gl-w-full
= render 'shared/credentials_inventory/expiry_date', credential: ssh_key
---
title: Highlight expired SSH or PAT credentials in the credential inventory
merge_request: 35229
author:
type: changed
...@@ -51,20 +51,9 @@ RSpec.describe 'Admin::CredentialsInventory' do ...@@ -51,20 +51,9 @@ RSpec.describe 'Admin::CredentialsInventory' do
end end
context 'by SSH Keys' do context 'by SSH Keys' do
before do let(:credentials_path) { admin_credentials_path(filter: 'ssh_keys') }
create(:personal_key,
user: create(:user, name: 'Tom'),
created_at: '2019-12-09',
last_used_at: '2019-12-10')
visit admin_credentials_path(filter: 'ssh_keys')
end
it 'shows details of ssh keys' do it_behaves_like 'credentials inventory SSH keys'
expect(first_row.text).to include('Tom')
expect(first_row.text).to include('2019-12-09')
expect(first_row.text).to include('2019-12-10')
end
end end
end end
end end
......
...@@ -48,20 +48,9 @@ RSpec.describe 'Groups::Security::Credentials' do ...@@ -48,20 +48,9 @@ RSpec.describe 'Groups::Security::Credentials' do
end end
context 'by SSH Keys' do context 'by SSH Keys' do
before do let(:credentials_path) { group_security_credentials_path(group_id: group_id, filter: 'ssh_keys') }
create(:personal_key,
user: managed_user,
created_at: '2019-12-09',
last_used_at: '2019-12-10')
visit group_security_credentials_path(group_id: group_id, filter: 'ssh_keys')
end
it 'shows details of ssh keys' do it_behaves_like 'credentials inventory SSH keys', group_managed_account: true
expect(first_row.text).to include('David')
expect(first_row.text).to include('2019-12-09')
expect(first_row.text).to include('2019-12-10')
end
end end
end end
end end
......
# frozen_string_literal: true # frozen_string_literal: true
require 'spec_helper'
RSpec.shared_examples 'credentials inventory expiry date' do
it 'shows the expiry date' do
visit credentials_path
expect(first_row.text).to include(expiry_date)
end
end
RSpec.shared_examples 'credentials inventory expiry date before' do
before do
travel_to(view_at_date)
end
after do
travel_back
end
it 'shows the expiry without any warnings' do
visit credentials_path
expect(first_row).not_to have_selector('[data-testid="expiry-date-icon"]')
end
end
RSpec.shared_examples 'credentials inventory expiry date close or past' do
before do
travel_to(view_at_date)
end
after do
travel_back
end
it 'adds a warning to the expiry date' do
visit credentials_path
expect(first_row.find('[data-testid="expiry-date-icon"]').find('svg').native.inner_html).to match(/<use xlink:href=".+?icons-.+?##{expected_icon}">/)
end
end
RSpec.shared_examples_for 'credentials inventory personal access tokens' do |group_managed_account: false| RSpec.shared_examples_for 'credentials inventory personal access tokens' do |group_managed_account: false|
let_it_be(:user) { group_managed_account ? managed_user : create(:user, name: 'David') } let_it_be(:user) { group_managed_account ? managed_user : create(:user, name: 'David') }
context 'when a personal access token is active' do context 'when a personal access token is active' do
before do before_all do
create(:personal_access_token, create(:personal_access_token,
user: user, user: user,
created_at: '2019-12-10', created_at: '2019-12-10',
updated_at: '2020-06-22', updated_at: '2020-06-22',
expires_at: nil) expires_at: nil)
end
before do
visit credentials_path visit credentials_path
end end
it 'shows the details with no revoked date' do it 'shows the details with no revoked date', :aggregate_failures do
expect(first_row.text).to include('David') expect(first_row.text).to include('David')
expect(first_row.text).to include('api') expect(first_row.text).to include('api')
expect(first_row.text).to include('2019-12-10') expect(first_row.text).to include('2019-12-10')
...@@ -23,19 +67,56 @@ RSpec.shared_examples_for 'credentials inventory personal access tokens' do |gro ...@@ -23,19 +67,56 @@ RSpec.shared_examples_for 'credentials inventory personal access tokens' do |gro
end end
end end
context 'when a personal access token has an expiry' do
let_it_be(:expiry_date) { 1.day.since.to_date.to_s }
before_all do
create(:personal_access_token,
user: user,
created_at: '2019-12-10',
updated_at: '2020-06-22',
expires_at: expiry_date)
end
context 'and is not expired' do
let(:view_at_date) { 20.days.ago }
it_behaves_like 'credentials inventory expiry date'
it_behaves_like 'credentials inventory expiry date before'
end
context 'and is near expiry' do
let(:expected_icon) { 'warning' }
let(:view_at_date) { 1.day.ago }
it_behaves_like 'credentials inventory expiry date'
it_behaves_like 'credentials inventory expiry date close or past'
end
context 'and is expired' do
let(:expected_icon) { 'error' }
let(:view_at_date) { 2.days.since }
it_behaves_like 'credentials inventory expiry date'
it_behaves_like 'credentials inventory expiry date close or past'
end
end
context 'when a personal access token is revoked' do context 'when a personal access token is revoked' do
before do before_all do
create(:personal_access_token, create(:personal_access_token,
:revoked, :revoked,
user: user, user: user,
created_at: '2019-12-10', created_at: '2019-12-10',
updated_at: '2020-06-22', updated_at: '2020-06-22',
expires_at: nil) expires_at: nil)
end
before do
visit credentials_path visit credentials_path
end end
it 'shows the details with a revoked date' do it 'shows the details with a revoked date', :aggregate_failures do
expect(first_row.text).to include('David') expect(first_row.text).to include('David')
expect(first_row.text).to include('api') expect(first_row.text).to include('api')
expect(first_row.text).to include('2019-12-10') expect(first_row.text).to include('2019-12-10')
...@@ -43,3 +124,63 @@ RSpec.shared_examples_for 'credentials inventory personal access tokens' do |gro ...@@ -43,3 +124,63 @@ RSpec.shared_examples_for 'credentials inventory personal access tokens' do |gro
end end
end end
end end
RSpec.shared_examples_for 'credentials inventory SSH keys' do |group_managed_account: false|
let_it_be(:user) { group_managed_account ? managed_user : create(:user, name: 'David') }
context 'when a SSH key is active' do
before_all do
create(:personal_key,
user: user,
created_at: '2019-12-09',
last_used_at: '2019-12-10',
expires_at: nil)
end
before do
visit credentials_path
end
it 'shows the details with no expiry', :aggregate_failures do
expect(first_row.text).to include('David')
expect(first_row.text).to include('2019-12-09')
expect(first_row.text).to include('2019-12-10')
expect(first_row.text).to include('Never')
end
end
context 'when a SSH key has an expiry' do
let_it_be(:expiry_date) { 1.day.since.to_date.to_s }
before_all do
create(:personal_key,
user: user,
created_at: '2019-12-10',
last_used_at: '2020-06-22',
expires_at: expiry_date)
end
context 'and is not expired' do
let(:view_at_date) { 20.days.ago }
it_behaves_like 'credentials inventory expiry date'
it_behaves_like 'credentials inventory expiry date before'
end
context 'and is near expiry' do
let(:expected_icon) { 'warning' }
let(:view_at_date) { 1.day.ago }
it_behaves_like 'credentials inventory expiry date'
it_behaves_like 'credentials inventory expiry date close or past'
end
context 'and is expired' do
let(:expected_icon) { 'error' }
let(:view_at_date) { 2.days.since }
it_behaves_like 'credentials inventory expiry date'
it_behaves_like 'credentials inventory expiry date close or past'
end
end
end
...@@ -23533,6 +23533,9 @@ msgstr "" ...@@ -23533,6 +23533,9 @@ msgstr ""
msgid "This content could not be displayed because %{reason}. You can %{options} instead." msgid "This content could not be displayed because %{reason}. You can %{options} instead."
msgstr "" msgstr ""
msgid "This credential has expired"
msgstr ""
msgid "This date is after the due date, so this epic won't appear in the roadmap." msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr "" msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment