package com.sequenceiq.cloudbreak.cloud.azure.task.interactivelogin;
import static com.sequenceiq.cloudbreak.cloud.azure.task.interactivelogin.AzureInteractiveLoginStatusCheckerTask.AZURE_MANAGEMENT;
import java.io.IOException;
import java.util.UUID;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonObject;
/**
* Created by perdos on 10/18/16.
*/
@Service
public class AzureRoleManager {
private static final Logger LOGGER = LoggerFactory.getLogger(AzureRoleManager.class);
private static final String OWNER_ROLE = "Owner";
@Retryable(value = InteractiveLoginException.class, maxAttempts = 15, backoff = @Backoff(delay = 1000))
public void assignRole(String accessToken, String subscriptionId, String principalObjectId) throws InteractiveLoginException {
String ownerRoleNameRoleIdPair = getOwnerRoleDefinitionId(subscriptionId, accessToken);
assignRole(accessToken, subscriptionId, ownerRoleNameRoleIdPair, principalObjectId);
}
private String getOwnerRoleDefinitionId(String subscriptionId, String accessToken) throws InteractiveLoginException {
Response response = getOwnerRole(subscriptionId, accessToken);
if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) {
String roles = response.readEntity(String.class);
try {
JsonNode rolesJsonNode = new ObjectMapper().readTree(roles);
String roleDefinitionId = rolesJsonNode.get("value").get(0).get("id").asText();
LOGGER.info("Role definition - roleId: " + roleDefinitionId);
return roleDefinitionId;
} catch (IOException e) {
throw new IllegalStateException(e);
}
} else {
if (Response.Status.FORBIDDEN.getStatusCode() == response.getStatus()) {
throw new InteractiveLoginException("You have no permission to access Active Directory roles, please contact with your administrator");
} else {
String errorResponse = response.readEntity(String.class);
LOGGER.error("get owner role definition id failed: " + errorResponse);
try {
String errorMessage = new ObjectMapper().readTree(errorResponse).get("error").get("message").asText();
throw new InteractiveLoginException("Get 'Owner' role name and definition id request error: " + errorMessage);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}
}
private Response getOwnerRole(String subscriptionId, String accessToken) {
Client client = ClientBuilder.newClient();
WebTarget resource = client.target(AZURE_MANAGEMENT);
Invocation.Builder request = resource.path("subscriptions/" + subscriptionId + "/providers/Microsoft.Authorization/roleDefinitions")
.queryParam("$filter", "roleName%20eq%20'" + OWNER_ROLE + "'")
.queryParam("api-version", "2015-07-01")
.request();
request.accept(MediaType.APPLICATION_JSON);
request.header("Authorization", "Bearer " + accessToken);
return request.get();
}
private void assignRole(String accessToken, String subscriptionId, String roleDefinitionId, String principalObjectId) throws InteractiveLoginException {
Client client = ClientBuilder.newClient();
WebTarget resource = client.target(AZURE_MANAGEMENT);
Invocation.Builder request = resource.path("subscriptions/" + subscriptionId + "/providers/Microsoft.Authorization/roleAssignments/"
+ UUID.randomUUID().toString()).queryParam("api-version", "2015-07-01").request();
request.accept(MediaType.APPLICATION_JSON);
request.header("Authorization", "Bearer " + accessToken);
JsonObject properties = new JsonObject();
properties.addProperty("roleDefinitionId", roleDefinitionId);
properties.addProperty("principalId", principalObjectId);
JsonObject jsonObject = new JsonObject();
jsonObject.add("properties", properties);
Response response = request.put(Entity.entity(jsonObject.toString(), MediaType.APPLICATION_JSON));
if (response.getStatusInfo().getFamily() != Response.Status.Family.SUCCESSFUL) {
throw new InteractiveLoginException("Assign role request error - status code: " + response.getStatus()
+ " - error message: " + response.readEntity(String.class));
} else {
LOGGER.info("Role assigned successfully");
}
}
}