Require confirm when users need to grant permission to identity
This commit is contained in:
Родитель
35d5e96e90
Коммит
e85e9d1637
|
@ -5,9 +5,6 @@
|
|||
|
||||
package com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.webappconfig;
|
||||
|
||||
import com.azure.core.management.profile.AzureProfile;
|
||||
import com.azure.resourcemanager.authorization.models.BuiltInRole;
|
||||
import com.azure.resourcemanager.authorization.models.RoleAssignment;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.microsoft.azure.toolkit.ide.appservice.AppServiceActionsContributor;
|
||||
|
@ -67,6 +64,7 @@ import java.util.stream.Collectors;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
import static com.microsoft.azure.toolkit.intellij.common.AzureBundle.message;
|
||||
import static com.microsoft.azure.toolkit.intellij.connector.IManagedIdentitySupported.*;
|
||||
|
||||
public class WebAppRunState extends AzureRunProfileState<WebAppBase<?, ?, ?>> {
|
||||
private static final String LIBS_ROOT = "/home/site/wwwroot/libs/";
|
||||
|
@ -132,16 +130,16 @@ public class WebAppRunState extends AzureRunProfileState<WebAppBase<?, ?, ?>> {
|
|||
final AbstractAzResource<?,?,?> data = (AbstractAzResource<?,?,?>) resource.getData();
|
||||
final String identity = con.getAuthenticationType() == AuthenticationType.SYSTEM_ASSIGNED_MANAGED_IDENTITY ?
|
||||
configuration.getPrincipalId() : Objects.requireNonNull(con.getUserAssignedManagedIdentity()).getData().getPrincipalId();
|
||||
final List<String> roles = data.getRoleAssignments(identity).stream().map(RoleAssignment::roleDefinitionId).toList();
|
||||
try {
|
||||
definition.getBuiltInRoles().forEach((id, role) -> {
|
||||
if (roles.stream().noneMatch(r -> r.endsWith(id))) {
|
||||
AzureMessager.getMessager().info(String.format("Assign role %s to identity %s...", role, identity));
|
||||
data.grantPermissionToIdentity(identity, role);
|
||||
}
|
||||
});
|
||||
} catch (final RuntimeException e) {
|
||||
AzureMessager.getMessager().warning(String.format("Failed to grant permission to identity %s, please try assign correct role to it in portal", identity), e);
|
||||
final String identityName = con.getAuthenticationType() == AuthenticationType.SYSTEM_ASSIGNED_MANAGED_IDENTITY ?
|
||||
target instanceof AzResource ? ((AzResource)target).getName() : target.toString() :
|
||||
Objects.requireNonNull(con.getUserAssignedManagedIdentity()).getData().getName();
|
||||
if (resource instanceof AzureServiceResource<?> serviceResource && !checkPermission(serviceResource, identity)) {
|
||||
if (!IManagedIdentitySupported.grantPermission(serviceResource, identity)) {
|
||||
final String message = String.format("The managed identity %s (%s) doesn't have enough permission to access resource %s.", identity, identityName, resource.getName());
|
||||
final Action<?> openIdentityConfigurationAction = getOpenIdentityConfigurationAction(serviceResource);
|
||||
final Action<?> grantPermissionAction = getGrantPermissionAction(serviceResource, identity);
|
||||
AzureMessager.getMessager().warning(message, openIdentityConfigurationAction, grantPermissionAction);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager;
|
|||
import com.microsoft.azure.toolkit.lib.common.model.AbstractAzResource;
|
||||
import com.microsoft.azure.toolkit.lib.common.model.AzResource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -21,12 +22,14 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Interfaced to indicate that the resource supports managed identity
|
||||
* <p>
|
||||
*/
|
||||
public interface IManagedIdentitySupported<T extends AzResource> {
|
||||
String FAILED_TO_ASSIGN_MESSAGE = "Failed to grant permission to identity <a href=\"%s\">%s</a>, %s, please try assign correct role to it in portal";
|
||||
|
||||
// check whether identity is connected to resource with full permission
|
||||
|
||||
|
@ -53,28 +56,42 @@ public interface IManagedIdentitySupported<T extends AzResource> {
|
|||
return AzureActionManager.getInstance().getAction(ResourceCommonActionsContributor.OPEN_URL).bind(url).withLabel("Open IAM Configuration");
|
||||
}
|
||||
|
||||
public static boolean grantPermission(@Nonnull AzureServiceResource<?> data, @Nonnull String identity) {
|
||||
final AzureServiceResource.Definition<?> d = data.getDefinition();
|
||||
final AzResource r = data.getData();
|
||||
if (d instanceof IManagedIdentitySupported<?> definition && MapUtils.isNotEmpty(definition.getBuiltInRoles()) && r instanceof AbstractAzResource<?, ?, ?> resource) {
|
||||
final Map<String, BuiltInRole> builtInRoles = definition.getBuiltInRoles();
|
||||
final List<String> roles = resource.getRoleAssignments(identity).stream().map(RoleAssignment::roleDefinitionId).toList();
|
||||
final String rolesStr = builtInRoles.values().stream().map(BuiltInRole::toString).collect(Collectors.joining(","));
|
||||
final boolean assignRole = AzureMessager.getDefaultMessager().confirm(String.format("Do you want to assign roles (%s) to identity (%s)?", rolesStr, identity), "Assign Required Roles");
|
||||
if (assignRole) {
|
||||
try {
|
||||
Objects.requireNonNull(definition.getBuiltInRoles()).forEach((id, role) -> {
|
||||
if (roles.stream().noneMatch(ro -> ro.endsWith(id))) {
|
||||
AzureMessager.getMessager().info(String.format("Assigning role (%s) to identity (%s)...", role, identity));
|
||||
resource.grantPermissionToIdentity(identity, role);
|
||||
}
|
||||
});
|
||||
AzureMessager.getMessager().info(String.format("Roles (%s) have been assigned to identity (%s)?", rolesStr, identity));
|
||||
return true;
|
||||
} catch (final RuntimeException e) {
|
||||
final String errorMessage = String.format(FAILED_TO_ASSIGN_MESSAGE, resource.getPortalUrl(), identity, e.getMessage());
|
||||
AzureMessager.getMessager().warning(errorMessage, getOpenIdentityConfigurationAction(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Action<?> getGrantPermissionAction(@Nonnull AzureServiceResource<?> data, @Nonnull String identity) {
|
||||
final AzureServiceResource.Definition<?> d = data.getDefinition();
|
||||
final AzResource r = data.getData();
|
||||
if (d instanceof IManagedIdentitySupported<?> definition && r instanceof AbstractAzResource<?, ?, ?> resource) {
|
||||
if (d instanceof IManagedIdentitySupported<?> definition && MapUtils.isNotEmpty(definition.getBuiltInRoles()) && r instanceof AbstractAzResource<?, ?, ?> resource) {
|
||||
return new Action<>(Action.Id.of("user/common.assign_role.identity"))
|
||||
.withLabel("Assign Required Roles")
|
||||
.withIdParam(identity)
|
||||
.withHandler(ignore -> {
|
||||
final Map<String, BuiltInRole> builtInRoles = definition.getBuiltInRoles();
|
||||
final List<String> roles = resource.getRoleAssignments(identity).stream().map(RoleAssignment::roleDefinitionId).toList();
|
||||
try {
|
||||
Objects.requireNonNull(definition.getBuiltInRoles()).forEach((id, role) -> {
|
||||
if (roles.stream().noneMatch(ro -> ro.endsWith(id))) {
|
||||
AzureMessager.getMessager().info(String.format("Assign role %s to identity %s...", role, identity));
|
||||
resource.grantPermissionToIdentity(identity, role);
|
||||
}
|
||||
});
|
||||
} catch (final RuntimeException e) {
|
||||
AzureMessager.getMessager().warning(String.format("Failed to grant permission to identity %s, please try assign correct role to it in portal", identity), e);
|
||||
}
|
||||
});
|
||||
.withHandler(ignore -> grantPermission(data, identity));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -9,16 +9,17 @@ import com.intellij.openapi.application.ApplicationManager;
|
|||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.microsoft.azure.toolkit.intellij.connector.Connection;
|
||||
import com.microsoft.azure.toolkit.intellij.connector.ConnectionTopics;
|
||||
import com.microsoft.azure.toolkit.intellij.connector.DeploymentTargetTopics;
|
||||
import com.microsoft.azure.toolkit.intellij.connector.*;
|
||||
import com.microsoft.azure.toolkit.intellij.facet.AzureFacet;
|
||||
import com.microsoft.azure.toolkit.lib.common.action.Action;
|
||||
import com.microsoft.azure.toolkit.lib.common.bundle.AzureString;
|
||||
import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException;
|
||||
import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager;
|
||||
import com.microsoft.azure.toolkit.lib.common.model.AbstractAzResource;
|
||||
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation;
|
||||
import com.microsoft.azure.toolkit.lib.common.operation.OperationBundle;
|
||||
import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager;
|
||||
import com.microsoft.azure.toolkit.lib.identities.Identity;
|
||||
import io.github.cdimascio.dotenv.internal.DotenvParser;
|
||||
import io.github.cdimascio.dotenv.internal.DotenvReader;
|
||||
import lombok.Getter;
|
||||
|
@ -33,20 +34,17 @@ import java.io.IOException;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.microsoft.azure.toolkit.intellij.connector.ConnectionTopics.CONNECTION_CHANGED;
|
||||
import static com.microsoft.azure.toolkit.intellij.connector.IManagedIdentitySupported.*;
|
||||
import static com.microsoft.azure.toolkit.intellij.connector.dotazure.AzureModule.DOT_ENV;
|
||||
|
||||
@Getter
|
||||
public class Profile {
|
||||
public static final String NO_PERMISSION_MESSAGE = "The managed identity <a href=\"%s\">%s</a> (%s) doesn't have enough permission to access resource %s.";
|
||||
@Nonnull
|
||||
private final String name;
|
||||
@Nonnull
|
||||
|
@ -98,9 +96,23 @@ public class Profile {
|
|||
|
||||
public synchronized Future<?> addConnection(@Nonnull Connection<?, ?> connection) {
|
||||
AzureFacet.addTo(this.module.getModule());
|
||||
this.resourceManager.addResource(connection.getResource());
|
||||
final Resource<?> resource = connection.getResource();
|
||||
this.resourceManager.addResource(resource);
|
||||
this.connectionManager.addConnection(connection);
|
||||
Optional.ofNullable(connection.getUserAssignedManagedIdentity()).ifPresent(this.resourceManager::addResource);
|
||||
// handle user assigned managed identity
|
||||
final Resource<Identity> identityResource = connection.getUserAssignedManagedIdentity();
|
||||
if (Objects.nonNull(identityResource)) {
|
||||
this.resourceManager.addResource(identityResource);
|
||||
AzureTaskManager.getInstance().runInBackground("Validating connection", () -> {
|
||||
final String identity = identityResource.getData().getPrincipalId();
|
||||
if (resource instanceof AzureServiceResource<?> serviceResource && !checkPermission(serviceResource, identity)) {
|
||||
final String message = String.format(NO_PERMISSION_MESSAGE, identityResource.getData().getPortalUrl(), identityResource.getName(),identityResource.getData().getPrincipalId(), resource.getName());
|
||||
final Action<?> openIdentityConfigurationAction = getOpenIdentityConfigurationAction(serviceResource);
|
||||
final Action<?> grantPermissionAction = getGrantPermissionAction(serviceResource, identity);
|
||||
AzureMessager.getMessager().warning(message, grantPermissionAction, openIdentityConfigurationAction);
|
||||
}
|
||||
});
|
||||
}
|
||||
return this.addConnectionToDotEnv(connection);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче