Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:indigo-iam/iam into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
rmiccoli committed Feb 28, 2023
2 parents e59f2cb + b9aad4b commit 5b1610c
Show file tree
Hide file tree
Showing 26 changed files with 295 additions and 167 deletions.
2 changes: 1 addition & 1 deletion iam-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>it.infn.mw</groupId>
<artifactId>iam-parent</artifactId>
<version>1.8.1-SNAPSHOT</version>
<version>1.8.1</version>
</parent>

<artifactId>iam-common</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion iam-login-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<parent>
<groupId>it.infn.mw</groupId>
<artifactId>iam-parent</artifactId>
<version>1.8.1-SNAPSHOT</version>
<version>1.8.1</version>
</parent>

<artifactId>iam-login-service</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public class RegisteredClientDTO {
private String clientSecret;

@Size(min = 4, max = 256,
groups = {OnDynamicClientRegistration.class, OnClientCreation.class, OnClientUpdate.class},
groups = {OnDynamicClientRegistration.class, OnClientCreation.class, OnClientUpdate.class, OnDynamicClientUpdate.class},
message = "Invalid length: must be between 4 and 256 characters")
@NotBlank(groups = {OnDynamicClientRegistration.class, OnClientCreation.class},
message = "should not be blank")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import java.util.List;

import org.mitre.oauth2.service.OAuth2TokenEntityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -69,6 +68,7 @@
import it.infn.mw.iam.core.user.IamAccountService;
import it.infn.mw.iam.persistence.model.IamAccount;
import it.infn.mw.iam.persistence.repository.IamAccountRepository;
import it.infn.mw.iam.registration.validation.UsernameValidator;

@SuppressWarnings("deprecation")
@RestController
Expand All @@ -90,18 +90,18 @@ public class ScimMeController implements ApplicationEventPublisherAware {

private final EnumSet<UpdaterType> enabledUpdaters;

@Autowired
public ScimMeController(IamAccountRepository accountRepository, IamAccountService accountService,
OAuth2TokenEntityService tokenService, UserConverter userConverter,
PasswordEncoder passwordEncoder, OidcIdConverter oidcIdConverter,
SamlIdConverter samlIdConverter, SshKeyConverter sshKeyConverter,
X509CertificateConverter x509CertificateConverter, IamProperties properties) {
X509CertificateConverter x509CertificateConverter, IamProperties properties,
UsernameValidator usernameValidator) {

this.iamAccountRepository = accountRepository;
this.userConverter = userConverter;
this.updatersFactory = new DefaultAccountUpdaterFactory(passwordEncoder, accountRepository,
accountService, tokenService, oidcIdConverter, samlIdConverter, sshKeyConverter,
x509CertificateConverter);
x509CertificateConverter, usernameValidator);

enabledUpdaters = EnumSet.noneOf(UpdaterType.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import java.util.List;

import org.mitre.oauth2.service.OAuth2TokenEntityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.domain.Page;
Expand Down Expand Up @@ -68,6 +67,7 @@
import it.infn.mw.iam.core.user.exception.UserAlreadyExistsException;
import it.infn.mw.iam.persistence.model.IamAccount;
import it.infn.mw.iam.persistence.repository.IamAccountRepository;
import it.infn.mw.iam.registration.validation.UsernameValidator;

@Service
public class ScimUserProvisioning
Expand All @@ -87,18 +87,19 @@ public class ScimUserProvisioning

private ApplicationEventPublisher eventPublisher;

@Autowired
public ScimUserProvisioning(IamAccountService accountService, OAuth2TokenEntityService tokenService,
IamAccountRepository accountRepository, PasswordEncoder passwordEncoder,
UserConverter userConverter, OidcIdConverter oidcIdConverter, SamlIdConverter samlIdConverter,
SshKeyConverter sshKeyConverter, X509CertificateConverter x509CertificateConverter) {
public ScimUserProvisioning(IamAccountService accountService,
OAuth2TokenEntityService tokenService, IamAccountRepository accountRepository,
PasswordEncoder passwordEncoder, UserConverter userConverter, OidcIdConverter oidcIdConverter,
SamlIdConverter samlIdConverter, SshKeyConverter sshKeyConverter,
X509CertificateConverter x509CertificateConverter,
UsernameValidator usernameValidator) {

this.accountService = accountService;
this.accountRepository = accountRepository;
this.userConverter = userConverter;
this.updatersFactory = new DefaultAccountUpdaterFactory(passwordEncoder, accountRepository,
accountService, tokenService, oidcIdConverter, samlIdConverter, sshKeyConverter,
x509CertificateConverter);
x509CertificateConverter, usernameValidator);
}

public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import it.infn.mw.iam.core.user.IamAccountService;
import it.infn.mw.iam.persistence.model.IamAccount;
import it.infn.mw.iam.persistence.repository.IamAccountRepository;
import it.infn.mw.iam.registration.validation.UsernameValidator;

public abstract class AccountBuilderSupport {

Expand All @@ -29,28 +30,21 @@ public abstract class AccountBuilderSupport {
protected final PasswordEncoder encoder;
protected final IamAccount account;
protected final OAuth2TokenEntityService tokenService;
protected final UsernameValidator usernameValidator;

public AccountBuilderSupport(IamAccountRepository repo, IamAccountService accountService,
OAuth2TokenEntityService tokenService, PasswordEncoder encoder, IamAccount account) {
OAuth2TokenEntityService tokenService, PasswordEncoder encoder, UsernameValidator usernameValidator, IamAccount account) {
this.repo = repo;
this.encoder = encoder;
this.accountService = accountService;
this.tokenService = tokenService;
this.usernameValidator = usernameValidator;
this.account = account;
}

public AccountBuilderSupport(IamAccountRepository repo, IamAccount account) {
this(repo, null, null, null, account);
}

public AccountBuilderSupport(IamAccountRepository repo, IamAccountService accountService,
PasswordEncoder encoder, IamAccount account) {
this(repo, accountService, null, encoder, account);
}

public AccountBuilderSupport(IamAccountRepository repo, IamAccountService accountService,
IamAccount account) {
this(repo, accountService, null, null, account);
this(repo, accountService, null, null, new UsernameValidator(), account);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import it.infn.mw.iam.core.user.IamAccountService;
import it.infn.mw.iam.persistence.model.IamAccount;
import it.infn.mw.iam.persistence.repository.IamAccountRepository;
import it.infn.mw.iam.registration.validation.UsernameValidator;

public class AccountUpdaters {

Expand All @@ -29,8 +30,9 @@ private AccountUpdaters() {

public static Adders adders(IamAccountRepository repo, IamAccountService accountService,
PasswordEncoder encoder,
IamAccount account, OAuth2TokenEntityService tokenService) {
return new Adders(repo, accountService, encoder, account, tokenService);
IamAccount account, OAuth2TokenEntityService tokenService,
UsernameValidator usernameValidator) {
return new Adders(repo, accountService, encoder, account, tokenService, usernameValidator);
}

public static Removers removers(IamAccountRepository repo, IamAccountService accountService,
Expand All @@ -39,10 +41,9 @@ public static Removers removers(IamAccountRepository repo, IamAccountService acc
}

public static Replacers replacers(IamAccountRepository repo, IamAccountService accountService,
PasswordEncoder encoder,
IamAccount account, OAuth2TokenEntityService tokenService) {
return new Replacers(repo, accountService, encoder, account, tokenService);
PasswordEncoder encoder, IamAccount account, OAuth2TokenEntityService tokenService,
UsernameValidator usernameValidator) {
return new Replacers(repo, accountService, encoder, account, tokenService, usernameValidator);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import it.infn.mw.iam.persistence.model.IamSshKey;
import it.infn.mw.iam.persistence.model.IamX509Certificate;
import it.infn.mw.iam.persistence.repository.IamAccountRepository;
import it.infn.mw.iam.registration.validation.UsernameValidator;

public class Adders extends Replacers {

Expand All @@ -66,8 +67,9 @@ public class Adders extends Replacers {
final Consumer<Collection<IamSshKey>> linkSshKeys;

public Adders(IamAccountRepository repo, IamAccountService accountService,
PasswordEncoder encoder, IamAccount account, OAuth2TokenEntityService tokenService) {
super(repo, accountService, encoder, account, tokenService);
PasswordEncoder encoder, IamAccount account, OAuth2TokenEntityService tokenService,
UsernameValidator usernameValidator) {
super(repo, accountService, encoder, account, tokenService, usernameValidator);

findByOidcId = id -> repo.findByOidcId(id.getIssuer(), id.getSubject());
findBySamlId = repo::findBySamlId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import it.infn.mw.iam.persistence.model.IamAccount;
import it.infn.mw.iam.persistence.model.IamUserInfo;
import it.infn.mw.iam.persistence.repository.IamAccountRepository;
import it.infn.mw.iam.registration.validation.UsernameValidator;

public class Replacers extends AccountBuilderSupport {

Expand All @@ -59,9 +60,10 @@ public class Replacers extends AccountBuilderSupport {
final AccountFinder<String> findByUsername;

public Replacers(IamAccountRepository repo, IamAccountService accountService,
PasswordEncoder encoder, IamAccount account, OAuth2TokenEntityService tokenService) {
PasswordEncoder encoder, IamAccount account, OAuth2TokenEntityService tokenService,
UsernameValidator usernameValidator) {

super(repo, accountService, tokenService, encoder, account);
super(repo, accountService, tokenService, encoder, usernameValidator, account);
findByEmail = repo::findByEmail;
findByUsername = repo::findByUsername;
encodedPasswordSetter = t -> account.setPassword(encoder.encode(t));
Expand Down Expand Up @@ -90,7 +92,9 @@ private Predicate<String> buildUsernameAddChecks() {

Predicate<String> usernameNotOwned = e -> !account.getUsername().equals(e);

return usernameNotBound.and(usernameNotOwned);
Predicate<String> usernameNotUnix = e -> usernameValidator.isValid(e, null);

return usernameNotBound.and(usernameNotOwned).and(usernameNotUnix);
}

public AccountUpdater givenName(String givenName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import it.infn.mw.iam.persistence.model.IamSshKey;
import it.infn.mw.iam.persistence.model.IamX509Certificate;
import it.infn.mw.iam.persistence.repository.IamAccountRepository;
import it.infn.mw.iam.registration.validation.UsernameValidator;

public class DefaultAccountUpdaterFactory implements AccountUpdaterFactory<IamAccount, ScimUser> {

Expand All @@ -65,6 +66,8 @@ public class DefaultAccountUpdaterFactory implements AccountUpdaterFactory<IamAc
final IamAccountService accountService;
final OAuth2TokenEntityService tokenService;

final UsernameValidator usernameValidator;

final OidcIdConverter oidcIdConverter;
final SamlIdConverter samlIdConverter;
final SshKeyConverter sshKeyConverter;
Expand All @@ -73,7 +76,8 @@ public class DefaultAccountUpdaterFactory implements AccountUpdaterFactory<IamAc
public DefaultAccountUpdaterFactory(PasswordEncoder encoder, IamAccountRepository repo,
IamAccountService accountService, OAuth2TokenEntityService tokenService,
OidcIdConverter oidcIdConverter, SamlIdConverter samlIdConverter,
SshKeyConverter sshKeyConverter, X509CertificateConverter x509CertificateConverter) {
SshKeyConverter sshKeyConverter, X509CertificateConverter x509CertificateConverter,
UsernameValidator usernameValidator) {

this.accountService = accountService;
this.tokenService = tokenService;
Expand All @@ -83,6 +87,7 @@ public DefaultAccountUpdaterFactory(PasswordEncoder encoder, IamAccountRepositor
this.samlIdConverter = samlIdConverter;
this.sshKeyConverter = sshKeyConverter;
this.x509CertificateConverter = x509CertificateConverter;
this.usernameValidator = usernameValidator;
}

private ScimCollectionConverter<IamSshKey, ScimSshKey> sshKeyConverter(ScimUser user) {
Expand Down Expand Up @@ -123,7 +128,7 @@ private static <T> void addUpdater(List<AccountUpdater> updaters, Predicate<T> v

private void prepareAdders(List<AccountUpdater> updaters, ScimUser user, IamAccount account) {

Adders add = AccountUpdaters.adders(repo, accountService, encoder, account, tokenService);
Adders add = AccountUpdaters.adders(repo, accountService, encoder, account, tokenService, usernameValidator);

if (user.hasName()) {

Expand Down Expand Up @@ -191,7 +196,8 @@ private void prepareRemovers(List<AccountUpdater> updaters, ScimUser user, IamAc

private void prepareReplacers(List<AccountUpdater> updaters, ScimUser user, IamAccount account) {

Replacers replace = AccountUpdaters.replacers(repo, accountService, encoder, account, tokenService);
Replacers replace = AccountUpdaters.replacers(repo, accountService, encoder, account,
tokenService, usernameValidator);

if (user.hasName()) {
addUpdater(updaters, Objects::nonNull, user.getName()::getGivenName, replace::givenName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import it.infn.mw.iam.notification.service.resolver.NotifyGmsAndAdminsStrategy;
import it.infn.mw.iam.persistence.repository.IamAccountRepository;
import it.infn.mw.iam.persistence.repository.IamAupRepository;
import it.infn.mw.iam.registration.validation.UsernameValidator;
import it.infn.mw.iam.service.aup.AUPSignatureCheckService;

@SuppressWarnings("deprecation")
Expand Down Expand Up @@ -234,7 +235,7 @@ IntrospectionResultAssembler defaultIntrospectionResultAssembler(
}

@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

Expand Down Expand Up @@ -263,4 +264,9 @@ ServletRegistrationBean<WebServlet> h2Console() {
return new ServletRegistrationBean<>(h2Servlet, "/h2-console/*");
}

@Bean
UsernameValidator usernameRegExpValidator() {
return new UsernameValidator();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,24 @@
import java.util.Date;
import java.util.List;

import javax.validation.constraints.Size;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

import it.infn.mw.iam.api.common.LabelDTO;

import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import it.infn.mw.iam.registration.validation.UsernameRegExp;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class RegistrationRequestDto {

// Regular expression from https://unix.stackexchange.com/a/435120
public static final String USERNAME_REGEXP = "^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\\$)$";

private String uuid;
private Date creationTime;
private String status;
private Date lastUpdateTime;
@Size(max = 32, message = "username cannot be longer than 32 chars")
@Pattern(regexp = USERNAME_REGEXP,
message = "invalid username (the provided username is not a valid UNIX username)")
@UsernameRegExp
private String username;
private String password;
private String givenname;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2016-2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.infn.mw.iam.registration.validation;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Retention(RUNTIME)
@Target({FIELD})
@Constraint(validatedBy = UsernameValidator.class)
public @interface UsernameRegExp {

String message() default "invalid username (the provided username is not a valid UNIX username)";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

}
Loading

0 comments on commit 5b1610c

Please sign in to comment.