Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 64 additions & 34 deletions python/src/mas/cli/install/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -726,21 +726,25 @@ def configAdminMode(self):
" - No ClusterRoles are installed in this mode, except where required by ArcGIS and Visual Inspection (MVI)",
" - CLI pre-installs namespace-scoped Roles in prepared namespaces to grant delegated admin permissions",
" - MAS can manage applications only in namespaces prepared by the OpenShift admin",
" - DNS integration is not available in this mode. If you use a custom domain, you need to configure DNS manually.",
" - DNS integration is not available in this mode. If you use a custom domain, you need to configure DNS manually only for MAS 9.2",
"",
" 3. <b>minimal</b> - Install with essential namespace-scoped Roles only",
" - No ClusterRoles are installed in this mode, except where required by ArcGIS and Visual Inspection (MVI)",
" - Only essential permissions required for MAS applications are applied",
" - MAS UI/API cannot manage application lifecycle; OpenShift admins must manage apps outside MAS",
" - DNS integration is not available in this mode. If you use a custom domain, you need to configure DNS manually.",
" - DNS integration is not available in this mode. If you use a custom domain, you need to configure DNS manually only for MAS 9.2",
]
)

adminModeInt = self.promptForInt("Mas Admin Mode", default=1, min=1, max=3)
adminModeMap = {1: "cluster", 2: "namespaced", 3: "minimal"}
self.mas_admin_mode = adminModeMap[adminModeInt]

if self.mas_admin_mode in ["namespaced", "minimal"]:
if isVersionEqualOrAfter("9.3.0", self.getParam("mas_channel")):
# 9.3+: issuerKind is not prompted — it is derived later from the DNS provider/Let's encrypt choice.
# Default (no dns provider, no LE) Issuer, set as fallback here.
self.setParam("mas_issuer_kind", "Issuer")
elif self.mas_admin_mode in ["namespaced", "minimal"]:
self.setParam("mas_issuer_kind", "Issuer")
else:
self.printDescription(
Expand All @@ -759,10 +763,14 @@ def configAdminMode(self):
self.setParam("mas_issuer_kind", "ClusterIssuer" if issuerKindChoice == 2 else "Issuer")
elif self.mas_admin_mode == "":
self.mas_admin_mode = "cluster"
self.setParam("mas_issuer_kind", "ClusterIssuer")
if isVersionEqualOrAfter("9.3.0", self.getParam("mas_channel")):
self.setParam("mas_issuer_kind", "Issuer")
else:
self.setParam("mas_issuer_kind", "ClusterIssuer")

def _handleDNSIntegrationRestriction(self):
if not isVersionEqualOrAfter("9.2.0", self.getParam("mas_channel")):
# DNS integration restrictions only apply to MAS 9.2.x
if not (isVersionEqualOrAfter("9.2.0", self.getParam("mas_channel")) and not isVersionEqualOrAfter("9.3.0", self.getParam("mas_channel"))):
return False

if self.mas_admin_mode in ["namespaced", "minimal"]:
Expand Down Expand Up @@ -956,6 +964,8 @@ def configRoutingMode(self):
if self.yesOrNo("Do you want to use Let's Encrypt for certificate management"):
self.promptForString("Let's Encrypt e-mail", "mas_le_email")
self.setParam("mas_cluster_issuer", f"{self.getParam('mas_instance_id')}-http01-le-prod")
if isVersionEqualOrAfter("9.3.0", self.getParam("mas_channel")):
self.setParam("mas_issuer_kind", "Issuer")

def _checkIngressControllerForPathRouting(self, controllerName="default"):
"""Check if a specific IngressController exists and is configured for path-based routing.
Expand Down Expand Up @@ -1135,6 +1145,8 @@ def configDNSAndCertsCloudflare(self):

certIssuer = self._promptCertIssuer()
self.setParam("mas_cluster_issuer", self._buildCertIssuerName(self.getParam("mas_instance_id"), "cloudflare", certIssuer))
if isVersionEqualOrAfter("9.3.0", self.getParam("mas_channel")):
self.setParam("mas_issuer_kind", "ClusterIssuer")

@logMethodCall
def configDNSAndCertsCIS(self, configMas: bool, configAIService: bool):
Expand All @@ -1149,6 +1161,8 @@ def configDNSAndCertsCIS(self, configMas: bool, configAIService: bool):
self.setParam("mas_cluster_issuer", self._buildCertIssuerName(self.getParam("mas_instance_id"), "cis", certIssuer))
if configAIService:
self.setParam("aiservice_certificate_issuer", self._buildCertIssuerName(self.getParam("aiservice_instance_id"), "cis", certIssuer))
if isVersionEqualOrAfter("9.3.0", self.getParam("mas_channel")):
self.setParam("mas_issuer_kind", "ClusterIssuer")

configEnhancedSecurity = self.yesOrNo("Configure enhanced security for CIS", "cis_enhanced_security")
if configEnhancedSecurity:
Expand Down Expand Up @@ -1189,6 +1203,8 @@ def configDNSAndCertsRoute53(self, configMas: bool, configAIService: bool):

if configMas:
self.setParam("mas_cluster_issuer", f"{self.getParam('mas_instance_id')}-route53-le-prod")
if isVersionEqualOrAfter("9.3.0", self.getParam("mas_channel")):
self.setParam("mas_issuer_kind", "ClusterIssuer")

if configAIService:
self.setParam("aiservice_certificate_issuer", f"{self.getParam('aiservice_instance_id')}-route53-le-prod")
Expand Down Expand Up @@ -2626,47 +2642,61 @@ def nonInteractiveMode(self) -> None:
f"--admin-mode is required for MAS version 9.2 or higher (selected channel: {self.getParam('mas_channel')}). Valid options: cluster, namespaced, minimal"
)

# Set issuer kind based on admin mode if not explicitly set
if self.getParam("mas_issuer_kind") == "":
if self.mas_admin_mode == "cluster":
if isVersionEqualOrAfter("9.3.0", self.getParam("mas_channel")):
# MAS 9.3+: --mas-issuer-kind is not supported — issuerKind is derived automatically.
if hasattr(self.args, "mas_issuer_kind") and self.args.mas_issuer_kind is not None:
self.fatalError(
f"--mas-issuer-kind is not supported on MAS 9.3+ (selected channel: {self.getParam('mas_channel')}).\n"
"issuerKind is derived automatically from your domain and routing configuration"
)
if self.getParam("mas_routing_mode") == "path" and self.getParam("mas_le_email") != "":
self.setParam("mas_issuer_kind", "Issuer")
elif self.getParam("dns_provider") != "":
self.setParam("mas_issuer_kind", "ClusterIssuer")
else:
self.setParam("mas_issuer_kind", "Issuer")
else:
# Set issuer kind based on admin mode if not explicitly set
if self.getParam("mas_issuer_kind") == "":
if self.mas_admin_mode == "cluster":
self.setParam("mas_issuer_kind", "ClusterIssuer")
else:
self.setParam("mas_issuer_kind", "Issuer")

# Validate ClusterIssuer requires cluster mode
if self.getParam("mas_issuer_kind") == "ClusterIssuer" and self.mas_admin_mode != "cluster":
self.fatalError(
"\n".join(
[
"Invalid configuration for certificate issuer kind 'ClusterIssuer'",
"ClusterIssuer can only be used when --admin-mode cluster is selected.",
]
)
)

# Validate DNS integration restrictions
if self.getParam("dns_provider") != "":
if self.mas_admin_mode in ["namespaced", "minimal"]:
# Validate ClusterIssuer requires cluster mode
if self.getParam("mas_issuer_kind") == "ClusterIssuer" and self.mas_admin_mode != "cluster":
self.fatalError(
"\n".join(
[
f"Invalid configuration for admin mode '{self.mas_admin_mode}'",
"DNS integration is not available in this mode.",
"Remove DNS integration option --dns-provider, or switch to --admin-mode cluster and use --mas-issuer-kind ClusterIssuer.",
"Invalid configuration for certificate issuer kind 'ClusterIssuer'",
"ClusterIssuer can only be used when --admin-mode cluster is selected.",
]
)
)

if self.mas_admin_mode == "cluster" and self.getParam("mas_issuer_kind") == "Issuer":
self.fatalError(
"\n".join(
[
"Invalid configuration for certificate issuer kind 'Issuer'",
"DNS integration is not available when --mas-issuer-kind Issuer is selected.",
"Remove DNS integration option --dns-provider, or use --mas-issuer-kind ClusterIssuer.",
]
# Validate DNS integration restrictions
if self.getParam("dns_provider") != "":
if self.mas_admin_mode in ["namespaced", "minimal"]:
self.fatalError(
"\n".join(
[
f"Invalid configuration for admin mode '{self.mas_admin_mode}'",
"DNS integration is not available in this mode.",
"Remove DNS integration option --dns-provider, or switch to --admin-mode cluster.",
]
)
)

if self.mas_admin_mode == "cluster" and self.getParam("mas_issuer_kind") == "Issuer":
self.fatalError(
"\n".join(
[
"Invalid configuration for certificate issuer kind 'Issuer'",
"DNS integration is not available when --mas-issuer-kind Issuer is selected.",
"Remove DNS integration option --dns-provider, or use --mas-issuer-kind ClusterIssuer.",
]
)
)
)
else:
if self.mas_admin_mode != "":
self.fatalError(f"--admin-mode is not supported for MAS version 9.1 and earlier (selected channel: {self.getParam('mas_channel')})")
Expand Down
Loading
Loading