use of com.yahoo.athenz.common.server.log.AuditLogMsgBuilder in project athenz by yahoo.
the class ZTSImpl method deleteInstanceIdentity.
@Override
public InstanceIdentity deleteInstanceIdentity(ResourceContext ctx, String provider, String domain, String service, String instanceId) {
final String caller = "deleteinstanceidentity";
final String callerTiming = "deleteinstanceidentity_timing";
metric.increment(HTTP_POST);
logPrincipal(ctx);
validateRequest(ctx.request(), caller);
validate(provider, TYPE_SERVICE_NAME, caller);
validate(domain, TYPE_DOMAIN_NAME, caller);
validate(service, TYPE_SIMPLE_NAME, caller);
validate(instanceId, TYPE_PATH_ELEMENT, caller);
// for consistent handling of all requests, we're going to convert
// all incoming object values into lower case (e.g. domain, role,
// policy, service, etc name)
provider = provider.toLowerCase();
domain = domain.toLowerCase();
service = service.toLowerCase();
Object timerMetric = metric.startTiming(callerTiming, domain);
metric.increment(HTTP_REQUEST, domain);
metric.increment(caller, domain);
// remove the cert record for this instance
instanceCertManager.deleteX509CertRecord(provider, instanceId);
// create our audit log entry
AuditLogMsgBuilder msgBldr = getAuditLogMsgBuilder(ctx, domain, caller, HTTP_POST);
msgBldr.whatEntity(instanceId);
StringBuilder auditLogDetails = new StringBuilder(512);
auditLogDetails.append("Provider: ").append(provider).append(" Domain: ").append(domain).append(" Service: ").append(service).append(" InstanceId: ").append(instanceId);
msgBldr.whatDetails(auditLogDetails.toString());
auditLogger.log(msgBldr);
metric.stopTiming(timerMetric);
return null;
}
use of com.yahoo.athenz.common.server.log.AuditLogMsgBuilder in project athenz by yahoo.
the class ZTSImpl method getRoleToken.
// Token interface
public RoleToken getRoleToken(ResourceContext ctx, String domainName, String roleName, Integer minExpiryTime, Integer maxExpiryTime, String proxyForPrincipal) {
final String caller = "getroletoken";
final String callerTiming = "getroletoken_timing";
metric.increment(HTTP_GET);
logPrincipal(ctx);
validateRequest(ctx.request(), caller);
validate(domainName, TYPE_DOMAIN_NAME, caller);
if (roleName != null && !roleName.isEmpty()) {
validate(roleName, TYPE_ENTITY_LIST, caller);
}
if (proxyForPrincipal != null && !proxyForPrincipal.isEmpty()) {
validate(proxyForPrincipal, TYPE_ENTITY_NAME, caller);
}
// for consistent handling of all requests, we're going to convert
// all incoming object values into lower case since ZMS Server
// saves all of its object names in lower case
domainName = domainName.toLowerCase();
if (roleName != null) {
roleName = roleName.toLowerCase();
}
if (proxyForPrincipal != null) {
proxyForPrincipal = normalizeDomainAliasUser(proxyForPrincipal.toLowerCase());
}
Object timerMetric = metric.startTiming(callerTiming, domainName);
// get our principal's name
final Principal principal = ((RsrcCtxWrapper) ctx).principal();
String principalName = principal.getFullName();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("getRoleToken(domain: " + domainName + ", principal: " + principalName + ", role-name: " + roleName + ", proxy-for: " + proxyForPrincipal + ")");
}
// do not allow empty (not null) values for role
roleName = convertEmptyStringToNull(roleName);
proxyForPrincipal = convertEmptyStringToNull(proxyForPrincipal);
if (leastPrivilegePrincipal && roleName == null) {
throw requestError("getRoleToken: Client must specify a roleName to request a token for", caller, ZTSConsts.ZTS_UNKNOWN_DOMAIN);
}
if (proxyForPrincipal != null && !isAuthorizedProxyUser(authorizedProxyUsers, principalName)) {
LOGGER.error("getRoleToken: Principal: " + principalName + " not authorized for proxy role token request");
throw forbiddenError("getRoleToken: Principal: " + principalName + " not authorized for proxy role token request", caller, ZTSConsts.ZTS_UNKNOWN_DOMAIN);
}
StringBuilder auditLogDetails = new StringBuilder(512);
auditLogDetails.append("RoleName=").append(roleName);
AuditLogMsgBuilder msgBldr = getAuditLogMsgBuilder(ctx, domainName, caller, HTTP_GET);
msgBldr.when(Timestamp.fromCurrentTime().toString()).whatEntity("RoleToken").why("zts-audit");
// first retrieve our domain data object from the cache
DataCache data = dataStore.getDataCache(domainName);
if (data == null) {
// just increment the request counter without any dimension
// we don't want to get persistent indexes for invalid domains
metric.increment(HTTP_REQUEST, ZTSConsts.ZTS_UNKNOWN_DOMAIN);
metric.increment(caller, ZTSConsts.ZTS_UNKNOWN_DOMAIN);
throw notFoundError("getRoleToken: No such domain: " + domainName, caller, ZTSConsts.ZTS_UNKNOWN_DOMAIN);
}
// update our metric with dimension. we're moving the metric here
// after the domain name has been confirmed as valid since with
// dimensions we get stuck with persistent indexes so we only want
// to create them for valid domain names
metric.increment(HTTP_REQUEST, domainName);
metric.increment(caller, domainName);
// check if the authorized service domain matches to the
// requested domain name
checkRoleTokenAuthorizedServiceRequest(principal, domainName, caller);
// we need to convert our request role name into array since
// it could contain multiple values separated by commas
String[] requestedRoleList = null;
if (roleName != null) {
requestedRoleList = roleName.split(",");
}
// process our request and retrieve the roles for the principal
Set<String> roles = new HashSet<>();
dataStore.getAccessibleRoles(data, domainName, principalName, requestedRoleList, roles, false);
if (roles.isEmpty()) {
throw forbiddenError("getRoleToken: No access to any roles in domain: " + domainName, caller, domainName);
}
// if this is proxy for operation then we want to make sure that
// both principals have access to the same set of roles so we'll
// remove any roles that are authorized by only one of the principals
String proxyUser = null;
if (proxyForPrincipal != null) {
Set<String> rolesForProxy = new HashSet<>();
dataStore.getAccessibleRoles(data, domainName, proxyForPrincipal, requestedRoleList, rolesForProxy, false);
roles.retainAll(rolesForProxy);
if (roles.isEmpty()) {
throw forbiddenError("getRoleToken: No access to any roles by User and Proxy Principals", caller, domainName);
}
// we need to switch our principal and proxy for user
proxyUser = principalName;
principalName = proxyForPrincipal;
}
long tokenTimeout = determineTokenTimeout(minExpiryTime, maxExpiryTime);
List<String> roleList = new ArrayList<>(roles);
boolean domainCompleteRoleSet = (includeRoleCompleteFlag && roleName == null);
com.yahoo.athenz.auth.token.RoleToken token = new com.yahoo.athenz.auth.token.RoleToken.Builder(ZTS_ROLE_TOKEN_VERSION, domainName, roleList).expirationWindow(tokenTimeout).host(serverHostName).keyId(privateKeyId).principal(principalName).ip(ServletRequestUtil.getRemoteAddress(ctx.request())).proxyUser(proxyUser).domainCompleteRoleSet(domainCompleteRoleSet).build();
token.sign(privateKey);
RoleToken roleToken = new RoleToken();
roleToken.setToken(token.getSignedToken());
roleToken.setExpiryTime(token.getExpiryTime());
metric.stopTiming(timerMetric);
return roleToken;
}
use of com.yahoo.athenz.common.server.log.AuditLogMsgBuilder in project athenz by yahoo.
the class DBService method auditLogRequest.
void auditLogRequest(ResourceContext ctx, String domainName, String auditRef, String caller, String operation, String entityName, String auditDetails) {
AuditLogMsgBuilder msgBldr = ZMSUtils.getAuditLogMsgBuilder(ctx, auditLogger, domainName, auditRef, caller, operation);
msgBldr.when(Timestamp.fromCurrentTime().toString()).whatEntity(entityName);
if (auditDetails != null) {
msgBldr.whatDetails(auditDetails);
}
auditLogger.log(msgBldr);
}
use of com.yahoo.athenz.common.server.log.AuditLogMsgBuilder in project athenz by yahoo.
the class ZTSImpl method processProviderSSHRefreshRequest.
InstanceIdentity processProviderSSHRefreshRequest(ResourceContext ctx, final Principal principal, final String domain, final String service, final String provider, final String instanceId, final String sshCsr, X509CertRecord x509CertRecord, final String caller) {
final String principalName = principal.getFullName();
// now we need to make sure the serial number for the certificate
// matches to what we had issued previously. If we have a mismatch
// then we're going to revoke this instance as it has been possibly
// compromised
X509Certificate cert = principal.getX509Certificate();
String serialNumber = cert.getSerialNumber().toString();
if (!x509CertRecord.getCurrentSerial().equals(serialNumber) && !x509CertRecord.getPrevSerial().equals(serialNumber)) {
// we have a mismatch for both current and previous serial
// numbers so we're going to revoke it
LOGGER.error("Revoking certificate refresh for cn: {} instance id: {}," + " current serial: {}, previous serial: {}, cert serial: {}", principalName, x509CertRecord.getInstanceId(), x509CertRecord.getCurrentSerial(), x509CertRecord.getPrevSerial(), serialNumber);
x509CertRecord.setPrevSerial("-1");
x509CertRecord.setCurrentSerial("-1");
instanceCertManager.updateX509CertRecord(x509CertRecord);
throw forbiddenError("Certificate revoked", caller, domain);
}
// generate identity with the ssh certificate
InstanceIdentity identity = new InstanceIdentity().setName(principalName);
if (!instanceCertManager.generateSshIdentity(identity, sshCsr, null)) {
throw serverError("unable to generate ssh identity", caller, domain);
}
// set the other required attributes in the identity object
identity.setProvider(provider);
identity.setInstanceId(instanceId);
// create our audit log entry
AuditLogMsgBuilder msgBldr = getAuditLogMsgBuilder(ctx, domain, caller, HTTP_POST);
msgBldr.whatEntity(instanceId);
StringBuilder auditLogDetails = new StringBuilder(512);
auditLogDetails.append("Provider: ").append(provider).append(" Domain: ").append(domain).append(" Service: ").append(service).append(" InstanceId: ").append(instanceId).append(" Serial: ").append(serialNumber).append(" Type: ssh");
msgBldr.whatDetails(auditLogDetails.toString());
auditLogger.log(msgBldr);
return identity;
}
use of com.yahoo.athenz.common.server.log.AuditLogMsgBuilder in project athenz by yahoo.
the class ZTSImpl method postInstanceRefreshRequest.
@Override
public Identity postInstanceRefreshRequest(ResourceContext ctx, String domain, String service, InstanceRefreshRequest req) {
final String caller = "postinstancerefreshrequest";
final String callerTiming = "postinstancerefreshrequest_timing";
metric.increment(HTTP_POST);
logPrincipal(ctx);
validateRequest(ctx.request(), caller);
validate(domain, TYPE_DOMAIN_NAME, caller);
validate(service, TYPE_SIMPLE_NAME, caller);
validate(req, TYPE_INSTANCE_REFRESH_REQUEST, caller);
// for consistent handling of all requests, we're going to convert
// all incoming object values into lower case (e.g. domain, role,
// policy, service, etc name)
domain = domain.toLowerCase();
service = service.toLowerCase();
Object timerMetric = metric.startTiming(callerTiming, domain);
metric.increment(HTTP_REQUEST, domain);
metric.increment(caller, domain);
// make sure the credentials match to whatever the request is
Principal principal = ((RsrcCtxWrapper) ctx).principal();
String fullServiceName = domain + "." + service;
final String principalName = principal.getFullName();
boolean userRequest = false;
if (!fullServiceName.equals(principalName)) {
try {
userRequest = authorizer.access("update", domain + ":service", principal, null);
} catch (ResourceException ex) {
LOGGER.error("postInstanceRefreshRequest: access check failure for {}: {}", principalName, ex.getMessage());
}
if (!userRequest) {
throw requestError("Principal mismatch: " + fullServiceName + " vs. " + principalName, caller, domain);
}
}
if (userDomain.equalsIgnoreCase(domain)) {
throw requestError("TLS Certificates require ServiceTokens: " + fullServiceName, caller, domain);
}
// determine if this is a refresh or initial request
final Authority authority = principal.getAuthority();
boolean refreshOperation = (!userRequest && (authority instanceof CertificateAuthority));
// retrieve the public key for the request for verification
final String keyId = userRequest || refreshOperation ? req.getKeyId() : principal.getKeyId();
String publicKey = getPublicKey(domain, service, keyId);
if (publicKey == null) {
throw requestError("Unable to retrieve public key for " + fullServiceName + " with key id: " + keyId, caller, domain);
}
// validate that the cn and public key match to the provided details
X509CertRequest x509CertReq = null;
try {
x509CertReq = new X509CertRequest(req.getCsr());
} catch (CryptoException ex) {
throw requestError("Unable to parse PKCS10 certificate request", caller, domain);
}
final PKCS10CertificationRequest certReq = x509CertReq.getCertReq();
if (!ZTSUtils.verifyCertificateRequest(certReq, domain, service, null)) {
throw requestError("Invalid CSR - data mismatch", caller, domain);
}
if (!x509CertReq.comparePublicKeys(publicKey)) {
throw requestError("Invalid CSR - public key mismatch", caller, domain);
}
if (refreshOperation) {
final String ipAddress = ServletRequestUtil.getRemoteAddress(ctx.request());
ServiceX509RefreshRequestStatus status = validateServiceX509RefreshRequest(principal, x509CertReq, ipAddress);
if (status == ServiceX509RefreshRequestStatus.IP_NOT_ALLOWED) {
throw forbiddenError("IP not allowed for refresh: " + ipAddress, caller, domain);
}
if (status != ServiceX509RefreshRequestStatus.SUCCESS) {
throw requestError("Request valiation failed: " + status, caller, domain);
}
}
// generate identity with the certificate
int expiryTime = req.getExpiryTime() != null ? req.getExpiryTime() : 0;
Identity identity = ZTSUtils.generateIdentity(certSigner, req.getCsr(), fullServiceName, null, expiryTime);
if (identity == null) {
throw serverError("Unable to generate identity", caller, domain);
}
// create our audit log entry
AuditLogMsgBuilder msgBldr = getAuditLogMsgBuilder(ctx, domain, caller, HTTP_POST);
msgBldr.whatEntity(fullServiceName);
X509Certificate newCert = Crypto.loadX509Certificate(identity.getCertificate());
StringBuilder auditLogDetails = new StringBuilder(512);
auditLogDetails.append("Provider: ").append(ZTSConsts.ZTS_SERVICE).append(" Domain: ").append(domain).append(" Service: ").append(service).append(" Serial: ").append(newCert.getSerialNumber().toString()).append(" Principal: ").append(principalName).append(" Type: x509");
msgBldr.whatDetails(auditLogDetails.toString());
auditLogger.log(msgBldr);
metric.stopTiming(timerMetric);
return identity;
}
Aggregations