1
/*******************************************************************************
2
*Copyright (c) 2009 Eucalyptus Systems, Inc.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation, only version 3 of the License.
9
* This file is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* You should have received a copy of the GNU General Public License along
15
* with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Please contact Eucalyptus Systems, Inc., 130 Castilian
18
* Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
19
* if you need additional information or have any questions.
21
* This file may incorporate work covered under the following copyright and
24
* Software License Agreement (BSD License)
26
* Copyright (c) 2008, Regents of the University of California
27
* All rights reserved.
29
* Redistribution and use of this software in source and binary forms, with
30
* or without modification, are permitted provided that the following
33
* Redistributions of source code must retain the above copyright notice,
34
* this list of conditions and the following disclaimer.
36
* Redistributions in binary form must reproduce the above copyright
37
* notice, this list of conditions and the following disclaimer in the
38
* documentation and/or other materials provided with the distribution.
40
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
41
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
42
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
44
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
46
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
48
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
51
* THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
52
* LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
53
* SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
54
* IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
55
* BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
56
* THE REGENTSā DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
57
* OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
58
* WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
59
* ANY SUCH LICENSES OR RIGHTS.
60
*******************************************************************************
61
* Author: chris grzegorczyk <grze@eucalyptus.com>
63
package com.eucalyptus.auth
65
import java.io.Serializable;
66
import java.security.cert.X509Certificate;
67
import java.util.Date;
68
import java.util.List;
69
import java.util.ArrayList;
71
import org.bouncycastle.util.encoders.UrlBase64;
72
import javax.persistence.Entity;
73
import javax.persistence.Id;
74
import javax.persistence.Transient;
75
import org.hibernate.annotations.Cache
76
import org.hibernate.annotations.CacheConcurrencyStrategy
77
import org.hibernate.annotations.GenericGenerator
79
import javax.persistence.MappedSuperclass;
80
import javax.persistence.Table
81
import javax.persistence.GeneratedValue
82
import javax.persistence.Column
83
import javax.persistence.Lob
84
import javax.persistence.OneToMany
85
import javax.persistence.OneToOne
86
import javax.persistence.FetchType
87
import javax.persistence.CascadeType
88
import javax.persistence.JoinTable
89
import javax.persistence.JoinColumn
90
import javax.persistence.Version;
91
import javax.persistence.Temporal;
92
import javax.persistence.TemporalType;
93
import javax.persistence.Version;
94
import javax.persistence.PersistenceContext;
96
import org.hibernate.sql.Alias
97
import org.apache.log4j.Logger
99
import com.google.common.collect.Lists;
100
import com.eucalyptus.auth.principal.User;
101
import com.eucalyptus.auth.util.B64;
102
import com.eucalyptus.auth.util.PEMFiles;
103
import com.eucalyptus.entities.AbstractPersistent;
106
@PersistenceContext(name="eucalyptus_auth")
107
@Table( name = "auth_users" )
108
@Cache( usage = CacheConcurrencyStrategy.READ_WRITE )
109
public class UserEntity extends AbstractPersistent implements Serializable, User {
111
private static Logger LOG = Logger.getLogger( UserEntity.class );
113
@Column( name = "auth_user_name", unique=true )
116
@Column( name = "auth_user_query_id" )
119
@Column( name = "auth_user_secretkey" )
122
@Column( name = "auth_user_password" )
125
@Column( name = "auth_user_is_admin" )
126
Boolean administrator;
128
@Column( name = "auth_user_is_enabled" )
131
@Column( name = "auth_user_token" )
134
@OneToMany( cascade=[CascadeType.ALL], fetch=FetchType.EAGER )
135
@JoinTable(name = "auth_user_has_x509", joinColumns = [ @JoinColumn( name = "auth_user_id" ) ],inverseJoinColumns = [ @JoinColumn( name = "auth_x509_id" ) ])
136
@Cache( usage = CacheConcurrencyStrategy.READ_WRITE )
137
List<X509Cert> certificates = [];
140
List<String> eucaGroupIds = [];
145
public User getDelegate( ) {
149
public UserEntity( String userName ){
153
public UserEntity( String userName, Boolean enabled ){
155
this.setEnabled( enabled );
158
public void revokeX509Certificate() {
159
for( X509Cert cert : this.getCertificates() ) {
160
cert.setRevoked(true);
162
LOG.debug("Current certificate for ${this.getName()}: ${this.getX509Certificate()?.getSerialNumber()}");
165
public void revokeSecretKey() {
166
this.setSecretKey( null );
169
public List<X509Certificate> getAllX509Certificates() {
170
List<X509Certificate> certs = Lists.newArrayList( );
171
for( X509Cert c : this.getCertificates() ) {
172
certs.add( X509Cert.toCertificate( c ) );
177
public X509Certificate getX509Certificate() {
178
for( X509Cert cert : this.getCertificates() ) {
179
if( !cert.getRevoked( ) ) {
180
return X509Cert.toCertificate( cert );
186
public boolean checkToken( String token ) {
187
return this.getToken( ).equals( token )
190
public void setX509Certificate( X509Certificate x509 ) {
191
LOG.debug( "Setting new user certificate: " + x509.getSubjectX500Principal( ) + " " + x509.getSerialNumber( ) );
192
this.getCertificates( ).add( X509Cert.fromCertificate( x509 ) );
194
public Boolean isEnabled() {
197
public Boolean isAdministrator() {
198
return administrator;
200
public BigInteger getNumber() {
201
return new BigInteger( this.getId(), 16 );
204
public int hashCode( ) {
205
final int prime = 31;
207
result = prime * result + ( ( name == null ) ? 0 : name.hashCode( ) );
211
public boolean equals( Object obj ) {
212
if ( this.is( obj ) ) return true;
213
if ( getClass( ).is( obj.getClass( ) ) ) return false;
214
User other = ( User ) obj;
215
if ( name == null ) {
216
if ( other.name != null ) return false;
217
} else if ( !name.equals( other.name ) ) return false;
220
public String toString( ) {
221
StringBuilder sb = new StringBuilder( );
222
sb.append( "UserEntity [ ");
223
sb.append( "administrator = ").append( administrator == null ? "null" : administrator ).append( ", " );
224
sb.append( "enabled = ").append( enabled == null ? "null" : enabled ).append( ", " );
225
sb.append( "name = ").append( name == null ? "null" : name ).append( ", " );
226
sb.append( "password = ").append( password == null ? "null" : password ).append( ", " );
227
sb.append( "queryId = ").append( queryId == null ? "null" : queryId ).append( ", " );
228
sb.append( "secretKey = ").append( secretKey == null ? "null" : secretKey ).append( ", " );
229
sb.append( "token = ").append( token == null ? "null" : token ).append( ", " );
230
sb.append( "certificates = ");
231
for ( X509Cert certificate : getCertificates( ) ) {
232
sb.append( certificate.toString( ) ).append( ", " );
234
sb.append( "eucaGroupIds = " );
235
for ( String id : eucaGroupIds ) {
236
sb.append( id ).append( ", ");
243
@PersistenceContext(name="eucalyptus_auth")
244
@Table(name="auth_x509")
245
@Cache( usage = CacheConcurrencyStrategy.READ_WRITE )
246
public class X509Cert extends AbstractPersistent implements Serializable {
247
@Column( name = "auth_x509_alias", unique=true )
249
@Column( name = "auth_x509_revoked" )
252
@Column( name = "auth_x509_pem_certificate" )
253
String pemCertificate
256
public X509Cert( String alias ) {
259
public Boolean isRevoked( ) {
262
public static X509Cert fromCertificate(X509Certificate x509) {
263
X509Cert x = new X509Cert( );
264
x.setAlias(x509.getSerialNumber( ).toString());
265
x.setPemCertificate( B64.url.encString( PEMFiles.getBytes( x509 ) ) );
268
public static X509Certificate toCertificate(X509Cert x509) {
269
return PEMFiles.getCert( B64.url.dec( x509.getPemCertificate( ) ) );
273
public int hashCode( ) {
274
final int prime = 31;
276
result = prime * result + ( ( alias == null ) ? 0 : alias.hashCode( ) );
280
public boolean equals( Object obj ) {
281
if ( this.is( obj ) ) return true;
282
if ( !getClass( ).equals( obj.getClass( ) ) ) return false;
283
X509Cert other = ( X509Cert ) obj;
284
if ( alias == null ) {
285
if ( other.alias != null ) return false;
286
} else if ( !alias.equals( other.alias ) ) return false;
289
public String toString( ) {
290
return ( new StringBuilder( ) ).append( alias == null ? "null" : alias ).append( " " )
291
.append( revoked == null ? "null" : revoked ).append( " " )
292
.append( pemCertificate == null ? "null" : pemCertificate )
298
@PersistenceContext(name="eucalyptus_auth")
299
@Table( name = "auth_clusters" )
300
@Cache( usage = CacheConcurrencyStrategy.READ_WRITE )
301
public class ClusterCredentials extends AbstractPersistent implements Serializable {
302
@Column( name = "auth_cluster_name", unique=true )
304
@OneToOne( cascade=[CascadeType.ALL], fetch=FetchType.EAGER )
305
@JoinColumn(name="auth_cluster_x509_certificate")
306
@Cache( usage = CacheConcurrencyStrategy.READ_WRITE )
307
X509Cert clusterCertificate
308
@OneToOne( cascade=[CascadeType.ALL], fetch=FetchType.EAGER )
309
@JoinColumn(name="auth_cluster_node_x509_certificate")
310
@Cache( usage = CacheConcurrencyStrategy.READ_WRITE )
311
X509Cert nodeCertificate
312
public ClusterCredentials( ) {
314
public ClusterCredentials( String clusterName ) {
315
this.clusterName = clusterName;
319
public int hashCode( ) {
320
final int prime = 31;
322
result = prime * result + ( ( clusterName == null ) ? 0 : clusterName.hashCode( ) );
327
public boolean equals( Object obj ) {
328
if ( this.is( obj ) ) return true;
329
if ( !getClass( ).equals( obj.getClass( ) ) ) return false;
330
ClusterCredentials other = ( ClusterCredentials ) obj;
331
if ( clusterName == null ) {
332
if ( other.clusterName != null ) return false;
333
} else if ( !clusterName.equals( other.clusterName ) ) return false;