diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..86a63dc --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ae7194d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +# Auto detect text files and perform LF normalization +* text=auto +*.txt text +*.sh text eol=lf +*.html text eol=lf diff=html +*.css text eol=lf +*.js text eol=lf +*.jpg -text +*.pdf -text +*.java text diff=java diff --git a/.github/workflows/branch-ci.yml b/.github/workflows/branch-ci.yml new file mode 100644 index 0000000..b639968 --- /dev/null +++ b/.github/workflows/branch-ci.yml @@ -0,0 +1,36 @@ +name: Branch CI + +on: + push: + paths-ignore: + - '.github/workflows/**' + - '*.md' + - '*.txt' + branches-ignore: + - 'release*' + +jobs: + build: + name: Branch CI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/cache@v1 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + server-id: github + server-username: GITHUB_ACTOR + server-password: GITHUB_TOKEN + - name: Maven Build + run: mvn clean install -DskipTests=true -Dmaven.javadoc.skip=true -Ddockerfile.skip=true -B -V + env: + GITHUB_TOKEN: ${{ secrets.ORGANIZATION_TOKEN }} + - name: Maven Verify + run: mvn verify -B diff --git a/.github/workflows/pre-release-ci.yml b/.github/workflows/pre-release-ci.yml new file mode 100644 index 0000000..664e97c --- /dev/null +++ b/.github/workflows/pre-release-ci.yml @@ -0,0 +1,37 @@ +name: Pre-release CI + +on: + release: + types: [prereleased] + +jobs: + build: + name: Pre-release CI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/cache@v1 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + server-id: github + server-username: GITHUB_ACTOR + server-password: GITHUB_TOKEN + - name: Deploy pre-release version + run: | + pre_release_version=${{ github.event.release.tag_name }} + echo Pre-release version $pre_release_version + mvn versions:set -DnewVersion=$pre_release_version -DgenerateBackupPoms=false + mvn versions:commit + mvn clean deploy -B -V + env: + GITHUB_TOKEN: ${{ secrets.ORGANIZATION_TOKEN }} + - name: Rollback pre-release (remove tag) + if: failure() + run: git push origin :refs/tags/${{ github.event.release.tag_name }} diff --git a/.github/workflows/release-ci.yml b/.github/workflows/release-ci.yml new file mode 100644 index 0000000..d674150 --- /dev/null +++ b/.github/workflows/release-ci.yml @@ -0,0 +1,60 @@ +name: Release CI + +on: + release: + types: [released] + +jobs: + build: + name: Release CI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - run: git checkout ${{ github.event.release.target_commitish }} + - uses: actions/cache@v1 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + server-id: github + server-username: GITHUB_ACTOR + server-password: GITHUB_TOKEN + - name: Maven Build + run: mvn clean install -DskipTests=true -Ddockerfile.skip=true -B -V + env: + GITHUB_TOKEN: ${{ secrets.ORGANIZATION_TOKEN }} + - name: Maven Verify + run: mvn verify -B + - name: Configure git + run: | + git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com" + git config --global user.name "${GITHUB_ACTOR}" + - name: Prepare release + id: prepare_release + run: | + mvn -B build-helper:parse-version release:prepare \ + -DreleaseVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.incrementalVersion} \ + -Darguments="-DskipTests=true -Ddockerfile.skip=true" + echo ::set-output name=release_tag::$(git describe --tags --abbrev=0) + - name: Perform release + run: mvn -B release:perform -Darguments="-DskipTests=true -Ddockerfile.skip=true" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: ${{ secrets.GITHUB_REPOSITORY }} + - name: Rollback release + if: failure() + run: | + mvn release:rollback || echo "nothing to rollback" + git push origin :refs/tags/${{ github.event.release.tag_name }} + if [ ! -z "${{ steps.prepare_release.outputs.release_tag }}" ] + then + git tag -d ${{ steps.prepare_release.outputs.release_tag }} + git push origin :refs/tags/${{ steps.prepare_release.outputs.release_tag }} + fi diff --git a/.gitignore b/.gitignore index 6f068f4..7cab252 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,13 @@ -# everything that starts with dot (hidden files) .* -# except this file !.gitignore -# except this file-extention +!.gitattributes +!.github +!.editorconfig !.*.yml - -# Build targets +!.env.example **/target/ - -# logs and reports +*.iml +**/logs/*.log +*.db *.csv *.log -*.zip - -# IntelliJ IDEA project files and directories -*.iml - -**/pom.xml.releaseBackup -/release.properties diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c02c943..0000000 --- a/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -addons: - apt: - packages: - - libxml-xpath-perl -sudo: required -language: java -jdk: openjdk11 -before_install: -- "./src/main/scripts/ci/before-install.sh" -- "./src/main/scripts/cd/before-deploy.sh" -script: "mvn verify -B" -after_success: "./src/main/scripts/ci/after-success.sh" -deploy: -- provider: script - script: - - "./src/main/scripts/cd/deploy.sh" - on: - branch: develop -- provider: script - script: - - "./src/main/scripts/cd/release.sh" - on: - branch: master -- provider: script - script: - - "./src/main/scripts/cd/release.sh" - on: - tags: true diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 0000000..f43e7a0 --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,17 @@ +extends: default +rules: + document-start: + present: false + truthy: disable + comments: + min-spaces-from-content: 1 + line-length: + max: 150 + braces: + min-spaces-inside: 0 + max-spaces-inside: 0 + brackets: + min-spaces-inside: 0 + max-spaces-inside: 0 + indentation: + indent-sequences: consistent diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/jwt/pom.xml b/jwt/pom.xml index 2907bb9..2f4ad83 100644 --- a/jwt/pom.xml +++ b/jwt/pom.xml @@ -1,4 +1,6 @@ - + 4.0.0 diff --git a/pom.xml b/pom.xml index b113fff..2642638 100644 --- a/pom.xml +++ b/pom.xml @@ -1,24 +1,43 @@ - - + 4.0.0 io.scalecube scalecube-parent-pom - 0.1.0-RC1 + 0.2.17 scalecube-security-parent 1.0.12-SNAPSHOT pom - ScaleCube Security + + + github + GitHub Packages + https://maven.pkg.github.com/scalecube/packages + + false + + + + + + + github + GitHub Packages + https://maven.pkg.github.com/scalecube/scalecube-security + + + - https://github.com/scalecube/scalecube-security - scm:git:git@github.com:scalecube/scalecube-security.git - scm:git:git@github.com:scalecube/scalecube-security.git + https://github.com/scalecube/scalecube + scm:git:https://github.com/scalecube/scalecube-security.git + scm:git:https://github.com/scalecube/scalecube-security.git HEAD @@ -30,14 +49,20 @@ 0.11.1 - Dysprosium-SR7 - 5.1.1 - 2.24.5 + Dysprosium-SR9 + 2.11.0 + 1.7.30 + + 3.1.0 1.3 + 5.4.2 + 5.0.0 + 1.14.0 + io.projectreactor reactor-bom @@ -45,6 +70,13 @@ pom import + + + org.slf4j + slf4j-api + ${slf4j.version} + + io.jsonwebtoken jjwt-api @@ -60,6 +92,14 @@ jjwt-jackson ${jjwt.version} + + + com.fasterxml.jackson + jackson-bom + ${jackson.version} + pom + import + @@ -68,19 +108,13 @@ org.junit.jupiter junit-jupiter-engine - ${junit.version} + ${junit-jupiter.version} test org.junit.jupiter junit-jupiter-params - ${junit.version} - test - - - org.mockito - mockito-junit-jupiter - ${mockito.version} + ${junit-jupiter.version} test diff --git a/src/main/scripts/cd/before-deploy.sh b/src/main/scripts/cd/before-deploy.sh deleted file mode 100755 index 74c5259..0000000 --- a/src/main/scripts/cd/before-deploy.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env bash - -DIRNAME=$(dirname $0) -BEFORE_DEPLOY_EXEC_FILES=$(find $DIRNAME -name 'before-deploy-*.sh') - -echo Running $0 -echo *-*-*-*-*-*-*-*-*-*-*-*-*-* - -decryptsecrets() { - echo decrypting secrets - echo *-*-*-*-*-*-*-*-*-*-*-* - mkdir -p ~/tmp - openssl aes-256-cbc -K $encrypted_SOME_key -iv $encrypted_SOME_iv -in $TRAVIS_BUILD_DIR/src/main/scripts/cd/secrets.tar.enc -out ~/tmp/secrets.tar -d - md5sum ~/tmp/secrets.tar - tar -xvf ~/tmp/secrets.tar -C ~/.ssh - shred -z -u ~/tmp/secrets.tar -} - -importpgp() { - echo importing pgp secret - echo *-*-*-*-*-*-*-*-*-*-*-* - eval $(gpg-agent --daemon --batch) - gpg --batch --passphrase $GPG_PASSPHRASE --import ~/.ssh/codesigning.asc - shred -z -u ~/.ssh/codesigning.asc -} - -setupssh() { - echo importing ssh secret - echo *-*-*-*-*-*-*-*-*-*-*-* - chmod 400 ~/.ssh/id_rsa - touch ~/.ssh/config - - echo "Host github.com" >> $HOME/.ssh/config - echo " IdentityFile $HOME/.ssh/id_rsa" >> $HOME/.ssh/config - echo " StrictHostKeyChecking no" >> $HOME/.ssh/config - - eval "$(ssh-agent -s)" - ssh-add ~/.ssh/id_rsa - ssh -T git@github.com | true -} - -setupgit() { - echo setting git up - echo *-*-*-*-*-*-*-*-*-*-*-* - git remote set-url origin git@github.com:$TRAVIS_REPO_SLUG.git - git config --global user.email "io.scalecube.ci@gmail.com" - git config --global user.name "io-scalecube-ci" - git checkout -B $TRAVIS_BRANCH | true -} - -deployment() { - if [ "$TRAVIS_PULL_REQUEST" = 'false' -a "$TRAVIS_BRANCH" = 'master' -o "$TRAVIS_BRANCH" = 'develop' -o -n "$TRAVIS_TAG" ]; then - echo deployment - echo *-*-*-*-*-*-*-*-*-*-*-* - decryptsecrets - importpgp - setupssh - setupgit - fi -} - -deployment - -# extends before-deploy.sh -for script_file in $BEFORE_DEPLOY_EXEC_FILES; do - . $script_file -done diff --git a/src/main/scripts/cd/deploy.sh b/src/main/scripts/cd/deploy.sh deleted file mode 100755 index 81bdffb..0000000 --- a/src/main/scripts/cd/deploy.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env sh - -DIRNAME=$(dirname $0) -DEPLOY_EXEC_FILES=$(find $DIRNAME -name 'deploy-*.sh') - -echo Running $0 -echo *-*-*-*-*-*-*-*-*-*-*-*-*-* - -mvn -P release deploy -Darguments=-DskipTests -B -V -s travis-settings.xml -pip install --user -r requirements.txt -$(dirname $0)/external_build.sh - -# extends deploy.sh -for script_file in $DEPLOY_EXEC_FILES; do - . $script_file -done - diff --git a/src/main/scripts/cd/external_build.sh b/src/main/scripts/cd/external_build.sh deleted file mode 100755 index 9d34224..0000000 --- a/src/main/scripts/cd/external_build.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python - -import requests -import urlparse -import json -import time -import sys -import os - -class TravisBuilds: - """ - This class provides requests to builds and check their statuses - """ - travis_api_url = 'https://api.travis-ci.org/' - build_id = None - - def __init__(self, repo_name, auth_token): - self.headers = {'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Travis-API-Version': '3', - 'Authorization': 'token {}'.format(auth_token) - } - self.repo_name = repo_name - - def start_build(self): - data = {"request": { - "branch": "master" - }} - url = urlparse.urljoin(self.travis_api_url, - 'repo/{}/requests'.format(self.repo_name)) - response = requests.post(url=url, data=json.dumps(data), headers=self.headers) - if response.status_code == 202: - self.build_id = self.get_build_id(response.json()["request"]["id"]) - print self.build_id - return True - - def get_build_id(self, request_id): - time.sleep(10) - url = urlparse.urljoin(self.travis_api_url, - 'repo/{}/request/{}'.format(self.repo_name, request_id)) - response = requests.get(url=url, headers=self.headers) - return response.json()["builds"][0]['id'] - - def wait_for_build_result(self): - attempts = 0 - tests_minutes = int(os.getenv('TESTS_MINUTES')) - while attempts < tests_minutes: - url = urlparse.urljoin(self.travis_api_url, 'build/{}'.format(self.build_id)) - response = requests.get(url=url, headers=self.headers) - if response.json()['state'] == "passed": - return True - else: - print "External build is running {} minutes".format(attempts) - time.sleep(60) - attempts += 1 - return False - - -if __name__ == '__main__': - external_build = os.getenv('TRIGGER_EXTERNAL_CI', '') - if external_build: - travis = TravisBuilds(external_build, os.getenv('TRAVIS_AUTH_TOKEN')) - build = travis.start_build() - result = travis.wait_for_build_result() - if result: - sys.exit(0) - sys.exit(1) - sys.exit(0) diff --git a/src/main/scripts/cd/release.sh b/src/main/scripts/cd/release.sh deleted file mode 100755 index 9f3eb77..0000000 --- a/src/main/scripts/cd/release.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env sh - -DIRNAME=$(dirname $0) -RELEASE_EXEC_FILES=$(find $DIRNAME -name 'release-*.sh') - -echo Running $0 -echo *-*-*-*-*-*-*-*-*-*-*-*-*-* - -. $DIRNAME/before-deploy.sh - -commit_to_develop() { - git fetch - git branch -r - git checkout -B develop - git rebase $TRAVIS_BRANCH - git commit --amend -m "++++ Prepare for next development iteration build: $TRAVIS_BUILD_NUMBER ++++" - git push origin develop -} - -check_next_version() { - export NEXT_VERSION=$(echo $TRAVIS_COMMIT_MESSAGE | grep -E -o '[0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT') - if [ -n "$NEXT_VERSION" ] ; then - export MVN_NEXT_VERSION=-DdevelopmentVersion=$NEXT_VERSION - fi -} - -check_tag_for_rc() { - export VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) - if [ -n "$TRAVIS_TAG" ] ; then - RC_VER=$(echo $TRAVIS_TAG | grep -E -o 'RC-?[0-9]+') - RC_PREPARE=$(echo $TRAVIS_TAG | grep -o -i 'prepare') - if [ -n "$RC_VER" -a -n "$RC_PREPARE" ] ; then - export NEW_RC_VERSION=$(echo $VERSION | sed "s/SNAPSHOT/$RC_VER/g") - echo Release candidate: $NEW_RC_VERSION - echo *-*-*-*-*-*-*-*-*-*-*-* - decryptsecrets - importpgp - setupssh - setupgit - export MVN_RELEASE_VERSION=-DreleaseVersion=$NEW_RC_VERSION - if [ -n "$MVN_NEXT_VERSION" ] ; then - export MVN_NEXT_VERSION=-DdevelopmentVersion=$VERSION; - fi - fi - fi -} - -check_next_version -check_tag_for_rc - -mvn -P release -Darguments=-DskipTests release:prepare release:perform $MVN_RELEASE_VERSION $MVN_NEXT_VERSION -DautoVersionSubmodules=true -DscmCommentPrefix="$TRAVIS_COMMIT_MESSAGE [skip ci] " -B -V -s travis-settings.xml || exit 126 - -mvn -B -q clean - -if [ -z "$NEW_RC_VERSION" ]; then - commit_to_develop -fi - -# extends release.sh -for script_file in $RELEASE_EXEC_FILES; do - . $script_file -done diff --git a/src/main/scripts/cd/secrets.tar.enc b/src/main/scripts/cd/secrets.tar.enc deleted file mode 100755 index 606b766..0000000 Binary files a/src/main/scripts/cd/secrets.tar.enc and /dev/null differ diff --git a/src/main/scripts/ci/after-success.sh b/src/main/scripts/ci/after-success.sh deleted file mode 100755 index 20a24d4..0000000 --- a/src/main/scripts/ci/after-success.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -DIRNAME=$(dirname $0) -AFTER_SUCCESS_EXEC_FILES=$(find $DIRNAME -name 'after-success-*.sh') - -echo Running $0 -echo *-*-*-*-*-*-*-*-*-*-*-*-*-* - -if [ -z "$CODACY_PROJECT_TOKEN" ]; then - echo [WARNING] Please go to https://app.codacy.com/app/$TRAVIS_REPO_SLUG/settings/coverage and add CODACY_PROJECT_TOKEN to travis settings -else - find -name jacoco.xml | xargs -i java -jar ~/codacy-coverage-reporter-assembly.jar report -l Java --partial -r {} - java -jar ~/codacy-coverage-reporter-assembly.jar final -fi; - -# extends after-success.sh -for script_file in $AFTER_SUCCESS_EXEC_FILES; do - . $script_file -done - diff --git a/src/main/scripts/ci/before-install.sh b/src/main/scripts/ci/before-install.sh deleted file mode 100755 index 49f7a9d..0000000 --- a/src/main/scripts/ci/before-install.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -DIRNAME=$(dirname $0) -BEFORE_INSTALL_EXEC_FILES=$(find $DIRNAME -name 'before-install-*.sh') - -echo Running $0 -echo *-*-*-*-*-*-*-*-*-*-*-*-*-* - -echo logging to docker image repository: -echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin - -# get latest version of codacy reporter from sonatype -latest=$(curl "https://oss.sonatype.org/service/local/repositories/releases/content/com/codacy/codacy-coverage-reporter/maven-metadata.xml" | xpath -e "/metadata/versioning/release/text()") - -echo Downloading latest version $latest of codacy reporter from sonatype -# download latest assembly jar -mvn -B -q dependency:get dependency:copy \ - -DoutputDirectory=$HOME \ - -DoutputAbsoluteArtifactFilename=true \ - -Dmdep.stripVersion=true \ - -DrepoUrl=https://oss.sonatype.org/service/local/repositories/releases/content/ \ - -Dartifact=com.codacy:codacy-coverage-reporter:$latest:jar:assembly - -echo local file md5sum: -md5sum ~/codacy-coverage-reporter-assembly.jar -echo remote file md5sum: -curl "https://oss.sonatype.org/service/local/repositories/releases/content/com/codacy/codacy-coverage-reporter/$latest/codacy-coverage-reporter-$latest-assembly.jar.md5" - -# extends before-install.sh -for script_file in $BEFORE_INSTALL_EXEC_FILES; do - . $script_file -done - diff --git a/tokens/pom.xml b/tokens/pom.xml index b001f93..a8cc237 100644 --- a/tokens/pom.xml +++ b/tokens/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 @@ -10,63 +12,6 @@ scalecube-security-tokens - - 0.11.1 - - Dysprosium-SR7 - 2.11.0 - 1.7.30 - - 5.4.2 - 5.0.0 - 1.14.0 - 3.1.0 - - exberry-io/${project.artifactId} - - - - - - - io.jsonwebtoken - jjwt-api - ${jjwt.version} - - - io.jsonwebtoken - jjwt-impl - ${jjwt.version} - - - io.jsonwebtoken - jjwt-jackson - ${jjwt.version} - - - - com.fasterxml.jackson - jackson-bom - ${jackson.version} - pom - import - - - - io.projectreactor - reactor-bom - ${reactor.version} - pom - import - - - org.slf4j - slf4j-api - ${slf4j.version} - - - - io.jsonwebtoken @@ -84,12 +29,11 @@ io.projectreactor reactor-core - org.slf4j slf4j-api - + org.junit.jupiter junit-jupiter @@ -114,18 +58,6 @@ ${mockito.version} test - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - test - - - org.junit.jupiter - junit-jupiter-params - ${junit-jupiter.version} - test - diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/vault/VaultJwk.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwkInfo.java similarity index 60% rename from tokens/src/main/java/io/scalecube/security/tokens/jwt/vault/VaultJwk.java rename to tokens/src/main/java/io/scalecube/security/tokens/jwt/JwkInfo.java index c2eccc2..25cb6c8 100644 --- a/tokens/src/main/java/io/scalecube/security/tokens/jwt/vault/VaultJwk.java +++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwkInfo.java @@ -1,9 +1,9 @@ -package io.scalecube.security.tokens.jwt.vault; +package io.scalecube.security.tokens.jwt; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.StringJoiner; -public class VaultJwk { +public class JwkInfo { private String use; private String kty; @@ -16,12 +16,26 @@ public class VaultJwk { @JsonProperty("e") private String exponent; // e + public JwkInfo() {} + /** - * Serialization only constructor. + * Constructor. * - * @deprecated not to be used + * @param use use + * @param kty kty + * @param kid kid + * @param alg alg + * @param modulus modulus + * @param exponent exponent */ - public VaultJwk() {} + public JwkInfo(String use, String kty, String kid, String alg, String modulus, String exponent) { + this.use = use; + this.kty = kty; + this.kid = kid; + this.alg = alg; + this.modulus = modulus; + this.exponent = exponent; + } public String use() { return use; @@ -49,7 +63,7 @@ public String exponent() { @Override public String toString() { - return new StringJoiner(", ", VaultJwk.class.getSimpleName() + "[", "]") + return new StringJoiner(", ", JwkInfo.class.getSimpleName() + "[", "]") .add("use='" + use + "'") .add("kty='" + kty + "'") .add("kid='" + kid + "'") diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwkInfoList.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwkInfoList.java new file mode 100644 index 0000000..d0c33bb --- /dev/null +++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwkInfoList.java @@ -0,0 +1,28 @@ +package io.scalecube.security.tokens.jwt; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.StringJoiner; + +public class JwkInfoList { + + private List keys = Collections.emptyList(); + + public JwkInfoList() {} + + public JwkInfoList(List keys) { + this.keys = new ArrayList<>(keys); + } + + public List keys() { + return keys; + } + + @Override + public String toString() { + return new StringJoiner(", ", JwkInfoList.class.getSimpleName() + "[", "]") + .add("keys=" + keys) + .toString(); + } +} diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwksKeyProvider.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwksKeyProvider.java new file mode 100644 index 0000000..a3edcc6 --- /dev/null +++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/JwksKeyProvider.java @@ -0,0 +1,114 @@ +package io.scalecube.security.tokens.jwt; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.Key; +import java.time.Duration; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Scheduler; +import reactor.core.scheduler.Schedulers; + +public final class JwksKeyProvider implements KeyProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(JwksKeyProvider.class); + + private final Scheduler scheduler = Schedulers.newSingle("jwks-key-provider", true); + + private final ObjectMapper mapper; + private final String jwksUri; + private final long connectTimeoutMillis; + private final long readTimeoutMillis; + + /** + * Constructor. + * + * @param jwksUri jwksUri + */ + public JwksKeyProvider(String jwksUri) { + this.jwksUri = jwksUri; + this.mapper = initMapper(); + this.connectTimeoutMillis = Duration.ofSeconds(10).toMillis(); + this.readTimeoutMillis = Duration.ofSeconds(10).toMillis(); + } + + /** + * Constructor. + * + * @param jwksUri jwksUri + * @param connectTimeout connectTimeout + * @param readTimeout readTimeout + */ + public JwksKeyProvider(String jwksUri, Duration connectTimeout, Duration readTimeout) { + this.jwksUri = jwksUri; + this.mapper = initMapper(); + this.connectTimeoutMillis = connectTimeout.toMillis(); + this.readTimeoutMillis = readTimeout.toMillis(); + } + + @Override + public Mono findKey(String kid) { + return Mono.defer(this::callJwksUri) + .map(this::toKeyList) + .flatMap(list -> Mono.justOrEmpty(findRsaKey(list, kid))) + .switchIfEmpty(Mono.error(new KeyProviderException("Key was not found, kid: " + kid))) + .doOnSubscribe(s -> LOGGER.debug("[findKey] Looking up key in jwks, kid: {}", kid)) + .subscribeOn(scheduler) + .publishOn(scheduler); + } + + private Mono callJwksUri() { + return Mono.fromCallable( + () -> { + HttpURLConnection httpClient = (HttpURLConnection) new URL(jwksUri).openConnection(); + httpClient.setConnectTimeout((int) connectTimeoutMillis); + httpClient.setReadTimeout((int) readTimeoutMillis); + + int responseCode = httpClient.getResponseCode(); + if (responseCode != 200) { + LOGGER.error("[callJwksUri][{}] Not expected response code: {}", jwksUri, responseCode); + throw new KeyProviderException("Not expected response code: " + responseCode); + } + + return httpClient.getInputStream(); + }); + } + + private JwkInfoList toKeyList(InputStream stream) { + try (InputStream inputStream = new BufferedInputStream(stream)) { + return mapper.readValue(inputStream, JwkInfoList.class); + } catch (IOException e) { + LOGGER.error("[toKeyList] Exception occurred: {}", e.toString()); + throw new KeyProviderException(e); + } + } + + private Optional findRsaKey(JwkInfoList list, String kid) { + return list.keys().stream() + .filter(k -> kid.equals(k.kid())) + .findFirst() + .map(info -> Utils.getRsaPublicKey(info.modulus(), info.exponent())); + } + + private static ObjectMapper initMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + mapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true); + mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + return mapper; + } +} diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/KeyProviderException.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/KeyProviderException.java new file mode 100644 index 0000000..512eab3 --- /dev/null +++ b/tokens/src/main/java/io/scalecube/security/tokens/jwt/KeyProviderException.java @@ -0,0 +1,28 @@ +package io.scalecube.security.tokens.jwt; + +public final class KeyProviderException extends RuntimeException { + + public KeyProviderException() {} + + public KeyProviderException(String s) { + super(s); + } + + public KeyProviderException(String s, Throwable throwable) { + super(s, throwable); + } + + public KeyProviderException(Throwable throwable) { + super(throwable); + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "{errorMessage=" + getMessage() + '}'; + } +} diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/vault/VaultJwkList.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/vault/VaultJwkList.java deleted file mode 100644 index 029dba0..0000000 --- a/tokens/src/main/java/io/scalecube/security/tokens/jwt/vault/VaultJwkList.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.scalecube.security.tokens.jwt.vault; - -import java.util.List; -import java.util.StringJoiner; - -public class VaultJwkList { - - private List keys; - - /** - * Serialization only constructor. - * - * @deprecated not to be used - */ - public VaultJwkList() {} - - public List keys() { - return keys; - } - - @Override - public String toString() { - return new StringJoiner(", ", VaultJwkList.class.getSimpleName() + "[", "]") - .add("keys=" + keys) - .toString(); - } -} diff --git a/tokens/src/main/java/io/scalecube/security/tokens/jwt/vault/VaultJwksKeyProvider.java b/tokens/src/main/java/io/scalecube/security/tokens/jwt/vault/VaultJwksKeyProvider.java deleted file mode 100644 index 16e308c..0000000 --- a/tokens/src/main/java/io/scalecube/security/tokens/jwt/vault/VaultJwksKeyProvider.java +++ /dev/null @@ -1,86 +0,0 @@ -package io.scalecube.security.tokens.jwt.vault; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import io.scalecube.security.tokens.jwt.KeyProvider; -import io.scalecube.security.tokens.jwt.Utils; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.net.http.HttpResponse.BodyHandlers; -import java.security.Key; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import reactor.core.Exceptions; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Scheduler; -import reactor.core.scheduler.Schedulers; - -public final class VaultJwksKeyProvider implements KeyProvider { - - private static final Logger LOGGER = LoggerFactory.getLogger(VaultJwksKeyProvider.class); - - private final Scheduler scheduler = Schedulers.newSingle("vault-jwks", true); - - private final ObjectMapper mapper; - - private final String jwksUri; - - public VaultJwksKeyProvider(String jwksUri) { - this.jwksUri = jwksUri; - this.mapper = initMapper(); - } - - @Override - public Mono findKey(String kid) { - return Mono.defer(this::callJwksUri) - .map(stream -> toRsaKey(stream, kid)) - .doOnSubscribe(s -> LOGGER.debug("[findKey] Looking up key in jwks, kid: {}", kid)) - .subscribeOn(scheduler); - } - - private Mono callJwksUri() { - HttpClient client = HttpClient.newHttpClient(); - HttpRequest request = HttpRequest.newBuilder().uri(URI.create(jwksUri)).build(); - return Mono.fromFuture( - client.sendAsync(request, BodyHandlers.ofInputStream()).thenApply(HttpResponse::body)); - } - - private Key toRsaKey(InputStream stream, String kid) { - return getKeyList(stream).keys().stream() - .filter(k -> kid.equals(k.kid())) - .filter(k -> "RSA".equals(k.kty())) // RSA - .filter(k -> "sig".equals(k.use())) // signature - .findFirst() - .map(vaultJwk -> Utils.getRsaPublicKey(vaultJwk.modulus(), vaultJwk.exponent())) - .orElseThrow(() -> new RuntimeException("Key was not found, kid: " + kid)); - } - - private VaultJwkList getKeyList(InputStream stream) { - VaultJwkList list; - try { - list = mapper.readValue(stream, VaultJwkList.class); - } catch (IOException e) { - throw Exceptions.propagate(e); - } - return list; - } - - private static ObjectMapper initMapper() { - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); - mapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true); - mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); - mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - return mapper; - } -} diff --git a/tokens/src/test/java/com/om2/exchange/tokens/jwt/BaseTest.java b/tokens/src/test/java/io/scalecube/security/tokens/jwt/BaseTest.java similarity index 96% rename from tokens/src/test/java/com/om2/exchange/tokens/jwt/BaseTest.java rename to tokens/src/test/java/io/scalecube/security/tokens/jwt/BaseTest.java index 472469c..7058ece 100644 --- a/tokens/src/test/java/com/om2/exchange/tokens/jwt/BaseTest.java +++ b/tokens/src/test/java/io/scalecube/security/tokens/jwt/BaseTest.java @@ -1,4 +1,4 @@ -package com.om2.exchange.tokens.jwt; +package io.scalecube.security.tokens.jwt; import java.lang.reflect.Method; import java.time.Duration; diff --git a/tokens/src/test/java/com/om2/exchange/tokens/jwt/vault/VaultJwksKeyProviderTests.java b/tokens/src/test/java/io/scalecube/security/tokens/jwt/JwksKeyProviderTests.java similarity index 95% rename from tokens/src/test/java/com/om2/exchange/tokens/jwt/vault/VaultJwksKeyProviderTests.java rename to tokens/src/test/java/io/scalecube/security/tokens/jwt/JwksKeyProviderTests.java index ee7feb2..94b2105 100644 --- a/tokens/src/test/java/com/om2/exchange/tokens/jwt/vault/VaultJwksKeyProviderTests.java +++ b/tokens/src/test/java/io/scalecube/security/tokens/jwt/JwksKeyProviderTests.java @@ -1,16 +1,14 @@ -package com.om2.exchange.tokens.jwt.vault; +package io.scalecube.security.tokens.jwt; import com.bettercloud.vault.json.Json; import com.bettercloud.vault.rest.Rest; import com.bettercloud.vault.rest.RestException; import com.bettercloud.vault.rest.RestResponse; -import com.om2.exchange.tokens.jwt.BaseTest; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Header; import io.jsonwebtoken.Jwt; import io.jsonwebtoken.JwtParserBuilder; import io.jsonwebtoken.Jwts; -import io.scalecube.security.tokens.jwt.vault.VaultJwksKeyProvider; import java.io.IOException; import java.util.UUID; import org.junit.jupiter.api.AfterAll; @@ -22,7 +20,7 @@ import org.testcontainers.vault.VaultContainer; import reactor.test.StepVerifier; -class VaultJwksKeyProviderTests extends BaseTest { +class JwksKeyProviderTests extends BaseTest { private static final String VAULT_TOKEN = "test"; private static final String VAULT_TOKEN_HEADER = "X-Vault-Token"; @@ -54,14 +52,14 @@ void testJwksKeysRetrieval() throws RestException, IOException, InterruptedExcep String token = generateIdentityToken(clientToken, roleName); // oidc/token String kid = getKid(token); - VaultJwksKeyProvider keyProvider = new VaultJwksKeyProvider(jwksUri(vaultAddr)); + JwksKeyProvider keyProvider = new JwksKeyProvider(jwksUri(vaultAddr)); StepVerifier.create(keyProvider.findKey(kid)).expectNextCount(1).expectComplete().verify(); } @Test void testJwksKeysRetrievalKeyNotFound() { - VaultJwksKeyProvider keyProvider = new VaultJwksKeyProvider(jwksUri(vaultAddr)); + JwksKeyProvider keyProvider = new JwksKeyProvider(jwksUri(vaultAddr)); StepVerifier.create(keyProvider.findKey(UUID.randomUUID().toString())) .expectErrorMatches( diff --git a/tokens/src/test/java/com/om2/exchange/tokens/jwt/JwtTokenResolverTests.java b/tokens/src/test/java/io/scalecube/security/tokens/jwt/JwtTokenResolverTests.java similarity index 93% rename from tokens/src/test/java/com/om2/exchange/tokens/jwt/JwtTokenResolverTests.java rename to tokens/src/test/java/io/scalecube/security/tokens/jwt/JwtTokenResolverTests.java index e7af519..0a7129d 100644 --- a/tokens/src/test/java/com/om2/exchange/tokens/jwt/JwtTokenResolverTests.java +++ b/tokens/src/test/java/io/scalecube/security/tokens/jwt/JwtTokenResolverTests.java @@ -1,11 +1,5 @@ -package com.om2.exchange.tokens.jwt; - -import io.scalecube.security.tokens.jwt.JwtToken; -import io.scalecube.security.tokens.jwt.JwtTokenParser; -import io.scalecube.security.tokens.jwt.JwtTokenParserFactory; -import io.scalecube.security.tokens.jwt.JwtTokenResolverImpl; -import io.scalecube.security.tokens.jwt.KeyProvider; -import io.scalecube.security.tokens.jwt.Utils; +package io.scalecube.security.tokens.jwt; + import java.io.IOException; import java.security.Key; import java.util.Collections; @@ -19,7 +13,7 @@ class JwtTokenResolverTests extends BaseTest { - public static final Map BODY = Collections.singletonMap("aud", "aud"); + private static final Map BODY = Collections.singletonMap("aud", "aud"); @Test void testTokenResolver() throws IOException { diff --git a/travis-settings.xml b/travis-settings.xml deleted file mode 100644 index 369079d..0000000 --- a/travis-settings.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - skipstyle - - true - - - - skippmd - - true - - - - bintray - - - central - bintray - https://jcenter.bintray.com - - false - - - - - - ossrh - - ${env.GPG_KEY} - - - - - - ossrh - ${env.SONATYPE_USERNAME} - ${env.SONATYPE_PASSWORD} - - - docker.io - ${env.DOCKER_USERNAME} - ${env.DOCKER_PASSWORD} - - - - bintray - ossrh - -