-
Notifications
You must be signed in to change notification settings - Fork 499
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NAS-130390 / 24.10 / Move discovery auth from per-portal to system-wi…
…de (#14198) - Perform database migration - Generate alerts from migration if appropriate. Uses keyvalue - Add new iscsi.discoveryauth.* APIs - Stub out auth aspect of iscsi.portal.* APIs, for later removal - Add code to clear ISCSIDiscoveryAuth alerts
- Loading branch information
1 parent
5eb8fae
commit 5447c45
Showing
6 changed files
with
477 additions
and
19 deletions.
There are no files selected for viewing
86 changes: 86 additions & 0 deletions
86
src/middlewared/middlewared/alembic/versions/24.10/2024-08-12_15-53_discoveryauth.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
"""Add iSCSI discoverauth | ||
Flatten the per-portal discovery auth to a system-wide discovery auth. | ||
Revision ID: 504a7bd32680 | ||
Revises: 4b0b7ba46e63 | ||
Create Date: 2024-08-12 15:53:48.342351+00:00 | ||
""" | ||
import json | ||
|
||
from alembic import op | ||
import sqlalchemy as sa | ||
|
||
|
||
# revision identifiers, used by Alembic. | ||
revision = '504a7bd32680' | ||
down_revision = '4b0b7ba46e63' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
op.create_table('services_iscsidiscoveryauth', | ||
sa.Column('id', sa.Integer(), nullable=False), | ||
sa.Column('iscsi_discoveryauth_authmethod', sa.String(length=120), nullable=False), | ||
sa.Column('iscsi_discoveryauth_authgroup', sa.Integer(), nullable=False), | ||
sa.PrimaryKeyConstraint('id', name=op.f('pk_services_iscsidiscoveryauth')), | ||
sa.UniqueConstraint('iscsi_discoveryauth_authgroup', name=op.f('uq_services_iscsidiscoveryauth_iscsi_discoveryauth_authgroup')), | ||
sqlite_autoincrement=True | ||
) | ||
|
||
conn = op.get_bind() | ||
data = conn.execute("SELECT iscsi_target_portal_discoveryauthgroup, iscsi_target_portal_discoveryauthmethod, id FROM services_iscsitargetportal").fetchall() | ||
|
||
# Migrate the data into the new table. | ||
# - Mutual CHAP first. | ||
mutual_chap_auth_groups = [] | ||
for authgroup, authmethod, _portal_id in data: | ||
if authmethod == 'CHAP Mutual' and authgroup not in mutual_chap_auth_groups: | ||
# Let's not carry around 'CHAP Mutual' anymore. | ||
conn.execute('INSERT INTO services_iscsidiscoveryauth (iscsi_discoveryauth_authmethod, iscsi_discoveryauth_authgroup) VALUES ("CHAP_MUTUAL",?)', authgroup) | ||
mutual_chap_auth_groups.append(authgroup) | ||
# - Simple CHAP next. | ||
simple_chap_auth_groups = [] | ||
for authgroup, authmethod, _portal_id in data: | ||
if authmethod == 'CHAP' and authgroup not in mutual_chap_auth_groups + simple_chap_auth_groups: | ||
conn.execute('INSERT INTO services_iscsidiscoveryauth (iscsi_discoveryauth_authmethod, iscsi_discoveryauth_authgroup) VALUES ("CHAP",?)', authgroup) | ||
simple_chap_auth_groups.append(authgroup) | ||
|
||
# Things to test | ||
# 1. Do we have a mix of None and non-None? | ||
# 2. If not, do we have more than one CHAP/Mutual CHAP | ||
# 3. Do we have more than one Mutual CHAP peeruser/secret? | ||
none_list = list(filter(lambda t: t[1] == 'None', data)) | ||
none_count = len(none_list) | ||
non_none_count = len(mutual_chap_auth_groups) + len(simple_chap_auth_groups) | ||
|
||
if none_count and non_none_count: | ||
portal_id_strs = list(str(item[2]) for item in none_list) | ||
none_ips = conn.execute("SELECT iscsi_target_portalip_ip FROM services_iscsitargetportalip WHERE iscsi_target_portalip_portal_id IN (?)", ','.join(portal_id_strs)).fetchall() | ||
conn.execute("INSERT INTO system_keyvalue (\"key\", value) VALUES (?, ?)", | ||
("ISCSIDiscoveryAuthMixed", json.dumps({'ips': [ip[0] for ip in none_ips]}))) | ||
elif non_none_count > 1: | ||
conn.execute("INSERT INTO system_keyvalue (\"key\", value) VALUES (?, ?)", | ||
("ISCSIDiscoveryAuthMultipleCHAP", json.dumps({}))) | ||
|
||
if mutual_chap_auth_groups: | ||
if len(mutual_chap_auth_groups) == 1: | ||
data = conn.execute(f"SELECT DISTINCT iscsi_target_auth_peeruser FROM services_iscsitargetauthcredential WHERE iscsi_target_auth_tag = {mutual_chap_auth_groups[0]} AND iscsi_target_auth_peeruser != ''").fetchall() | ||
else: | ||
tags = ','.join(str(x) for x in mutual_chap_auth_groups) | ||
data = conn.execute(f"SELECT DISTINCT iscsi_target_auth_peeruser FROM services_iscsitargetauthcredential WHERE iscsi_target_auth_tag in ({tags}) AND iscsi_target_auth_peeruser != ''").fetchall() | ||
if len(list(data)) > 1: | ||
active_peeruser = data[0][0] | ||
conn.execute("INSERT INTO system_keyvalue (\"key\", value) VALUES (?, ?)", | ||
("ISCSIDiscoveryAuthMultipleMutualCHAP", json.dumps({'peeruser': active_peeruser}))) | ||
|
||
# Remove the obsolete columns | ||
with op.batch_alter_table('services_iscsitargetportal', schema=None) as batch_op: | ||
batch_op.drop_column('iscsi_target_portal_discoveryauthgroup') | ||
batch_op.drop_column('iscsi_target_portal_discoveryauthmethod') | ||
|
||
|
||
def downgrade(): | ||
pass |
24 changes: 24 additions & 0 deletions
24
src/middlewared/middlewared/alert/source/discovery_auth.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from middlewared.alert.base import AlertCategory, AlertClass, AlertLevel, SimpleOneShotAlertClass | ||
|
||
UPGRADE_ALERTS = ['ISCSIDiscoveryAuthMixed', 'ISCSIDiscoveryAuthMultipleCHAP', 'ISCSIDiscoveryAuthMultipleMutualCHAP'] | ||
|
||
|
||
class ISCSIDiscoveryAuthMixedAlertClass(AlertClass, SimpleOneShotAlertClass): | ||
category = AlertCategory.SHARING | ||
level = AlertLevel.WARNING | ||
title = "iSCSI Discovery Authorization Global" | ||
text = "Prior to upgrade had specified iSCSI discovery auth on only some portals, now applies globally. May need to update client configuration when using %(ips)s" | ||
|
||
|
||
class ISCSIDiscoveryAuthMultipleCHAPAlertClass(AlertClass, SimpleOneShotAlertClass): | ||
category = AlertCategory.SHARING | ||
level = AlertLevel.WARNING | ||
title = "iSCSI Discovery Authorization merged" | ||
text = "Prior to upgrade different portals had different iSCSI discovery auth, now applies globally." | ||
|
||
|
||
class ISCSIDiscoveryAuthMultipleMutualCHAPAlertClass(AlertClass, SimpleOneShotAlertClass): | ||
category = AlertCategory.SHARING | ||
level = AlertLevel.WARNING | ||
title = "iSCSI Discovery Authorization Multiple Mutual CHAP" | ||
text = "Multiple mutual CHAP peers defined for discovery auth, but only first one (\"%(peeruser)s\") applies. May need to update client configuration." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.