aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-auth-saml/src/main/java/org/sonar/auth/saml/SamlSettings.java
blob: 25aa4d96e75eede6ffc8e5376c7d17b407e47339 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
 * SonarQube
 * Copyright (C) 2009-2025 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.sonar.auth.saml;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.server.ServerSide;

import static java.lang.String.valueOf;
import static org.sonar.api.PropertyType.BOOLEAN;
import static org.sonar.api.PropertyType.PASSWORD;

@ServerSide
public class SamlSettings {
  public static final String ENABLED = "sonar.auth.saml.enabled";
  public static final String PROVIDER_ID = "sonar.auth.saml.providerId";
  public static final String PROVIDER_NAME = "sonar.auth.saml.providerName";

  public static final String APPLICATION_ID = "sonar.auth.saml.applicationId";
  public static final String LOGIN_URL = "sonar.auth.saml.loginUrl";
  public static final String CERTIFICATE = "sonar.auth.saml.certificate.secured";

  public static final String USER_LOGIN_ATTRIBUTE = "sonar.auth.saml.user.login";
  public static final String USER_NAME_ATTRIBUTE = "sonar.auth.saml.user.name";
  public static final String USER_EMAIL_ATTRIBUTE = "sonar.auth.saml.user.email";
  public static final String GROUP_NAME_ATTRIBUTE = "sonar.auth.saml.group.name";

  public static final String SIGN_REQUESTS_ENABLED = "sonar.auth.saml.signature.enabled";
  public static final String SERVICE_PROVIDER_CERTIFICATE = "sonar.auth.saml.sp.certificate.secured";
  public static final String SERVICE_PROVIDER_PRIVATE_KEY = "sonar.auth.saml.sp.privateKey.secured";

  public static final String CATEGORY = "authentication";
  public static final String SUBCATEGORY = "saml";

  private final Configuration configuration;

  public SamlSettings(Configuration configuration) {
    this.configuration = configuration;
  }

  String getProviderId() {
    return configuration.get(PROVIDER_ID).orElseThrow(() -> new IllegalArgumentException("Provider ID is missing"));
  }

  String getProviderName() {
    return configuration.get(PROVIDER_NAME).orElseThrow(() -> new IllegalArgumentException("Provider Name is missing"));
  }

  String getApplicationId() {
    return configuration.get(APPLICATION_ID).orElseThrow(() -> new IllegalArgumentException("Application ID is missing"));
  }

  String getLoginUrl() {
    return configuration.get(LOGIN_URL).orElseThrow(() -> new IllegalArgumentException("Login URL is missing"));
  }

  String getCertificate() {
    return configuration.get(CERTIFICATE).orElseThrow(() -> new IllegalArgumentException("Identity provider certificate is missing"));
  }

  String getUserLogin() {
    return configuration.get(USER_LOGIN_ATTRIBUTE).orElseThrow(() -> new IllegalArgumentException("User login attribute is missing"));
  }

  String getUserName() {
    return configuration.get(USER_NAME_ATTRIBUTE).orElseThrow(() -> new IllegalArgumentException("User name attribute is missing"));
  }

  boolean isSignRequestsEnabled() {
    return configuration.getBoolean(SIGN_REQUESTS_ENABLED).orElse(false);
  }

  Optional<String> getServiceProviderPrivateKey() {
    return configuration.get(SERVICE_PROVIDER_PRIVATE_KEY);
  }

  String getServiceProviderCertificate() {
    return configuration.get(SERVICE_PROVIDER_CERTIFICATE).orElseThrow(() -> new IllegalArgumentException("Service provider certificate is missing"));
  }

  Optional<String> getUserEmail() {
    return configuration.get(USER_EMAIL_ATTRIBUTE);
  }

  Optional<String> getGroupName() {
    return configuration.get(GROUP_NAME_ATTRIBUTE);
  }

  public boolean isEnabled() {
    return configuration.getBoolean(ENABLED).orElse(false) &&
      configuration.get(PROVIDER_ID).isPresent() &&
      configuration.get(APPLICATION_ID).isPresent() &&
      configuration.get(LOGIN_URL).isPresent() &&
      configuration.get(CERTIFICATE).isPresent() &&
      configuration.get(USER_LOGIN_ATTRIBUTE).isPresent() &&
      configuration.get(USER_NAME_ATTRIBUTE).isPresent();
  }

  public static List<PropertyDefinition> definitions() {
    return Arrays.asList(
      PropertyDefinition.builder(ENABLED)
        .name("Enabled")
        .description("Enable SAML users to login. Value is ignored if provider ID, login url, certificate, login, name attributes are not defined.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .type(BOOLEAN)
        .defaultValue(valueOf(false))
        .index(1)
        .build(),
      PropertyDefinition.builder(APPLICATION_ID)
        .name("Application ID")
        .description("The identifier used on the Identity Provider for registering SonarQube.")
        .defaultValue("sonarqube")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .index(2)
        .build(),
      PropertyDefinition.builder(PROVIDER_NAME)
        .name("Provider Name")
        .description("Name of the Identity Provider displayed in the login page when SAML authentication is active.")
        .defaultValue("SAML")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .index(3)
        .build(),
      PropertyDefinition.builder(PROVIDER_ID)
        .name("Provider ID")
        .description("Identifier of the Identity Provider, the entity that provides SAML authentication.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .index(4)
        .build(),
      PropertyDefinition.builder(LOGIN_URL)
        .name("SAML login url")
        .description("The URL where the Identity Provider expects to receive SAML requests.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .index(5)
        .build(),
      PropertyDefinition.builder(CERTIFICATE)
        .name("Identity provider certificate")
        .description("The public X.509 certificate used by the Identity Provider to authenticate SAML messages.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .type(PASSWORD)
        .index(6)
        .build(),
      PropertyDefinition.builder(USER_LOGIN_ATTRIBUTE)
        .name("SAML user login attribute")
        .description("The name of the attribute where the SAML Identity Provider will put the login of the authenticated user.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .index(7)
        .build(),
      PropertyDefinition.builder(USER_NAME_ATTRIBUTE)
        .name("SAML user name attribute")
        .description("The name of the attribute where the SAML Identity Provider will put the name of the authenticated user.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .index(8)
        .build(),
      PropertyDefinition.builder(USER_EMAIL_ATTRIBUTE)
        .name("SAML user email attribute")
        .description("The name of the attribute where the SAML Identity Provider will put the email of the authenticated user.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .index(9)
        .build(),
      PropertyDefinition.builder(GROUP_NAME_ATTRIBUTE)
        .name("SAML group attribute")
        .description("Attribute defining the user groups in SAML, used to synchronize group memberships. If you leave this field empty, " +
          "group memberships will not be synced when users log in.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .index(10)
        .build(),
      PropertyDefinition.builder(SIGN_REQUESTS_ENABLED)
        .name("Sign requests")
        .description("Enables signature of SAML requests. It requires both service provider private key and certificate to be set.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .type(BOOLEAN)
        .defaultValue(valueOf(false))
        .index(11)
        .build(),
      PropertyDefinition.builder(SERVICE_PROVIDER_PRIVATE_KEY)
        .name("Service provider private key")
        .description("PKCS8 stored private key used for signing the requests and decrypting responses from the identity provider. ")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .type(PASSWORD)
        .index(12)
        .build(),
      PropertyDefinition.builder(SERVICE_PROVIDER_CERTIFICATE)
        .name("Service provider certificate")
        .description("X.509 certificate for the service provider, used for signing the requests and decrypting responses from the identity provider.")
        .category(CATEGORY)
        .subCategory(SUBCATEGORY)
        .type(PASSWORD)
        .index(13)
        .build());
  }
}