From 086e8381d8235db912d935def6491ef321c75a9b Mon Sep 17 00:00:00 2001 From: Piotr Jaszczyk Date: Thu, 30 May 2019 13:04:36 +0200 Subject: Update dependencies and enhance crypt-password lib Change-Id: I7fe56e43d7ff0ac9b50708a6abe2163f7ddf8904 Issue-ID: DCAEGEN2-1542 Signed-off-by: Piotr Jaszczyk --- pom.xml | 510 +++++++++++---------- security/crypt-password/pom.xml | 98 ++-- .../sdk/security/CharsFromStreamReader.java | 62 +++ .../services/sdk/security/CryptPassword.java | 33 +- .../services/sdk/security/DecodePassword.java | 34 -- .../services/sdk/security/EncodePassword.java | 76 +++ .../dcaegen2/services/sdk/security/ExitCode.java | 31 ++ .../sdk/security/CharsFromStreamReaderTest.java | 57 +++ .../services/sdk/security/CryptPasswordTest.java | 55 +++ 9 files changed, 625 insertions(+), 331 deletions(-) create mode 100644 security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/CharsFromStreamReader.java delete mode 100644 security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/DecodePassword.java create mode 100644 security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/EncodePassword.java create mode 100644 security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/ExitCode.java create mode 100644 security/crypt-password/src/test/java/org/onap/dcaegen2/services/sdk/security/CharsFromStreamReaderTest.java create mode 100644 security/crypt-password/src/test/java/org/onap/dcaegen2/services/sdk/security/CryptPasswordTest.java diff --git a/pom.xml b/pom.xml index 090cb49d..ea0a379e 100644 --- a/pom.xml +++ b/pom.xml @@ -1,260 +1,272 @@ - - 4.0.0 - - org.onap.oparent - oparent - 1.2.1 - - + + 4.0.0 + + org.onap.oparent + oparent + 1.2.1 + + - org.onap.dcaegen2.services - sdk - 1.2.0-SNAPSHOT + org.onap.dcaegen2.services + sdk + 1.2.0-SNAPSHOT - dcaegen2-services-sdk - Common SDK repo for all DCAE Services - pom + dcaegen2-services-sdk + Common SDK repo for all DCAE Services + pom - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + - - 8 - 5.3.1 - 5.3.1 - 1.3.1 - 2.7.4 - 3.11.1 - Californium-SR4 - 1.7.25 - 1.2.3 - 2.23.4 - 3.6.1 - 0.10.0 - 1.6 - 16.0.3 - 3.6.0.2 - 1.1.4 - 1.11.2 - + + 8 + 5.3.1 + 5.3.1 + 1.3.1 + 2.7.5 + 3.12.2 + Californium-SR8 + 1.7.25 + 1.2.3 + 2.28.2 + 3.6.1 + 0.10.0 + 1.6 + 16.0.3 + 3.6.0.2 + 1.1.4 + 1.11.2 + - - rest-services - services - security - standardization - + + rest-services + services + security + standardization + - - - - maven-javadoc-plugin - - - true - false - false - - - - aggregate - site - - aggregate - - - - attach-javadoc - - jar - - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - - + + + + maven-javadoc-plugin + + + true + false + false + + + + aggregate + site + + aggregate + + + + attach-javadoc + + jar + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + - - - - org.apache.maven.plugins - maven-resources-plugin - 3.1.0 - - ${project.build.sourceEncoding} - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.0 - - ${java.version} - ${java.version} - ${project.build.sourceEncoding} - true - true - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.1 - - - maven-javadoc-plugin - 3.0.1 - - - -Xdoclint:none - - - - - maven-project-info-reports-plugin - 2.9 - - - org.codehaus.mojo - build-helper-maven-plugin - 1.7 - - - com.github.os72 - protoc-jar-maven-plugin - ${protoc-jar-maven-plugin.version} - - - - + + + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + true + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + + maven-javadoc-plugin + 3.0.1 + + + -Xdoclint:none + + + + + maven-project-info-reports-plugin + 2.9 + + + org.codehaus.mojo + build-helper-maven-plugin + 1.7 + + + com.github.os72 + protoc-jar-maven-plugin + ${protoc-jar-maven-plugin.version} + + + + - - - - maven-project-info-reports-plugin - - - - dependencies - license - - - - - - + + + + maven-project-info-reports-plugin + + + + dependencies + license + + + + + + - - - - com.google.protobuf - protobuf-java - ${protobuf.version} - - - org.immutables - value - ${immutables.version} - - - org.immutables - gson - ${immutables.version} - - - io.vavr - vavr - ${vavr.version} - - - org.apache.commons - commons-text - ${commons-text.version} - - - org.slf4j - jul-to-slf4j - ${slf4j.version} - - - org.slf4j - log4j-over-slf4j - ${slf4j.version} - - - org.slf4j - slf4j-api - ${slf4j.version} - - - org.jetbrains - annotations - ${jetbrains-annotations.version} - - - io.projectreactor - reactor-bom - ${reactor.bom.version} - pom - import - - - ch.qos.logback - logback-classic - ${logback.version} - runtime - - - io.micrometer - micrometer-registry-prometheus - ${micrometer.version} - + + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + org.immutables + value + ${immutables.version} + + + org.immutables + gson + ${immutables.version} + + + io.vavr + vavr + ${vavr.version} + + + org.apache.commons + commons-text + ${commons-text.version} + + + org.slf4j + jul-to-slf4j + ${slf4j.version} + + + org.slf4j + log4j-over-slf4j + ${slf4j.version} + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.jetbrains + annotations + ${jetbrains-annotations.version} + + + io.projectreactor + reactor-bom + ${reactor.bom.version} + pom + import + + + ch.qos.logback + logback-classic + ${logback.version} + runtime + + + org.slf4j + jcl-over-slf4j + 1.7.26 + runtime + + + io.micrometer + micrometer-registry-prometheus + ${micrometer.version} + + + org.springframework.security + spring-security-crypto + 5.0.12.RELEASE + - - org.mockito - mockito-core - ${mockito.version} - test - - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-api - ${junit-jupiter.version} - test - - - org.assertj - assertj-core - ${assertj-core.version} - test - - - org.testcontainers - testcontainers - ${testcontainers.version} - test - - - org.testcontainers - junit-jupiter - ${testcontainers.version} - test - - - - \ No newline at end of file + + org.mockito + mockito-core + ${mockito.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter.version} + test + + + org.assertj + assertj-core + ${assertj-core.version} + test + + + org.testcontainers + testcontainers + ${testcontainers.version} + test + + + org.testcontainers + junit-jupiter + ${testcontainers.version} + test + + + + diff --git a/security/crypt-password/pom.xml b/security/crypt-password/pom.xml index 2e37c151..299aced7 100644 --- a/security/crypt-password/pom.xml +++ b/security/crypt-password/pom.xml @@ -1,52 +1,70 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - - org.onap.dcaegen2.services.sdk.security - dcaegen2-services-sdk-security - 1.2.0-SNAPSHOT - - 4.0.0 + + org.onap.dcaegen2.services.sdk.security + dcaegen2-services-sdk-security + 1.2.0-SNAPSHOT + + 4.0.0 - org.onap.dcaegen2.services.sdk.security.crypt - crypt-password + org.onap.dcaegen2.services.sdk.security.crypt + crypt-password - Security :: Crypt Password - DMaaP Security Module - jar + Security :: Crypt Password + DMaaP Security Module + jar - - - org.springframework.security - spring-security-crypto - 3.1.0.RELEASE - - + + + org.springframework.security + spring-security-crypto + + + org.junit.jupiter + junit-jupiter-api + + + org.assertj + assertj-core + + + org.slf4j + jcl-over-slf4j + runtime + + + ch.qos.logback + logback-classic + runtime + + - - org.apache.maven.plugins - maven-shade-plugin - 3.2.1 - - - package - - shade - - - - - org.onap.dcaegen2.services.sdk.security.DecodePassword - - - - - - + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + + + org.onap.dcaegen2.services.sdk.security.EncodePassword + + + + + + diff --git a/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/CharsFromStreamReader.java b/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/CharsFromStreamReader.java new file mode 100644 index 00000000..1ea18cc7 --- /dev/null +++ b/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/CharsFromStreamReader.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START==================================== + * DCAEGEN2-SERVICES-SDK + * ========================================================= + * Copyright (C) 2019 Nokia. All rights reserved. + * ========================================================= + * 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. + * ============LICENSE_END===================================== + */ + +package org.onap.dcaegen2.services.sdk.security; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.CharBuffer; + +final class CharsFromStreamReader { + + public static final int END_OF_STREAM = -1; + private final int maxLength; + + CharsFromStreamReader(int maxLength) { + this.maxLength = maxLength; + } + + CharSequence readPasswordFromStdIn() throws IOException { + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) { + return readPassword(bufferedReader); + } + } + + CharSequence readPassword(BufferedReader bufferedReader) throws IOException { + final CharBuffer charBuffer = CharBuffer.allocate(maxLength); + if (readAllChars(charBuffer, bufferedReader)) { + charBuffer.flip(); + return charBuffer.asReadOnlyBuffer(); + } else { + throw new IOException( + "Input exceeds maximum supported length of " + maxLength + " characters"); + } + } + + private boolean readAllChars(CharBuffer charBuffer, BufferedReader bufferedReader) throws IOException { + int readChars = 0; + while (readChars != END_OF_STREAM && charBuffer.remaining() > 0) { + readChars = bufferedReader.read(charBuffer); + } + // true when all characters were read + return readChars == -1; + } +} diff --git a/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/CryptPassword.java b/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/CryptPassword.java index 6ca78a01..4b16c9e2 100644 --- a/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/CryptPassword.java +++ b/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/CryptPassword.java @@ -21,15 +21,32 @@ package org.onap.dcaegen2.services.sdk.security; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -public class CryptPassword { +/** + * Class for encoding passwords using BCrypt algorithm. + */ +public final class CryptPassword { - private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); - public String decode(String arg) { - return encoder.encode(arg); - } + /** + * Encode the raw password. + * + * @param rawPassword raw password to be encoded + * @return encoded password + */ + public String encode(CharSequence rawPassword) { + return encoder.encode(rawPassword); + } - public boolean matches(String rawPassword, String encodedPassword){ - return encoder.matches(rawPassword,encodedPassword); - } + /** + * Verify the encoded password matches the submitted raw password. Returns true if the passwords match, false if + * they do not. + * + * @param rawPassword the raw password to encode and match + * @param encodedPassword the encoded password to compare with + * @return true if the raw password, after encoding, matches the encoded password + */ + public boolean matches(CharSequence rawPassword, String encodedPassword) { + return encoder.matches(rawPassword, encodedPassword); + } } diff --git a/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/DecodePassword.java b/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/DecodePassword.java deleted file mode 100644 index 85412eb6..00000000 --- a/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/DecodePassword.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * DCAEGEN2-SERVICES-SDK - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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. - * ============LICENSE_END========================================================= - */ -package org.onap.dcaegen2.services.sdk.security; - -class DecodePassword { - - private static CryptPassword cryptPassword = new CryptPassword(); - - public static void main(String[] args) { - - try { - System.out.println(cryptPassword.decode(args[0])); - }catch(Exception e){ - System.out.println("Param to crypt is required !"); - } - } -} diff --git a/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/EncodePassword.java b/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/EncodePassword.java new file mode 100644 index 00000000..77843816 --- /dev/null +++ b/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/EncodePassword.java @@ -0,0 +1,76 @@ +/* + * ============LICENSE_START======================================================= + * DCAEGEN2-SERVICES-SDK + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.services.sdk.security; + +import java.io.IOException; + +class EncodePassword { + + private static final int MAX_PASSWORD_LENGTH = 64 * 1024; + private static final int ARGS_LENGTH_PASSWORD_PROVIDED = 1; + private CryptPassword cryptPassword = new CryptPassword(); + private CharsFromStreamReader charsFromStreamReader = new CharsFromStreamReader(MAX_PASSWORD_LENGTH); + + public static void main(String[] args) { + new EncodePassword().run(args); + } + + public void run(String[] args) { + try { + encodeRawInput(readPassword(args)); + } catch (IOException ex) { + printErrorAndExit(ExitCode.IO_ERROR, "Error while reading the password: " + ex.getMessage()); + } + } + + private void encodeRawInput(CharSequence rawPassword) { + if (rawPassword == null || rawPassword.length() == 0) { + printErrorAndExit(ExitCode.INVALID_PASSWORD, "Password cannot be empty"); + } else { + printWarningIfContainsEndlChars(rawPassword); + printResult(cryptPassword.encode(rawPassword)); + } + } + + private void printWarningIfContainsEndlChars(CharSequence rawPassword) { + if (rawPassword.chars().anyMatch(ch -> ch == '\n' || ch == '\r')) { + printWarning("Warning: Password contains end of lines characters."); + } + } + + private CharSequence readPassword(String[] args) throws IOException { + return args.length >= ARGS_LENGTH_PASSWORD_PROVIDED + ? args[0] + : charsFromStreamReader.readPasswordFromStdIn(); + } + + private void printWarning(String msg) { + System.err.println(msg); + } + + private void printErrorAndExit(ExitCode exitCode, String msg) { + System.err.println(msg); + System.exit(exitCode.value); + } + + private void printResult(String encodedPassword) { + System.out.println(encodedPassword); + } +} diff --git a/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/ExitCode.java b/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/ExitCode.java new file mode 100644 index 00000000..51141eed --- /dev/null +++ b/security/crypt-password/src/main/java/org/onap/dcaegen2/services/sdk/security/ExitCode.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START==================================== + * DCAEGEN2-SERVICES-SDK + * ========================================================= + * Copyright (C) 2019 Nokia. All rights reserved. + * ========================================================= + * 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. + * ============LICENSE_END===================================== + */ + +package org.onap.dcaegen2.services.sdk.security; + +enum ExitCode { + INVALID_PASSWORD(1), IO_ERROR(2); + + final int value; + + ExitCode(int value) { + this.value = value; + } +} \ No newline at end of file diff --git a/security/crypt-password/src/test/java/org/onap/dcaegen2/services/sdk/security/CharsFromStreamReaderTest.java b/security/crypt-password/src/test/java/org/onap/dcaegen2/services/sdk/security/CharsFromStreamReaderTest.java new file mode 100644 index 00000000..2cfaa291 --- /dev/null +++ b/security/crypt-password/src/test/java/org/onap/dcaegen2/services/sdk/security/CharsFromStreamReaderTest.java @@ -0,0 +1,57 @@ +/* + * ============LICENSE_START==================================== + * DCAEGEN2-SERVICES-SDK + * ========================================================= + * Copyright (C) 2019 Nokia. All rights reserved. + * ========================================================= + * 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. + * ============LICENSE_END===================================== + */ + +package org.onap.dcaegen2.services.sdk.security; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import org.junit.jupiter.api.Test; + +class CharsFromStreamReaderTest { + private static final int MAX_LENGTH = 6; + private final CharsFromStreamReader cut = new CharsFromStreamReader(MAX_LENGTH); + + @Test + void readPasswordShouldThrowExceptionWhenInputExceedsMaxLength() throws IOException { + try (BufferedReader input = new BufferedReader(new StringReader("very long password"))) { + assertThatThrownBy(() -> cut.readPassword(input)) + .isInstanceOf(IOException.class) + .hasMessageContaining(Integer.toString(MAX_LENGTH)); + } + } + + + @Test + void readPasswordShouldReturnThePassword() throws IOException { + // given + final String givenPass = "pass"; + BufferedReader input = new BufferedReader(new StringReader(givenPass)); + + // when + final CharSequence result = cut.readPassword(input); + + // then + assertThat(result.toString()).isEqualTo(givenPass); + } +} \ No newline at end of file diff --git a/security/crypt-password/src/test/java/org/onap/dcaegen2/services/sdk/security/CryptPasswordTest.java b/security/crypt-password/src/test/java/org/onap/dcaegen2/services/sdk/security/CryptPasswordTest.java new file mode 100644 index 00000000..debd9afb --- /dev/null +++ b/security/crypt-password/src/test/java/org/onap/dcaegen2/services/sdk/security/CryptPasswordTest.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START==================================== + * DCAEGEN2-SERVICES-SDK + * ========================================================= + * Copyright (C) 2019 Nokia. All rights reserved. + * ========================================================= + * 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. + * ============LICENSE_END===================================== + */ + +package org.onap.dcaegen2.services.sdk.security; + + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.junit.jupiter.api.Test; + +class CryptPasswordTest { + + private final CryptPassword cut = new CryptPassword(); + + @Test + void encodedPasswordShouldMatchTheInput() { + final String rawPasswd = "some.strong.password"; + final String result = cut.encode(rawPasswd); + + assertThat(cut.matches(rawPasswd, result)).isTrue(); + } + + @Test + void testCompatibility() { + final String rawPasswd = "some.strong.password"; + final String encodedWithPreviousVersion = "$2a$10$LpP1jatprzTm9c4gX.jx7.k3.sa7Nm2aI7pe3hY/n6ZSo6g1Zye4K"; + + assertThat(cut.matches(rawPasswd, encodedWithPreviousVersion)).isTrue(); + } + + @Test + void differentPasswordShouldNotMatchTheInput() { + final String rawPasswd = "some.strong.password"; + final String result = cut.encode("different.password"); + + assertThat(cut.matches(rawPasswd, result)).isFalse(); + } +} \ No newline at end of file -- cgit 1.2.3-korg