package io.fathom.cloud.identity.api.os.resources;
import io.fathom.cloud.CloudException;
import io.fathom.cloud.identity.api.os.model.Credential;
import io.fathom.cloud.identity.api.os.model.Credentials;
import io.fathom.cloud.identity.api.os.model.WrappedCredential;
import io.fathom.cloud.identity.state.AuthRepository;
import io.fathom.cloud.protobuf.CloudCommons.TokenInfo;
import io.fathom.cloud.protobuf.IdentityModel.AccessId;
import io.fathom.cloud.protobuf.IdentityModel.CredentialData;
import io.fathom.cloud.protobuf.IdentityModel.UserData;
import io.fathom.cloud.state.DuplicateValueException;
import java.security.SecureRandom;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fathomdb.utils.Hex;
import com.google.common.collect.Lists;
import com.google.inject.persist.Transactional;
import com.google.protobuf.ByteString;
@Path("/openstack/identity/v3/users/{userId}/credentials/OS-EC2")
@Transactional
@Produces({ "application/json" })
public class CredentialsResource extends IdentityResourceBase {
private static final Logger log = LoggerFactory.getLogger(CredentialsResource.class);
// Should use identity service instead
@Deprecated
@Inject
AuthRepository authRepository;
@PathParam("userId")
String userId;
@GET
@Produces({ JSON })
public Credentials listEc2Credentials() throws CloudException {
UserData user = getUser(Long.valueOf(userId));
Credentials response = new Credentials();
response.credentials = Lists.newArrayList();
log.warn("TODO: EC2 credential enumeration is terrible");
for (CredentialData data : authRepository.getEc2Credentials().list()) {
if (data.getUserId() != user.getId()) {
continue;
}
Credential c = toModel(data);
response.credentials.add(c);
}
return response;
}
static final SecureRandom secureRandom = new SecureRandom();
@POST
@Produces({ JSON })
public WrappedCredential createEc2Credential() throws CloudException, DuplicateValueException {
UserData forUser = getUser(Long.valueOf(userId));
WrappedCredential response = new WrappedCredential();
TokenInfo tokenInfo = findTokenInfo();
if (tokenInfo == null) {
throw new WebApplicationException(Status.UNAUTHORIZED);
}
long projectId = tokenInfo.getProjectId();
if (projectId == 0) {
throw new WebApplicationException(Status.UNAUTHORIZED);
}
String accessId;
ByteString secret;
{
byte[] r = new byte[16];
synchronized (secureRandom) {
secureRandom.nextBytes(r);
}
secret = ByteString.copyFrom(r);
}
{
AccessId.Builder b = AccessId.newBuilder();
b.setUserId(forUser.getId());
byte[] r = new byte[8];
synchronized (secureRandom) {
// We don't technically need secure random here, but we want it
// later!
secureRandom.nextBytes(r);
}
b.setPadding(ByteString.copyFrom(r));
accessId = Hex.toHex(b.build().toByteArray());
}
CredentialData created;
{
CredentialData.Builder b = CredentialData.newBuilder();
b.setUserId(forUser.getId());
b.setProjectId(projectId);
b.setKey(accessId);
b.setDeprecatedSharedSecret(secret);
created = authRepository.getEc2Credentials().create(b);
}
response.credential = toModel(created);
return response;
}
private Credential toModel(CredentialData data) {
Credential c = new Credential();
c.secret = Hex.toHex(data.getDeprecatedSharedSecret().toByteArray());
c.access = data.getKey();
c.userId = "" + data.getUserId();
c.tenantId = "" + data.getProjectId();
return c;
}
}