Repository: brooklyn-server Updated Branches: refs/heads/master ba05e9642 -> 703cd0d31
CreatePassworkSensor: support "character groups" Character groups are groups like "capital letters", "numbers", etc. This option allows a blueprint to require that the generated password contains at least one character from every group. It is common (e.g. Micrsoft default password policy) to see a requirement like "must contain characters from at least 3 groups". Previously, this sensor could not guarantee that this would happen. Use it like this: - type: org.apache.brooklyn.core.sensor.password.CreatePasswordSensor brooklyn.config: name: my.password password.length: 10 password.character.groups: - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "1234567890" - "-_=+[{]};:|`~,<.>/?!@#$%^&*()" Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/d2ecd112 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/d2ecd112 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/d2ecd112 Branch: refs/heads/master Commit: d2ecd112601ba709fc8fd5ae6cb30f4be2a967b4 Parents: ba05e96 Author: Richard Downer <rich...@apache.org> Authored: Fri Dec 1 13:39:17 2017 +0000 Committer: Richard Downer <rich...@apache.org> Committed: Fri Dec 1 14:59:52 2017 +0000 ---------------------------------------------------------------------- .../sensor/password/CreatePasswordSensor.java | 34 +++++++++++++++++--- .../password/CreatePasswordSensorTest.java | 19 +++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d2ecd112/core/src/main/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensor.java b/core/src/main/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensor.java index 7b7a908..e62b332 100644 --- a/core/src/main/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensor.java +++ b/core/src/main/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensor.java @@ -18,8 +18,13 @@ */ package org.apache.brooklyn.core.sensor.password; +import java.util.List; import java.util.Map; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; +import com.google.common.reflect.TypeToken; import org.apache.brooklyn.api.entity.EntityLocal; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.config.ConfigKeys; @@ -33,8 +38,11 @@ public class CreatePasswordSensor extends AddSensor<String> { public static final ConfigKey<String> ACCEPTABLE_CHARS = ConfigKeys.newStringConfigKey("password.chars", "The characters allowed in password"); + public static final ConfigKey<List<String>> CHARACTER_GROUPS = ConfigKeys.newConfigKey(new TypeToken<List<String>>() {}, "password.character.groups", "A list of strings, where each string is a character group (such as letters, or numbers). The password will be constructed using only characters from these strings, and will use at least one character from each group. When using this option, `password.length` must be at least as long as the number of character groups given."); + private Integer passwordLength; private String acceptableChars; + private List<String> characterGroups; public CreatePasswordSensor(Map<String, String> params) { this(ConfigBag.newInstance(params)); @@ -44,16 +52,34 @@ public class CreatePasswordSensor extends AddSensor<String> { super(params); passwordLength = params.get(PASSWORD_LENGTH); acceptableChars = params.get(ACCEPTABLE_CHARS); + characterGroups = params.get(CHARACTER_GROUPS); } @Override public void apply(EntityLocal entity) { super.apply(entity); - String password = acceptableChars == null - ? Identifiers.makeRandomPassword(passwordLength) - : Identifiers.makeRandomPassword(passwordLength, acceptableChars); - + boolean isCharacterGroupsPresent = characterGroups != null + && characterGroups.size() > 0; + boolean isCharacterGroupsValid = isCharacterGroupsPresent + && !Iterables.contains(characterGroups, Predicates.isNull()) + && !Iterables.contains(characterGroups, Predicates.equalTo("")); + boolean isAcceptableCharsPresentAndValid = acceptableChars != null + && !acceptableChars.isEmpty(); + + Preconditions.checkArgument(!isCharacterGroupsPresent || isCharacterGroupsValid, "password.character.groups config key was given but does not contain any valid groups"); + Preconditions.checkArgument(!(isCharacterGroupsPresent && isAcceptableCharsPresentAndValid), "password.chars and password.character.groups both provided - please provide only ONE of them"); + Preconditions.checkArgument(!isCharacterGroupsValid || characterGroups.size() <= passwordLength, "password.length must be longer than the number of entries in password.character.groups"); + + String password; + if (isCharacterGroupsValid) { + password = Identifiers.makeRandomPassword(passwordLength, characterGroups.toArray(new String[0])); + } else if (isAcceptableCharsPresentAndValid) { + password = Identifiers.makeRandomPassword(passwordLength, acceptableChars); + } else { + password = Identifiers.makeRandomPassword(passwordLength); + } + entity.sensors().set(sensor, password); } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d2ecd112/core/src/test/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensorTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensorTest.java b/core/src/test/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensorTest.java index d033e3d..55041ab 100644 --- a/core/src/test/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensorTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/sensor/password/CreatePasswordSensorTest.java @@ -57,4 +57,23 @@ public class CreatePasswordSensorTest extends BrooklynAppUnitTestSupport{ String password = entity.getAttribute(SENSOR_STRING); Asserts.assertEquals(password.length(), 12); } + + @Test + public void testCreatePasswordCharacterGroups() { + final CreatePasswordSensor sensor = new CreatePasswordSensor(ConfigBag.newInstance() + .configure(CreatePasswordSensor.SENSOR_NAME, SENSOR_STRING.getName()) + .configure(CreatePasswordSensor.PASSWORD_LENGTH, 6) + .configure(CreatePasswordSensor.CHARACTER_GROUPS, ImmutableList.of("abc", "def", "ghi")) + ); + sensor.apply(entity); + + String password = entity.getAttribute(SENSOR_STRING); + Asserts.assertEquals(password.length(), 6); + Asserts.assertStringMatchesRegex(password, + "[a-i]{6}", // whole string consists of exactly 6 characters from all groups + ".*[a-c].*", // at least one from the a-c group + ".*[d-f].*", // at least one from the d-f group + ".*[g-i].*" // at least one from the g-i group + ); + } } \ No newline at end of file