-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add table identity * add crud identity * add available on application * Add identity in environment * fix unit test * Add unit test * Add identity resource predicate support
- Loading branch information
1 parent
c703e69
commit e0bba33
Showing
34 changed files
with
1,416 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package fr.icdc.ebad.domain; | ||
|
||
import com.fasterxml.jackson.annotation.JsonBackReference; | ||
import lombok.*; | ||
import org.hibernate.annotations.Cache; | ||
import org.hibernate.annotations.CacheConcurrencyStrategy; | ||
|
||
import javax.persistence.*; | ||
import javax.validation.constraints.NotNull; | ||
import javax.validation.constraints.Size; | ||
|
||
@Data | ||
@EqualsAndHashCode(callSuper = false) | ||
@Entity | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Table(name = "t_identity") | ||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) | ||
public class Identity extends AbstractAuditingEntity { | ||
@Id | ||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "identity_generator") | ||
@SequenceGenerator(name = "identity_generator", sequenceName = "t_identity_id_seq") | ||
private Long id; | ||
|
||
@NotNull | ||
@Size(min = 1, max = 255) | ||
@Column(nullable = false) | ||
private String name; | ||
|
||
@NotNull | ||
@Size(min = 1, max = 255) | ||
@Column(nullable = false) | ||
private String login; | ||
|
||
@Size(min = 1, max = 255) | ||
@Column | ||
private String password; | ||
|
||
@Size(min = 1, max = 2048) | ||
@Column | ||
private String privatekey; | ||
|
||
@Size(min = 1, max = 2048) | ||
@Column(name = "privatekey_path") | ||
private String privatekeyPath; | ||
|
||
@Size(min = 1, max = 255) | ||
@Column | ||
private String passphrase; | ||
|
||
@ManyToOne | ||
@JoinColumn(name = "available_application_id") | ||
@JsonBackReference | ||
private Application availableApplication; | ||
} |
20 changes: 20 additions & 0 deletions
20
src/main/java/fr/icdc/ebad/repository/IdentityRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package fr.icdc.ebad.repository; | ||
|
||
import com.querydsl.core.types.dsl.StringExpression; | ||
import com.querydsl.core.types.dsl.StringPath; | ||
import fr.icdc.ebad.domain.Identity; | ||
import fr.icdc.ebad.domain.QIdentity; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.data.querydsl.QuerydslPredicateExecutor; | ||
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer; | ||
import org.springframework.data.querydsl.binding.QuerydslBindings; | ||
import org.springframework.data.querydsl.binding.SingleValueBinding; | ||
|
||
public interface IdentityRepository extends JpaRepository<Identity, Long>, QuerydslPredicateExecutor<Identity>, QuerydslBinderCustomizer<QIdentity> { | ||
@Override | ||
default void customize(QuerydslBindings bindings, QIdentity root) { | ||
bindings | ||
.bind(String.class) | ||
.first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
src/main/java/fr/icdc/ebad/security/permission/PermissionIdentity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package fr.icdc.ebad.security.permission; | ||
|
||
import fr.icdc.ebad.domain.Identity; | ||
import fr.icdc.ebad.repository.IdentityRepository; | ||
import fr.icdc.ebad.security.SecurityUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.security.core.userdetails.UserDetails; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.util.Optional; | ||
|
||
@Service | ||
public class PermissionIdentity { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(PermissionIdentity.class); | ||
|
||
private final PermissionApplication permissionApplication; | ||
private final IdentityRepository identityRepository; | ||
|
||
public PermissionIdentity(PermissionApplication permissionApplication, IdentityRepository identityRepository) { | ||
this.permissionApplication = permissionApplication; | ||
this.identityRepository = identityRepository; | ||
} | ||
|
||
|
||
public boolean canReadByApplication(Long applicationId, UserDetails userDetails) { | ||
LOGGER.debug("PermissionIdentity canReadByApplication"); | ||
if (applicationId == null) { | ||
return SecurityUtils.isAdmin() || SecurityUtils.isUser(); | ||
} | ||
return permissionApplication.canWrite(applicationId, userDetails); | ||
} | ||
|
||
public boolean canRead(Long identityId, UserDetails userDetails) { | ||
LOGGER.debug("PermissionIdentity canRead"); | ||
if (identityId == null) { | ||
return false; | ||
} | ||
Optional<Identity> identityOptional = identityRepository.findById(identityId); | ||
if(identityOptional.isEmpty()){ | ||
return false; | ||
} | ||
if(identityOptional.get().getAvailableApplication() == null){ | ||
return SecurityUtils.isAdmin() || SecurityUtils.isUser(); | ||
} | ||
return canReadByApplication(identityOptional.get().getAvailableApplication().getId(), userDetails); | ||
} | ||
|
||
public boolean canWriteByApplication(Long applicationId, UserDetails userDetails) { | ||
LOGGER.debug("PermissionIdentity canWriteByApplication"); | ||
if (applicationId == null) { | ||
return SecurityUtils.isAdmin(); | ||
} | ||
return permissionApplication.canWrite(applicationId, userDetails); | ||
} | ||
|
||
public boolean canWrite(Long identityId, UserDetails userDetails) { | ||
LOGGER.debug("PermissionIdentity canWrite"); | ||
if (identityId == null) { | ||
return false; | ||
} | ||
Optional<Identity> identityOptional = identityRepository.findById(identityId); | ||
if(identityOptional.isEmpty()){ | ||
return false; | ||
} | ||
if(identityOptional.get().getAvailableApplication() == null){ | ||
return SecurityUtils.isAdmin(); | ||
} | ||
return canWriteByApplication(identityOptional.get().getAvailableApplication().getId(), userDetails); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package fr.icdc.ebad.service; | ||
|
||
import com.querydsl.core.types.Predicate; | ||
import fr.icdc.ebad.domain.Identity; | ||
import fr.icdc.ebad.domain.QIdentity; | ||
import fr.icdc.ebad.repository.IdentityRepository; | ||
import fr.icdc.ebad.service.util.EbadServiceException; | ||
import org.bouncycastle.jce.provider.BouncyCastleProvider; | ||
import org.bouncycastle.openssl.PEMDecryptorProvider; | ||
import org.bouncycastle.openssl.PEMEncryptedKeyPair; | ||
import org.bouncycastle.openssl.PEMKeyPair; | ||
import org.bouncycastle.openssl.PEMParser; | ||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; | ||
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; | ||
import org.bouncycastle.util.io.pem.PemReader; | ||
import org.springframework.data.domain.Page; | ||
import org.springframework.data.domain.Pageable; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.io.*; | ||
import java.security.KeyPair; | ||
import java.security.Security; | ||
import java.util.Optional; | ||
|
||
@Service | ||
public class IdentityService { | ||
private final IdentityRepository identityRepository; | ||
|
||
public IdentityService(IdentityRepository identityRepository) { | ||
this.identityRepository = identityRepository; | ||
} | ||
|
||
@Transactional | ||
public Identity saveIdentity(Identity identity) { | ||
return identityRepository.save(identity); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public Optional<Identity> getIdentity(Long id) { | ||
return identityRepository.findById(id); | ||
} | ||
|
||
@Transactional | ||
public void deleteIdentity(Long id) { | ||
identityRepository.deleteById(id); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public Page<Identity> findWithoutApp(Predicate predicate, Pageable pageable) { | ||
Predicate predicateAll = QIdentity.identity.availableApplication.isNull().and(predicate); | ||
return identityRepository.findAll(predicateAll, pageable); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public Page<Identity> findAllByApplication(Long applicationId, Predicate predicate, Pageable pageable) { | ||
Predicate predicateAll = QIdentity.identity.availableApplication.id.eq(applicationId).and(predicate); | ||
return identityRepository.findAll(predicateAll, pageable); | ||
} | ||
|
||
|
||
public KeyPair createKeyPair(Identity identity) throws EbadServiceException { | ||
Security.addProvider(new BouncyCastleProvider()); | ||
String password = identity.getPassphrase(); | ||
|
||
try( | ||
PemReader pemReader = new PemReader(openReader(identity)); | ||
PEMParser pemParser = new PEMParser(pemReader) | ||
) { | ||
Object pemKeyPair = pemParser.readObject(); | ||
|
||
if (pemKeyPair instanceof PEMEncryptedKeyPair) { | ||
if (password == null) { | ||
throw new EbadServiceException("Unable to import private key. Key is encrypted, but no password was provided."); | ||
} | ||
PEMDecryptorProvider decryptor = new JcePEMDecryptorProviderBuilder().build(password.toCharArray()); | ||
PEMKeyPair decryptedKeyPair = ((PEMEncryptedKeyPair) pemKeyPair).decryptKeyPair(decryptor); | ||
return new JcaPEMKeyConverter().getKeyPair(decryptedKeyPair); | ||
} else { | ||
return new JcaPEMKeyConverter().getKeyPair((PEMKeyPair) pemKeyPair); | ||
} | ||
}catch (IOException e){ | ||
throw new EbadServiceException("Error when trying to read ssh key file\n" + | ||
"Make sur use RSA keys, try to convert your key with \n" + | ||
"ssh-keygen -p -P \"old passphrase\" -N \"new passphrase\" -m pem -f path/to/key \n" + | ||
"THIS OVERWRITE YOUR KEY SO MAKE A BACKUP BEFORE", e); | ||
} | ||
} | ||
|
||
private Reader openReader(Identity identity) throws FileNotFoundException, EbadServiceException { | ||
if(identity.getPrivatekeyPath() != null) | ||
return new FileReader(identity.getPrivatekeyPath()); | ||
if(identity.getPrivatekey() != null) | ||
return new StringReader(identity.getPrivatekey()); | ||
|
||
throw new EbadServiceException("No key is provided"); | ||
} | ||
} |
Oops, something went wrong.