• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

square / keywhiz / 3679540993

pending completion
3679540993

push

github

GitHub
Adding option to disable database validation (#1170)

5 of 5 new or added lines in 2 files covered. (100.0%)

5180 of 6705 relevant lines covered (77.26%)

0.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.0
/server/src/main/java/keywhiz/KeywhizConfig.java
1
/*
2
 * Copyright (C) 2015 Square, Inc.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package keywhiz;
17

18
import com.codahale.metrics.MetricRegistry;
19
import com.fasterxml.jackson.annotation.JsonProperty;
20
import com.google.common.annotations.VisibleForTesting;
21
import io.dropwizard.Configuration;
22
import io.dropwizard.db.DataSourceFactory;
23
import io.dropwizard.db.ManagedDataSource;
24
import java.io.IOException;
25
import java.time.Duration;
26
import java.util.Map;
27
import javax.annotation.Nullable;
28
import javax.validation.Valid;
29
import javax.validation.constraints.NotNull;
30
import keywhiz.api.validation.ValidBase64;
31
import keywhiz.auth.UserAuthenticatorFactory;
32
import keywhiz.auth.cookie.CookieConfig;
33
import keywhiz.service.config.ClientAuthConfig;
34
import keywhiz.service.config.KeyStoreConfig;
35
import keywhiz.service.config.Templates;
36
import org.hibernate.validator.constraints.Length;
37
import org.hibernate.validator.constraints.NotEmpty;
38

39
import static com.google.common.base.StandardSystemProperty.USER_NAME;
40

41
/**
42
 * Keywhiz app-level configuration. Ensures validation of entire configuration at startup.
43
 */
44
public class KeywhizConfig extends Configuration {
1✔
45
  @NotEmpty
46
  @JsonProperty
47
  private String environment;
48

49
  @NotNull
1✔
50
  @JsonProperty
51
  private TemplatedDataSourceFactory database = new TemplatedDataSourceFactory();
52

53
  @NotNull
1✔
54
  @JsonProperty
55
  private TemplatedDataSourceFactory readonlyDatabase = new TemplatedDataSourceFactory();
56

57
  @Valid
58
  @NotNull
59
  @JsonProperty
60
  private UserAuthenticatorFactory userAuth;
61

62
  @NotNull
63
  @JsonProperty
64
  private CookieConfig sessionCookie;
65

66
  @JsonProperty
67
  private CookieConfig xsrfCookie;
68

69
  @NotNull
70
  @JsonProperty
71
  private String cookieKey;
72

73
  @Nullable
74
  @JsonProperty
75
  private Map<String, String> backupExportKeys;
76

77
  @NotNull
78
  @JsonProperty
79
  private KeyStoreConfig contentKeyStore;
80

81
  @NotNull
1✔
82
  @JsonProperty
83
  private String derivationProviderClass = "com.sun.crypto.provider.SunJCE";
84

85
  @JsonProperty
86
  private String migrationsDir;
87

88
  @JsonProperty
89
  private String statusCacheExpiry;
90

91
  @JsonProperty
92
  private RowHmacCheck rowHmacCheck;
93

94
  @JsonProperty
95
  private String flywaySchemaTable;
96

97
  @JsonProperty
98
  private ClientAuthConfig clientAuthConfig;
99

100
  @JsonProperty
101
  private Long maximumSecretSizeInBytesInclusive;
102

103
  @JsonProperty
104
  private NewSecretOwnershipStrategy newSecretOwnershipStrategy;
105

106
  @JsonProperty
107
  private Boolean validateDatabase;
108

109
  public enum RowHmacCheck {
1✔
110
    @JsonProperty("disabled")
1✔
111
    DISABLED,
112
    @JsonProperty("logging")
1✔
113
    DISABLED_BUT_LOG,
114
    @JsonProperty("enforced")
1✔
115
    ENFORCED;
116
  }
117

118
  public enum NewSecretOwnershipStrategy {
1✔
119
    @JsonProperty("none")
1✔
120
    NONE,
121
    @JsonProperty("inferFromClient")
1✔
122
    INFER_FROM_CLIENT;
123
  }
124

125
  public String getEnvironment() {
126
    return environment;
×
127
  }
128

129
  /**
130
   * Customizes the database config when requested. If the username for the database is not set, the
131
   * current user is set as the username.
132
   *
133
   * @return DatabaseConfiguration for read/write database.
134
   */
135
  public DataSourceFactory getDataSourceFactory() {
136
    if (database.getUser() == null) {
1✔
137
      database.setUser(USER_NAME.value());
×
138
    }
139
    return database;
1✔
140
  }
141

142
  /**
143
   * Customizes the database config when requested. If the username for the database is not set, the
144
   * current user is set as the username.
145
   *
146
   * @return DatabaseConfiguration for readonly database.
147
   */
148
  public DataSourceFactory getReadonlyDataSourceFactory() {
149
    if (readonlyDatabase.getUser() == null) {
1✔
150
      readonlyDatabase.setUser(USER_NAME.value());
×
151
    }
152
    return readonlyDatabase;
1✔
153
  }
154

155
  /**
156
   * Customizes the migrations directory.
157
   * <p>
158
   * The content of the directory might vary depending on the database engine. Having it
159
   * configurable is useful.
160
   *
161
   * @return path relative to the resources directory.
162
   */
163
  public String getMigrationsDir() {
164
    if (migrationsDir == null) {
1✔
165
      return "db/migration";
×
166
    }
167
    return migrationsDir;
1✔
168
  }
169

170
  public Duration getStatusCacheExpiry() {
171
    if ((statusCacheExpiry == null) || (statusCacheExpiry.isEmpty())) {
1✔
172
      // Default to 1 second
173
      return Duration.ofSeconds(1);
×
174
    }
175
    return Duration.parse(statusCacheExpiry);
1✔
176
  }
177

178
  /**
179
   * @return LDAP configuration to authenticate admin users. Absent if fakeLdap is true.
180
   */
181
  public UserAuthenticatorFactory getUserAuthenticatorFactory() {
182
    return userAuth;
1✔
183
  }
184

185
  /**
186
   * @return Configuration for authenticating session cookie provided by admin login.
187
   */
188
  public CookieConfig getSessionCookieConfig() {
189
    return sessionCookie;
1✔
190
  }
191

192
  /**
193
   * @return Base64-encoded key used to encrypt authenticating cookies.
194
   */
195
  // 256-bit key = 44 base64 characters
196
  @NotNull @ValidBase64 @Length(min = 44, max = 44)
197
  @JsonProperty
198
  public String getCookieKey() {
199
    try {
200
      return Templates.evaluateTemplate(cookieKey);
1✔
201
    } catch (IOException e) {
×
202
      throw new RuntimeException("Failure resolving cookieKey template", e);
×
203
    }
204
  }
205

206
  public KeyStoreConfig getContentKeyStore() {
207
    return contentKeyStore;
1✔
208
  }
209

210
  public String getDerivationProviderClass() {
211
    return derivationProviderClass;
1✔
212
  }
213

214
  @Nullable public String getBackupExportKey(String name) {
215
    if (backupExportKeys == null || backupExportKeys.isEmpty()) {
1✔
216
      return null;
×
217
    }
218
    return backupExportKeys.get(name);
1✔
219
  }
220

221
  public RowHmacCheck getRowHmacCheck() {
222
    return rowHmacCheck;
1✔
223
  }
224

225
  @VisibleForTesting
226
  public void setRowHmacCheck(RowHmacCheck rowHmacCheck) {
227
    this.rowHmacCheck = rowHmacCheck;
1✔
228
  }
1✔
229

230
  public String getFlywaySchemaTable() {
231
    if (flywaySchemaTable == null) {
1✔
232
      return "schema_version";
×
233
    }
234
    return flywaySchemaTable;
1✔
235
  }
236

237
  public ClientAuthConfig getClientAuthConfig() {
238
    return clientAuthConfig;
1✔
239
  }
240

241
  public Long getMaximumSecretSizeInBytesInclusive() { return maximumSecretSizeInBytesInclusive; }
1✔
242

243
  public NewSecretOwnershipStrategy getNewSecretOwnershipStrategy() {
244
    return newSecretOwnershipStrategy == null ? NewSecretOwnershipStrategy.NONE : newSecretOwnershipStrategy;
1✔
245
  }
246

247
  @VisibleForTesting
248
  public void setMaximumSecretSizeInBytesInclusive(Long maximumSecretSizeInBytesInclusive) {
249
    this.maximumSecretSizeInBytesInclusive = maximumSecretSizeInBytesInclusive;
1✔
250
  }
1✔
251

252
  public boolean shouldValidateDatabase() {
253
    return validateDatabase == null ? true : validateDatabase;
1✔
254
  }
255

256
  public void setValidateDatabase(boolean validateDatabase) {
257
    this.validateDatabase = validateDatabase;
×
258
  }
×
259

260
  public static class TemplatedDataSourceFactory extends DataSourceFactory {
1✔
261
    @Override public String getUrl() {
262
      try {
263
        String url = super.getUrl();
1✔
264
        if (url == null) {
1✔
265
          url = "";
×
266
        }
267
        return Templates.evaluateTemplate(url);
1✔
268
      } catch (IOException e) {
×
269
        throw new RuntimeException("Failure resolving database url template", e);
×
270
      }
271
    }
272

273
    @Override public String getPassword() {
274
      try {
275
        String password = super.getPassword();
1✔
276
        if (password == null) {
1✔
277
          password = "";
1✔
278
        }
279
        return Templates.evaluateTemplate(password);
1✔
280
      } catch (IOException e) {
×
281
        throw new RuntimeException("Failure resolving database password template", e);
×
282
      }
283
    }
284

285
    // Sets the evaluated password and URL before calling the parent's create method.
286
    @Override public ManagedDataSource build(MetricRegistry metricRegistry, String name) {
287
      setUrl(getUrl());
1✔
288
      setPassword(getPassword());
1✔
289
      return super.build(metricRegistry, name);
1✔
290
    }
291
  }
292
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc