/*************************************************************************
* Copyright 2009-2015 Eucalyptus Systems, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
* Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
* CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
* additional information or have any questions.
************************************************************************/
package com.eucalyptus.auth.euare.persist.entities;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Lob;
import javax.persistence.PersistenceContext;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import org.apache.log4j.Logger;
import org.hibernate.annotations.Type;
import com.eucalyptus.auth.euare.ServerCertificates;
import com.eucalyptus.auth.euare.ServerCertificates.VerifiedCertInfo;
import com.eucalyptus.auth.policy.annotation.PolicyResourceType;
import com.eucalyptus.auth.policy.annotation.PolicyVendor;
import com.eucalyptus.component.id.Euare;
import com.eucalyptus.entities.AbstractOwnedPersistent;
import com.eucalyptus.auth.principal.OwnerFullName;
import com.eucalyptus.auth.type.RestrictedType;
import com.eucalyptus.entities.Entities;
import com.eucalyptus.entities.EntityRestriction;
import com.eucalyptus.entities.TransactionResource;
import com.eucalyptus.upgrade.Upgrades;
import com.eucalyptus.upgrade.Upgrades.EntityUpgrade;
import com.google.common.base.Predicate;
/**
* @author Sang-Min Park
*
*/
@Entity
@PersistenceContext(name = "eucalyptus_auth")
@Table(name = "auth_server_cert", indexes = {
@Index( name = "auth_server_cert_account_id_idx", columnList = "metadata_account_id" ),
@Index( name = "auth_server_cert_display_name_idx", columnList = "metadata_display_name" ),
})
@PolicyVendor( "iam" )
@PolicyResourceType( "server-certificate" )
public class ServerCertificateEntity extends AbstractOwnedPersistent implements RestrictedType {
@Transient
private static final long serialVersionUID = 1L;
@Column(name = "metadata_server_cert_path", nullable = true)
private String certificatePath;
@Column(name = "metadata_server_cert_id", nullable=true)
private String certificateId;
@Lob
@Type(type = "org.hibernate.type.StringClobType")
@Column(name = "metadata_server_cert_body", nullable = true)
private String certificateBody;
@Lob
@Type(type = "org.hibernate.type.StringClobType")
@Column(name = "metadata_server_cert_chain", nullable = true)
private String certificateChain;
@Lob
@Type(type = "org.hibernate.type.StringClobType")
@Column(name = "metadata_server_cert_pk", nullable = true)
private String privateKey;
@Lob
@Type(type = "org.hibernate.type.StringClobType")
@Column(name = "metadata_session_key", nullable = true)
private String sessionKey;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "metadata_server_cert_expiration")
private Date expiration;
@SuppressWarnings("unused")
private ServerCertificateEntity() {
}
private ServerCertificateEntity(final OwnerFullName user){
super(user, null);
}
public ServerCertificateEntity(final OwnerFullName user, final String certName) {
super(user, certName);
}
public static EntityRestriction<ServerCertificateEntity> named(final OwnerFullName user){
return Entities.restriction( ServerCertificateEntity.class )
.equalIfNonNull( ServerCertificateEntity_.ownerAccountNumber, user == null ? null : user.getAccountNumber( ) )
.equalIfNonNull( ServerCertificateEntity_.ownerUserId, user == null ? null : user.getUserId( ) )
.equalIfNonNull( ServerCertificateEntity_.ownerUserName, user == null ? null : user.getUserName( ) )
.build( );
}
public static EntityRestriction<ServerCertificateEntity> named(
final OwnerFullName user,
final String certName
) {
final ServerCertificateEntity entity = new ServerCertificateEntity(user, certName );
return Entities.restriction( ServerCertificateEntity.class )
.equalIfNonNull( ServerCertificateEntity_.ownerAccountNumber, user == null ? null : user.getAccountNumber( ) )
.equalIfNonNull( ServerCertificateEntity_.ownerUserId, user == null ? null : user.getUserId( ) )
.equalIfNonNull( ServerCertificateEntity_.ownerUserName, user == null ? null : user.getUserName( ) )
.equalIfNonNull( ServerCertificateEntity_.displayName, certName )
.equalIfNonNull( ServerCertificateEntity_.uniqueName, entity.createUniqueName( ) )
.build( );
}
public void setCertName(final String certName) {
if(! isCertificateNameValid(certName))
throw new IllegalArgumentException();
this.setDisplayName(certName);
this.setUniqueName(this.createUniqueName());
}
public String getCertName() {
return this.displayName;
}
public String getCertPath() {
return this.certificatePath;
}
public void setCertPath(final String path) throws IllegalArgumentException {
if (path == null)
this.certificatePath = "/";
else
this.certificatePath = path;
if (!isCertificatePathValid(this.certificatePath))
throw new IllegalArgumentException();
}
public void setCertBody(final String body) {
this.certificateBody = body;
}
public String getCertBody() {
return this.certificateBody;
}
public void setCertChain(final String chain) {
this.certificateChain = chain;
}
public String getCertChain() {
return this.certificateChain;
}
public void setPrivateKey(final String pk) {
this.privateKey = pk;
}
public void setSessionKey(final String key) {
this.sessionKey = key;
}
public String getSessionKey() {
return this.sessionKey;
}
public String getPrivateKey() {
return this.privateKey;
}
public void setCertId(final String id){
this.certificateId = id;
}
public String getCertId(){
return this.certificateId;
}
public Date getExpiration( ) {
return expiration;
}
public void setExpiration( final Date expiration ) {
this.expiration = expiration;
}
public static boolean isCertificatePathValid( final String path) {
if (path == null)
return false;
if (!path.startsWith("/"))
return false;
if (path.length() < 1 || path.length() > 512)
return false;
return true;
}
public static boolean isCertificateNameValid(final String name) {
if (name == null)
return false;
// plus (+), equal (=), comma (,), period (.), at (@), and dash (-).
if (!name.matches("[A-Za-z0-9\\+=,\\.@\\-]+"))
return false;
if (name.length() < 1 || name.length() > 128)
return false;
return true;
}
@EntityUpgrade( entities = ServerCertificateEntity.class, since = Upgrades.Version.v4_4_1, value = Euare.class )
public enum ServerCertificateEntityUpgrade441 implements Predicate<Class> {
INSTANCE;
private static Logger logger = Logger.getLogger( ServerCertificateEntityUpgrade441.class );
@SuppressWarnings( "unchecked" )
@Override
public boolean apply( final Class entityClass ) {
try ( final TransactionResource tx = Entities.transactionFor( ServerCertificateEntity.class ) ) {
final List<ServerCertificateEntity> entities = Entities.criteriaQuery( ServerCertificateEntity.class )
.whereRestriction( r -> r.isNull( ServerCertificateEntity_.expiration ) ).list( );
for ( final ServerCertificateEntity entity : entities ) {
final String desc = entity.getCertId( ) + "/" + entity.getCertName( );
logger.info( "Setting expiration for server certificate " + desc );
try {
final VerifiedCertInfo certInfo = ServerCertificates.verifyCertificate(
entity.getCertBody( ),
entity.getCertChain( ) );
entity.setExpiration( certInfo.getExpiration( ) );
} catch ( final Exception e ) {
logger.error( "Error setting expiration for server certificate " + desc, e );
}
}
tx.commit( );
}
return true;
}
}
}