1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.linecorp.centraldogma.server.auth.saml;
17
18 import static com.google.common.base.Preconditions.checkState;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.security.GeneralSecurityException;
23 import java.time.Duration;
24
25 import org.opensaml.security.credential.CredentialResolver;
26
27 import com.fasterxml.jackson.core.JsonProcessingException;
28
29 import com.linecorp.armeria.server.saml.KeyStoreCredentialResolverBuilder;
30 import com.linecorp.armeria.server.saml.SamlServiceProvider;
31 import com.linecorp.armeria.server.saml.SamlServiceProviderBuilder;
32 import com.linecorp.centraldogma.server.auth.AuthConfig;
33 import com.linecorp.centraldogma.server.auth.AuthProvider;
34 import com.linecorp.centraldogma.server.auth.AuthProviderFactory;
35 import com.linecorp.centraldogma.server.auth.AuthProviderParameters;
36 import com.linecorp.centraldogma.server.auth.saml.SamlAuthProperties.Idp;
37 import com.linecorp.centraldogma.server.auth.saml.SamlAuthProperties.KeyStore;
38
39
40
41
42 public final class SamlAuthProviderFactory implements AuthProviderFactory {
43 @Override
44 public AuthProvider create(AuthProviderParameters parameters) {
45 final SamlAuthProperties properties = getProperties(parameters.authConfig());
46 try {
47 final KeyStore ks = properties.keyStore();
48 final Idp idp = properties.idp();
49 final SamlServiceProviderBuilder builder = SamlServiceProvider.builder();
50 builder.entityId(properties.entityId())
51 .hostname(properties.hostname())
52 .signingKey(properties.signingKey())
53 .encryptionKey(properties.encryptionKey())
54 .authorizer(parameters.authorizer())
55 .ssoHandler(new SamlAuthSsoHandler(
56 parameters.sessionIdGenerator(),
57 parameters.loginSessionPropagator(),
58 Duration.ofMillis(parameters.authConfig().sessionTimeoutMillis()),
59 parameters.authConfig().loginNameNormalizer(),
60 properties.idp().subjectLoginNameIdFormat(),
61 properties.idp().attributeLoginName()))
62 .credentialResolver(credentialResolver(ks))
63 .signatureAlgorithm(ks.signatureAlgorithm())
64 .idp()
65 .entityId(idp.entityId())
66 .ssoEndpoint(idp.endpoint())
67 .signingKey(idp.signingKey())
68 .encryptionKey(idp.encryptionKey());
69 return new SamlAuthProvider(builder.build());
70 } catch (Exception e) {
71 throw new IllegalStateException("Failed to create " +
72 SamlAuthProvider.class.getSimpleName(), e);
73 }
74 }
75
76 private static SamlAuthProperties getProperties(AuthConfig authConfig) {
77 try {
78 final SamlAuthProperties p = authConfig.properties(SamlAuthProperties.class);
79 checkState(p != null, "authentication properties are not specified");
80 return p;
81 } catch (JsonProcessingException e) {
82 throw new IllegalArgumentException("Failed to get properties from " +
83 AuthConfig.class.getSimpleName(), e);
84 }
85 }
86
87 private static CredentialResolver credentialResolver(KeyStore keyStore)
88 throws IOException, GeneralSecurityException {
89 final KeyStoreCredentialResolverBuilder builder;
90 final String path = keyStore.path();
91 final File file = new File(path);
92 if (file.isFile()) {
93 builder = new KeyStoreCredentialResolverBuilder(file);
94 } else {
95 builder = new KeyStoreCredentialResolverBuilder(
96 SamlAuthProviderFactory.class.getClassLoader(), path);
97 }
98
99 builder.type(keyStore.type())
100 .password(keyStore.password())
101 .keyPasswords(keyStore.keyPasswords());
102 return builder.build();
103 }
104 }