diff --git a/plugins/core/jetbrains-community/resources/telemetryOverride.json b/plugins/core/jetbrains-community/resources/telemetryOverride.json index 053a73d6df8..d83f6448bd5 100644 --- a/plugins/core/jetbrains-community/resources/telemetryOverride.json +++ b/plugins/core/jetbrains-community/resources/telemetryOverride.json @@ -755,25 +755,6 @@ ], "passive": true }, - { - "name": "auth_userState", - "description": "The state of the user's authentication.", - "metadata": [ - { - "type": "source", - "required": true - }, - { - "type": "authStatus", - "required": true - }, - { - "type": "authEnabledConnections", - "required": true - } - ], - "passive": true - }, { "name": "webview_amazonqSignInOpened", "description": "Called when a Amazon Q sign in webview is opened.", diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt index 23730e6ef45..c7983d36b33 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/GettingStartedAuthUtils.kt @@ -16,6 +16,7 @@ import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection import software.aws.toolkits.jetbrains.core.credentials.reauthConnectionIfNeeded import software.aws.toolkits.jetbrains.core.credentials.sono.Q_SCOPES import software.aws.toolkits.jetbrains.core.gettingstarted.editor.SourceOfEntry +import software.aws.toolkits.jetbrains.core.gettingstarted.editor.getAuthScopes import software.aws.toolkits.jetbrains.core.gettingstarted.editor.getAuthStatus import software.aws.toolkits.jetbrains.core.gettingstarted.editor.getConnectionCount import software.aws.toolkits.jetbrains.core.gettingstarted.editor.getEnabledConnections @@ -238,10 +239,10 @@ fun reauthenticateWithQ(project: Project) { fun emitUserState(project: Project) { AuthTelemetry.userState( project, - source = getStartupState().toString(), authEnabledConnections = getEnabledConnections(project), + authScopes = getAuthScopes(project), authStatus = getAuthStatus(project), - passive = true + source = getStartupState().toString() ) } diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanelUtils.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanelUtils.kt index 78b9525bd63..34d545f7971 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanelUtils.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedPanelUtils.kt @@ -6,6 +6,7 @@ package software.aws.toolkits.jetbrains.core.gettingstarted.editor import com.intellij.openapi.project.Project import com.intellij.ui.dsl.builder.Panel import software.aws.toolkits.core.credentials.CredentialIdentifier +import software.aws.toolkits.core.credentials.CredentialType import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection import software.aws.toolkits.jetbrains.core.credentials.AwsConnectionManager import software.aws.toolkits.jetbrains.core.credentials.ConnectionState @@ -115,6 +116,20 @@ fun checkIamConnectionValidity(project: Project): ActiveConnection { } } +fun checkIamProfileByCredentialType(project: Project): ActiveConnection { + val currConn = AwsConnectionManager.getInstance(project).selectedCredentialIdentifier ?: return ActiveConnection.NotConnected + val invalidConnection = AwsConnectionManager.getInstance(project).connectionState.let { it.isTerminal && it !is ConnectionState.ValidConnection } + val connectionType = when (currConn.credentialType) { + CredentialType.SsoProfile -> ActiveConnectionType.IAM_IDC + else -> ActiveConnectionType.IAM + } + return if (invalidConnection) { + ActiveConnection.ExpiredIam(connectionType = connectionType, activeConnectionIam = currConn) + } else { + ActiveConnection.ValidIam(connectionType = connectionType, activeConnectionIam = currConn) + } +} + /** * Finds the first valid [ActiveConnection] and returns it. * @@ -146,6 +161,7 @@ fun checkConnectionValidity(project: Project): ActiveConnection { return result } +@Deprecated("Does not work for current config file setup. Old versions still utilize this logic.") fun isCredentialSso(providerId: String): ActiveConnectionType { val profileName = providerId.split("-").first() val ssoSessionIds = CredentialManager.getInstance().getSsoSessionIdentifiers().map { diff --git a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedTelemetryUtils.kt b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedTelemetryUtils.kt index 858cac5c9aa..99ea1207ee9 100644 --- a/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedTelemetryUtils.kt +++ b/plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/gettingstarted/editor/GettingStartedTelemetryUtils.kt @@ -10,6 +10,7 @@ import software.aws.toolkits.core.utils.tryOrNull import software.aws.toolkits.jetbrains.core.credentials.CredentialManager import software.aws.toolkits.jetbrains.core.credentials.ToolkitAuthManager import software.aws.toolkits.jetbrains.core.credentials.profiles.ProfileCredentialsIdentifierSso +import software.aws.toolkits.jetbrains.core.credentials.sono.IDENTITY_CENTER_ROLE_ACCESS_SCOPE import software.aws.toolkits.jetbrains.settings.AwsSettings import software.aws.toolkits.telemetry.AuthStatus import software.aws.toolkits.telemetry.StartUpState @@ -22,54 +23,66 @@ fun getConnectionCount(): Long { fun getEnabledConnectionsForTelemetry(project: Project?): Set { project ?: return emptySet() - val enabledConnections = mutableSetOf() - - val explorerConnection = checkIamConnectionValidity(project) - if (explorerConnection !is ActiveConnection.NotConnected) { - if (explorerConnection.connectionType == ActiveConnectionType.IAM_IDC) { - enabledConnections.add(AuthFormId.IDENTITYCENTER_EXPLORER) - } else { - enabledConnections.add( - AuthFormId.IAMCREDENTIALS_EXPLORER - ) - } - } - val codeCatalystConnection = checkBearerConnectionValidity(project, BearerTokenFeatureSet.CODECATALYST) - if (codeCatalystConnection !is ActiveConnection.NotConnected) { - if (codeCatalystConnection.connectionType == ActiveConnectionType.IAM_IDC) { - enabledConnections.add(AuthFormId.IDENTITYCENTER_CODECATALYST) - } else { - enabledConnections.add(AuthFormId.BUILDERID_CODECATALYST) - } - } + val enabledConnections = mutableSetOf() - val codeWhispererConnection = checkBearerConnectionValidity(project, BearerTokenFeatureSet.CODEWHISPERER) - if (codeWhispererConnection !is ActiveConnection.NotConnected) { - if (codeWhispererConnection.connectionType == ActiveConnectionType.IAM_IDC) { - enabledConnections.add(AuthFormId.IDENTITYCENTER_CODEWHISPERER) - } else { - enabledConnections.add( - AuthFormId.BUILDERID_CODEWHISPERER - ) - } - } + addConnectionInfoToSet( + checkIamConnectionValidity(project), + enabledConnections, + AuthFormId.IDENTITYCENTER_EXPLORER, + AuthFormId.IAMCREDENTIALS_EXPLORER + ) - val qConnection = checkBearerConnectionValidity(project, BearerTokenFeatureSet.Q) - if (qConnection !is ActiveConnection.NotConnected) { - if (qConnection.connectionType == ActiveConnectionType.IAM_IDC) { - enabledConnections.add(AuthFormId.IDENTITYCENTER_Q) - } else { - enabledConnections.add( - AuthFormId.BUILDERID_Q - ) - } - } - return enabledConnections + addConnectionInfoToSet( + checkBearerConnectionValidity(project, BearerTokenFeatureSet.CODECATALYST), + enabledConnections, + AuthFormId.IDENTITYCENTER_CODECATALYST, + AuthFormId.BUILDERID_CODECATALYST + ) + + addConnectionInfoToSet( + checkBearerConnectionValidity(project, BearerTokenFeatureSet.CODEWHISPERER), + enabledConnections, + AuthFormId.IDENTITYCENTER_CODEWHISPERER, + AuthFormId.BUILDERID_CODEWHISPERER + ) + + addConnectionInfoToSet( + checkBearerConnectionValidity(project, BearerTokenFeatureSet.Q), + enabledConnections, + AuthFormId.IDENTITYCENTER_Q, + AuthFormId.BUILDERID_Q + ) + return enabledConnections.mapTo(mutableSetOf()) { it as AuthFormId } } fun getEnabledConnections(project: Project?): String = getEnabledConnectionsForTelemetry(project).joinToString(",") +fun getAuthScopesForTelemetry(project: Project?): Set { + project ?: return emptySet() + val scopes = mutableSetOf() + + val explorerConnection = checkIamProfileByCredentialType(project) + if (explorerConnection !is ActiveConnection.NotConnected && explorerConnection.connectionType == ActiveConnectionType.IAM_IDC) { + scopes.add(IDENTITY_CENTER_ROLE_ACCESS_SCOPE) + } + + addConnectionInfoToSet( + checkBearerConnectionValidity(project, BearerTokenFeatureSet.CODECATALYST), + dataSet = scopes + ) + + addConnectionInfoToSet( + checkBearerConnectionValidity(project, BearerTokenFeatureSet.Q), + dataSet = scopes + ) + + return scopes.mapTo(mutableSetOf()) { it as String } +} + +fun getAuthScopes(project: Project?): String = + getAuthScopesForTelemetry(project).joinToString(",") + fun getStartupState(): StartUpState { val hasStartedToolkitBefore = tryOrNull { getPersistentStateComponentStorageLocation(AwsSettings::class.java)?.exists() @@ -87,6 +100,38 @@ fun getAuthStatus(project: Project) = when (checkConnectionValidity(project)) { else -> AuthStatus.NotConnected } +fun addConnectionInfoToSet( + activeConnection: ActiveConnection, + dataSet: MutableSet, + idcConnection: AuthFormId? = null, + defaultConnection: AuthFormId? = null, +) { + if (activeConnection is ActiveConnection.NotConnected) { + return + } + + // add enabled connections + when (activeConnection.connectionType) { + ActiveConnectionType.IAM_IDC -> { + idcConnection ?.let { + dataSet.add(idcConnection) + return + } + } else -> { + defaultConnection?.let { + dataSet.add(defaultConnection) + return + } + } + } + + // add scopes + val connectionScopes = activeConnection.activeConnectionBearer?.scopes + if (!connectionScopes.isNullOrEmpty()) { + dataSet.addAll(connectionScopes) + } +} + enum class AuthFormId { IAMCREDENTIALS_EXPLORER, IDENTITYCENTER_EXPLORER,