mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-30 18:17:55 +00:00 
			
		
		
		
	[QTI-308] Add Enos integration tests (#16760)
Add our initial Enos integration tests to Vault. The Enos scenario workflow will automatically be run on branches that are created from the `hashicorp/vault` repository. See the README.md in ./enos a full description of how to compose and execute scenarios locally. * Simplify the metadata build workflow jobs * Automatically determine the Go version from go.mod * Add formatting check for Enos integration scenarios * Add Enos smoke and upgrade integration scenarios * Add Consul backend matrix support * Add Ubuntu and RHEL distro support * Add Vault edition support * Add Vault architecture support * Add Vault builder support * Add Vault Shamir and awskms auto-unseal support * Add Raft storage support * Add Raft auto-join voter verification * Add Vault version verification * Add Vault seal verification * Add in-place upgrade support for all variants * Add four scenario variants to CI. These test a maximal distribution of the aforementioned variants with the `linux/amd64` Vault install bundle. Signed-off-by: Ryan Cragun <me@ryan.ec> Co-authored-by: Rebecca Willett <rwillett@hashicorp.com> Co-authored-by: Jaymala <jaymalasinha@gmail.com>
This commit is contained in:
		
							
								
								
									
										105
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										105
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -12,35 +12,31 @@ env: | |||||||
|   GO_TAGS: "ui" |   GO_TAGS: "ui" | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   get-product-version: |  | ||||||
|  |   product-metadata: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     outputs: |     outputs: | ||||||
|       product-version: ${{ steps.get-product-version.outputs.product-version }} |       product-version: ${{ steps.get-product-version.outputs.product-version }} | ||||||
|       product-base-version: ${{ steps.get-product-version.outputs.product-base-version }} |       product-base-version: ${{ steps.get-product-version.outputs.product-base-version }} | ||||||
|  |       build-date: ${{ steps.get-build-date.outputs.build-date }} | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v2 |       - uses: actions/checkout@v3 | ||||||
|       - name: get product version |       - uses: actions/setup-go@v3 | ||||||
|  |       - name: Get product version | ||||||
|         id: get-product-version |         id: get-product-version | ||||||
|         run: | |         run: | | ||||||
|           make version |           make version | ||||||
|           IFS="-" read BASE_VERSION _other <<< "$(make version)" |           IFS="-" read BASE_VERSION _other <<< "$(make version)" | ||||||
|           echo "::set-output name=product-version::$(make version)" |           echo "::set-output name=product-version::$(make version)" | ||||||
|           echo "::set-output name=product-base-version::${BASE_VERSION}" |           echo "::set-output name=product-base-version::${BASE_VERSION}" | ||||||
|  |       - name: Get build date | ||||||
|   get-build-date: |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     outputs: |  | ||||||
|       build-date: ${{ steps.get-build-date.outputs.build-date }} |  | ||||||
|     steps: |  | ||||||
|       - uses: actions/checkout@v2 |  | ||||||
|       - name: get build date |  | ||||||
|         id: get-build-date |         id: get-build-date | ||||||
|         run: | |         run: | | ||||||
|           make build-date |           make build-date | ||||||
|           echo "::set-output name=build-date::$(make build-date)" |           echo "::set-output name=build-date::$(make build-date)" | ||||||
|  |  | ||||||
|   generate-metadata-file: |   generate-metadata-file: | ||||||
|     needs: get-product-version |     needs: product-metadata | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     outputs: |     outputs: | ||||||
|       filepath: ${{ steps.generate-metadata-file.outputs.filepath }} |       filepath: ${{ steps.generate-metadata-file.outputs.filepath }} | ||||||
| @@ -51,22 +47,20 @@ jobs: | |||||||
|         id: generate-metadata-file |         id: generate-metadata-file | ||||||
|         uses: hashicorp/actions-generate-metadata@v1 |         uses: hashicorp/actions-generate-metadata@v1 | ||||||
|         with: |         with: | ||||||
|           version: ${{ needs.get-product-version.outputs.product-version }} |           version: ${{ needs.product-metadata.outputs.product-version }} | ||||||
|           product: ${{ env.PKG_NAME }} |           product: ${{ env.PKG_NAME }} | ||||||
|  |  | ||||||
|       - uses: actions/upload-artifact@v2 |       - uses: actions/upload-artifact@v2 | ||||||
|         with: |         with: | ||||||
|           name: metadata.json |           name: metadata.json | ||||||
|           path: ${{ steps.generate-metadata-file.outputs.filepath }} |           path: ${{ steps.generate-metadata-file.outputs.filepath }} | ||||||
|  |  | ||||||
|   build-other: |   build-other: | ||||||
|     needs: [ get-product-version, get-build-date ] |     needs: [ product-metadata ] | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     strategy: |     strategy: | ||||||
|       matrix: |       matrix: | ||||||
|         goos: [ freebsd, windows, netbsd, openbsd, solaris ] |         goos: [ freebsd, windows, netbsd, openbsd, solaris ] | ||||||
|         goarch: [ "386", "amd64", "arm" ] |         goarch: [ "386", "amd64", "arm" ] | ||||||
|         go: [ "1.18.4" ] |  | ||||||
|         exclude: |         exclude: | ||||||
|           - goos: solaris |           - goos: solaris | ||||||
|             goarch: 386 |             goarch: 386 | ||||||
| @@ -76,14 +70,14 @@ jobs: | |||||||
|             goarch: arm |             goarch: arm | ||||||
|       fail-fast: true |       fail-fast: true | ||||||
|  |  | ||||||
|     name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build |     name: Go ${{ matrix.goos }} ${{ matrix.goarch }} build | ||||||
|  |  | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v2 |       - uses: actions/checkout@v2 | ||||||
|       - name: Setup go |       - name: Setup go | ||||||
|         uses: actions/setup-go@v2 |         uses: actions/setup-go@v3 | ||||||
|         with: |         with: | ||||||
|           go-version: ${{ matrix.go }} |           go-version-file: go.mod | ||||||
|       - name: Setup node and yarn |       - name: Setup node and yarn | ||||||
|         uses: actions/setup-node@v2 |         uses: actions/setup-node@v2 | ||||||
|         with: |         with: | ||||||
| @@ -104,32 +98,31 @@ jobs: | |||||||
|           CGO_ENABLED: 0 |           CGO_ENABLED: 0 | ||||||
|         run: | |         run: | | ||||||
|           mkdir dist out |           mkdir dist out | ||||||
|           GO_TAGS="${{ env.GO_TAGS }}" VAULT_VERSION=${{ needs.get-product-version.outputs.product-base-version }} VAULT_REVISION="$(git rev-parse HEAD)" VAULT_BUILD_DATE="${{ needs.get-build-date.outputs.build-date }}" make build |           GO_TAGS="${{ env.GO_TAGS }}" VAULT_VERSION=${{ needs.product-metadata.outputs.product-base-version }} VAULT_REVISION="$(git rev-parse HEAD)" VAULT_BUILD_DATE="${{ needs.get-build-date.outputs.build-date }}" make build | ||||||
|           zip -r -j out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ |           zip -r -j out/${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ | ||||||
|       - uses: actions/upload-artifact@v2 |       - uses: actions/upload-artifact@v2 | ||||||
|         with: |         with: | ||||||
|           name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip |           name: ${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip | ||||||
|           path: out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip |           path: out/${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip | ||||||
|  |  | ||||||
|   build-linux: |   build-linux: | ||||||
|     needs: [ get-product-version, get-build-date ] |     needs: [ product-metadata ] | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     strategy: |     strategy: | ||||||
|       matrix: |       matrix: | ||||||
|         goos: [linux] |         goos: [linux] | ||||||
|         goarch: ["arm", "arm64", "386", "amd64"] |         goarch: ["arm", "arm64", "386", "amd64"] | ||||||
|         go: ["1.18.4"] |  | ||||||
|       fail-fast: true |       fail-fast: true | ||||||
|  |  | ||||||
|     name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build |     name: Go ${{ matrix.goos }} ${{ matrix.goarch }} build | ||||||
|  |  | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v2 |       - uses: actions/checkout@v2 | ||||||
|  |  | ||||||
|       - name: Setup go |       - name: Setup go | ||||||
|         uses: actions/setup-go@v2 |         uses: actions/setup-go@v3 | ||||||
|         with: |         with: | ||||||
|           go-version: ${{ matrix.go }} |           go-version-file: go.mod | ||||||
|       - name: Setup node and yarn |       - name: Setup node and yarn | ||||||
|         uses: actions/setup-node@v2 |         uses: actions/setup-node@v2 | ||||||
|         with: |         with: | ||||||
| @@ -150,12 +143,12 @@ jobs: | |||||||
|           CGO_ENABLED: 0 |           CGO_ENABLED: 0 | ||||||
|         run: | |         run: | | ||||||
|           mkdir dist out |           mkdir dist out | ||||||
|           GO_TAGS="${{ env.GO_TAGS }}" VAULT_VERSION=${{ needs.get-product-version.outputs.product-base-version }} VAULT_REVISION="$(git rev-parse HEAD)" VAULT_BUILD_DATE="${{ needs.get-build-date.outputs.build-date }}" make build |           GO_TAGS="${{ env.GO_TAGS }}" VAULT_VERSION=${{ needs.product-metadata.outputs.product-base-version }} VAULT_REVISION="$(git rev-parse HEAD)" VAULT_BUILD_DATE="${{ needs.get-build-date.outputs.build-date }}" make build | ||||||
|           zip -r -j out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ |           zip -r -j out/${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ | ||||||
|       - uses: actions/upload-artifact@v2 |       - uses: actions/upload-artifact@v2 | ||||||
|         with: |         with: | ||||||
|           name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip |           name: ${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip | ||||||
|           path: out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip |           path: out/${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip | ||||||
|  |  | ||||||
|       - name: Package |       - name: Package | ||||||
|         uses: hashicorp/actions-packaging-linux@v1 |         uses: hashicorp/actions-packaging-linux@v1 | ||||||
| @@ -163,7 +156,7 @@ jobs: | |||||||
|           name: ${{ github.event.repository.name }} |           name: ${{ github.event.repository.name }} | ||||||
|           description: "Vault is a tool for secrets management, encryption as a service, and privileged access management." |           description: "Vault is a tool for secrets management, encryption as a service, and privileged access management." | ||||||
|           arch: ${{ matrix.goarch }} |           arch: ${{ matrix.goarch }} | ||||||
|           version: ${{ needs.get-product-version.outputs.product-version }} |           version: ${{ needs.product-metadata.outputs.product-version }} | ||||||
|           maintainer: "HashiCorp" |           maintainer: "HashiCorp" | ||||||
|           homepage: "https://github.com/hashicorp/vault" |           homepage: "https://github.com/hashicorp/vault" | ||||||
|           license: "MPL-2.0" |           license: "MPL-2.0" | ||||||
| @@ -189,22 +182,21 @@ jobs: | |||||||
|           path: out/${{ env.DEB_PACKAGE }} |           path: out/${{ env.DEB_PACKAGE }} | ||||||
|  |  | ||||||
|   build-darwin: |   build-darwin: | ||||||
|     needs: [ get-product-version, get-build-date ] |     needs: [ product-metadata ] | ||||||
|     runs-on: macos-latest |     runs-on: macos-latest | ||||||
|     strategy: |     strategy: | ||||||
|       matrix: |       matrix: | ||||||
|         goos: [ darwin ] |         goos: [ darwin ] | ||||||
|         goarch: [ "amd64", "arm64" ] |         goarch: [ "amd64", "arm64" ] | ||||||
|         go: [ "1.18.4" ] |  | ||||||
|       fail-fast: true |       fail-fast: true | ||||||
|     name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build |     name: Go ${{ matrix.goos }} ${{ matrix.goarch }} build | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v2 |       - uses: actions/checkout@v2 | ||||||
|  |  | ||||||
|       - name: Setup go |       - name: Setup go | ||||||
|         uses: actions/setup-go@v2 |         uses: actions/setup-go@v3 | ||||||
|         with: |         with: | ||||||
|           go-version: ${{ matrix.go }} |           go-version-file: go.mod | ||||||
|       - name: Setup node and yarn |       - name: Setup node and yarn | ||||||
|         uses: actions/setup-node@v2 |         uses: actions/setup-node@v2 | ||||||
|         with: |         with: | ||||||
| @@ -226,17 +218,17 @@ jobs: | |||||||
|           CGO_ENABLED: 0 |           CGO_ENABLED: 0 | ||||||
|         run: | |         run: | | ||||||
|           mkdir dist out |           mkdir dist out | ||||||
|           GO_TAGS="${{ env.GO_TAGS }}" VAULT_VERSION=${{ needs.get-product-version.outputs.product-base-version }} VAULT_REVISION="$(git rev-parse HEAD)" VAULT_BUILD_DATE="${{ needs.get-build-date.outputs.build-date }}" make build |           GO_TAGS="${{ env.GO_TAGS }}" VAULT_VERSION=${{ needs.product-metadata.outputs.product-base-version }} VAULT_REVISION="$(git rev-parse HEAD)" VAULT_BUILD_DATE="${{ needs.get-build-date.outputs.build-date }}" make build | ||||||
|           zip -r -j out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ |           zip -r -j out/${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ | ||||||
|       - uses: actions/upload-artifact@v2 |       - uses: actions/upload-artifact@v2 | ||||||
|         with: |         with: | ||||||
|           name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip |           name: ${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip | ||||||
|           path: out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip |           path: out/${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip | ||||||
|  |  | ||||||
|   build-docker: |   build-docker: | ||||||
|     name: Docker ${{ matrix.arch }} build |     name: Docker ${{ matrix.arch }} build | ||||||
|     needs: |     needs: | ||||||
|       - get-product-version |       - product-metadata | ||||||
|       - build-linux |       - build-linux | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     strategy: |     strategy: | ||||||
| @@ -244,7 +236,7 @@ jobs: | |||||||
|         arch: ["arm", "arm64", "386", "amd64"] |         arch: ["arm", "arm64", "386", "amd64"] | ||||||
|     env: |     env: | ||||||
|       repo: ${{github.event.repository.name}} |       repo: ${{github.event.repository.name}} | ||||||
|       version: ${{needs.get-product-version.outputs.product-version}} |       version: ${{needs.product-metadata.outputs.product-version}} | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v2 |       - uses: actions/checkout@v2 | ||||||
|       - name: Docker Build (Action) |       - name: Docker Build (Action) | ||||||
| @@ -253,7 +245,7 @@ jobs: | |||||||
|           version: ${{env.version}} |           version: ${{env.version}} | ||||||
|           target: default |           target: default | ||||||
|           arch: ${{matrix.arch}} |           arch: ${{matrix.arch}} | ||||||
|           zip_artifact_name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip |           zip_artifact_name: ${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_linux_${{ matrix.arch }}.zip | ||||||
|           tags: | |           tags: | | ||||||
|             docker.io/hashicorp/${{env.repo}}:${{env.version}} |             docker.io/hashicorp/${{env.repo}}:${{env.version}} | ||||||
|             public.ecr.aws/hashicorp/${{env.repo}}:${{env.version}} |             public.ecr.aws/hashicorp/${{env.repo}}:${{env.version}} | ||||||
| @@ -261,7 +253,7 @@ jobs: | |||||||
|   build-ubi: |   build-ubi: | ||||||
|     name: Red Hat UBI ${{ matrix.arch }} build |     name: Red Hat UBI ${{ matrix.arch }} build | ||||||
|     needs: |     needs: | ||||||
|       - get-product-version |       - product-metadata | ||||||
|       - build-linux |       - build-linux | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     strategy: |     strategy: | ||||||
| @@ -269,7 +261,7 @@ jobs: | |||||||
|         arch: ["amd64"] |         arch: ["amd64"] | ||||||
|     env: |     env: | ||||||
|       repo: ${{github.event.repository.name}} |       repo: ${{github.event.repository.name}} | ||||||
|       version: ${{needs.get-product-version.outputs.product-version}} |       version: ${{needs.product-metadata.outputs.product-version}} | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v2 |       - uses: actions/checkout@v2 | ||||||
|       - name: Docker Build (Action) |       - name: Docker Build (Action) | ||||||
| @@ -278,5 +270,22 @@ jobs: | |||||||
|           version: ${{env.version}} |           version: ${{env.version}} | ||||||
|           target: ubi |           target: ubi | ||||||
|           arch: ${{matrix.arch}} |           arch: ${{matrix.arch}} | ||||||
|           zip_artifact_name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip |           zip_artifact_name: ${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_linux_${{ matrix.arch }}.zip | ||||||
|           redhat_tag: scan.connect.redhat.com/ospid-f0a92725-d8c6-4023-9a87-ba785b94c3fd/${{env.repo}}:${{env.version}}-ubi |           redhat_tag: scan.connect.redhat.com/ospid-f0a92725-d8c6-4023-9a87-ba785b94c3fd/${{env.repo}}:${{env.version}}-ubi | ||||||
|  |  | ||||||
|  |   enos: | ||||||
|  |     name: Enos | ||||||
|  |     # Only run the Enos workflow against branches that are created from the | ||||||
|  |     # hashicorp/vault repository. This has the effect of limiting execution of | ||||||
|  |     # Enos scenarios to branches that originate from authors that have write | ||||||
|  |     # access to hashicorp/vault repository. This is required as Github Actions | ||||||
|  |     # will not populate the required secrets for branches created by outside | ||||||
|  |     # contributors in order to protect the secrets integrity. | ||||||
|  |     if: "! github.event.pull_request.head.repo.fork" | ||||||
|  |     needs: | ||||||
|  |       - product-metadata | ||||||
|  |       - build-linux | ||||||
|  |     uses: ./.github/workflows/enos-run.yml | ||||||
|  |     with: | ||||||
|  |       artifact-name: "vault_${{ needs.product-metadata.outputs.product-version }}_linux_amd64.zip" | ||||||
|  |     secrets: inherit | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								.github/workflows/enos-fmt.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.github/workflows/enos-fmt.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | --- | ||||||
|  | name: enos_fmt | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   pull_request: | ||||||
|  |     paths: | ||||||
|  |       - enos/** | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   fmt_check: | ||||||
|  |     # Only run this workflow on pull requests from hashicorp/vault branches | ||||||
|  |     # as we need secrets to install enos. | ||||||
|  |     if: "! github.event.pull_request.head.repo.fork" | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     env: | ||||||
|  |       GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }} | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@v3 | ||||||
|  |       - uses: hashicorp/setup-terraform@v2 | ||||||
|  |         with: | ||||||
|  |           terraform_wrapper: false | ||||||
|  |       - uses: hashicorp/action-setup-enos@v1 | ||||||
|  |         with: | ||||||
|  |           github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} | ||||||
|  |       - name: "check formatting" | ||||||
|  |         working-directory: ./enos | ||||||
|  |         run: make check-fmt | ||||||
							
								
								
									
										114
									
								
								.github/workflows/enos-run.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								.github/workflows/enos-run.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | |||||||
|  | --- | ||||||
|  | name: enos | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   # Only trigger this working using workflow_call. It assumes that secrets are | ||||||
|  |   # being inherited from the caller. | ||||||
|  |   workflow_call: | ||||||
|  |     inputs: | ||||||
|  |       artifact-name: | ||||||
|  |         required: true | ||||||
|  |         type: string | ||||||
|  |  | ||||||
|  | env: | ||||||
|  |   PKG_NAME: vault | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   enos: | ||||||
|  |     name: Integration | ||||||
|  |     strategy: | ||||||
|  |       matrix: | ||||||
|  |         # Run four scenarios to get a maximal distribution of variants in as | ||||||
|  |         # few jobs as possible. | ||||||
|  |         include: | ||||||
|  |           - scenario: "smoke backend:consul consul_version:1.12.3 distro:ubuntu seal:awskms" | ||||||
|  |             aws_region: "us-west-1" | ||||||
|  |           - scenario: "smoke backend:raft consul_version:1.12.3 distro:ubuntu seal:shamir" | ||||||
|  |             aws_region: "us-west-2" | ||||||
|  |           - scenario: "upgrade backend:raft consul_version:1.11.7 distro:rhel seal:shamir" | ||||||
|  |             aws_region: "us-west-1" | ||||||
|  |           - scenario: "upgrade backend:consul consul_version:1.11.7 distro:rhel seal:awskms" | ||||||
|  |             aws_region: "us-west-2" | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     env: | ||||||
|  |       GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }} | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout | ||||||
|  |         uses: actions/checkout@v3 | ||||||
|  |       - name: Set up Terraform | ||||||
|  |         uses: hashicorp/setup-terraform@v2 | ||||||
|  |         with: | ||||||
|  |           # the Terraform wrapper will break Terraform execution in Enos because | ||||||
|  |           # it changes the output to text when we expect it to be JSON. | ||||||
|  |           terraform_wrapper: false | ||||||
|  |       - name: Configure AWS credentials | ||||||
|  |         uses: aws-actions/configure-aws-credentials@v1 | ||||||
|  |         with: | ||||||
|  |           aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | ||||||
|  |           aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||||||
|  |           aws-region: ${{ matrix.aws_region }} | ||||||
|  |           role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | ||||||
|  |           role-skip-session-tagging: true | ||||||
|  |           role-duration-seconds: 3600 | ||||||
|  |       - name: Set up Enos | ||||||
|  |         uses: hashicorp/action-setup-enos@v1 | ||||||
|  |         with: | ||||||
|  |           github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} | ||||||
|  |       - name: Set up AWS SSH private key | ||||||
|  |         run: | | ||||||
|  |           mkdir -p ./enos/support | ||||||
|  |           echo "${{ secrets.ENOS_CI_SSH_KEY }}" > ./enos/support/private_key.pem | ||||||
|  |           chmod 600 ./enos/support/private_key.pem | ||||||
|  |       - name: Download Linux AMD64 Vault bundle | ||||||
|  |         id: download | ||||||
|  |         uses: actions/download-artifact@v3 | ||||||
|  |         with: | ||||||
|  |           name: ${{ inputs.artifact-name }} | ||||||
|  |           path: ./enos/support/downloads | ||||||
|  |       - name: Prepare for scenario execution | ||||||
|  |         run: | | ||||||
|  |           unzip ${{steps.download.outputs.download-path}}/*.zip -d enos/support | ||||||
|  |           mv ${{steps.download.outputs.download-path}}/*.zip enos/support/vault.zip | ||||||
|  |           mkdir -p enos/support/terraform-plugin-cache | ||||||
|  |       - name: Run Enos scenario | ||||||
|  |         id: run | ||||||
|  |         # Continue once and retry to handle occasional blips when creating | ||||||
|  |         # infrastructure. | ||||||
|  |         continue-on-error: true | ||||||
|  |         env: | ||||||
|  |           ENOS_VAR_aws_region: ${{ matrix.aws_region }} | ||||||
|  |           ENOS_VAR_aws_ssh_keypair_name: enos-ci-ssh-key | ||||||
|  |           ENOS_VAR_aws_ssh_private_key_path: ./support/private_key.pem | ||||||
|  |           ENOS_VAR_tfc_api_token: ${{ secrets.TF_API_TOKEN }} | ||||||
|  |           ENOS_VAR_terraform_plugin_cache_dir: ./support/terraform-plugin-cache | ||||||
|  |           ENOS_VAR_vault_bundle_path: ./support/vault.zip | ||||||
|  |         run: | | ||||||
|  |           enos scenario run --timeout 60m0s --chdir ./enos ${{ matrix.scenario }} arch:amd64 builder:crt edition:oss | ||||||
|  |       - name: Retry Enos scenario | ||||||
|  |         id: run_retry | ||||||
|  |         if: steps.run.outcome == 'failure' | ||||||
|  |         env: | ||||||
|  |           ENOS_VAR_aws_region: ${{ matrix.aws_region }} | ||||||
|  |           ENOS_VAR_aws_ssh_keypair_name: enos-ci-ssh-key | ||||||
|  |           ENOS_VAR_aws_ssh_private_key_path: ./support/private_key.pem | ||||||
|  |           ENOS_VAR_tfc_api_token: ${{ secrets.TF_API_TOKEN }} | ||||||
|  |           ENOS_VAR_terraform_plugin_cache_dir: ./support/terraform-plugin-cache | ||||||
|  |           ENOS_VAR_vault_bundle_path: ./support/vault.zip | ||||||
|  |         run: | | ||||||
|  |           enos scenario run --timeout 60m0s --chdir ./enos ${{ matrix.scenario }} arch:amd64 builder:crt edition:oss | ||||||
|  |       - name: Destroy Enos scenario | ||||||
|  |         if: ${{ always() }} | ||||||
|  |         env: | ||||||
|  |           ENOS_VAR_aws_region: ${{ matrix.aws_region }} | ||||||
|  |           ENOS_VAR_aws_ssh_keypair_name: enos-ci-ssh-key | ||||||
|  |           ENOS_VAR_aws_ssh_private_key_path: ./support/private_key.pem | ||||||
|  |           ENOS_VAR_tfc_api_token: ${{ secrets.TF_API_TOKEN }} | ||||||
|  |           ENOS_VAR_terraform_plugin_cache_dir: ./support/terraform-plugin-cache | ||||||
|  |           ENOS_VAR_vault_bundle_path: ./support/vault.zip | ||||||
|  |         run: | | ||||||
|  |           enos scenario destroy --timeout 60m0s --chdir ./enos ${{ matrix.scenario }} arch:amd64 builder:crt edition:oss | ||||||
|  |       - name: Output debug information on failure | ||||||
|  |         if: ${{ failure() }} | ||||||
|  |         run: | | ||||||
|  |           env | ||||||
|  |           find ./enos -name "scenario.tf" -exec cat {} \; | ||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -56,7 +56,11 @@ Vagrantfile | |||||||
| !.release/linux/package/etc/vault.d/vault.hcl | !.release/linux/package/etc/vault.d/vault.hcl | ||||||
| !command/agent/config/test-fixtures/*.hcl | !command/agent/config/test-fixtures/*.hcl | ||||||
| !command/server/test-fixtures/**/*.hcl | !command/server/test-fixtures/**/*.hcl | ||||||
|  | !enos/*.hcl | ||||||
|  |  | ||||||
|  | # Enos | ||||||
|  | enos/.enos | ||||||
|  | enos/support | ||||||
|  |  | ||||||
| .DS_Store | .DS_Store | ||||||
| .idea | .idea | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								enos/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								enos/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | .PHONY: default | ||||||
|  | default: check-fmt | ||||||
|  |  | ||||||
|  | .PHONY: check-fmt | ||||||
|  | check-fmt: check-fmt-enos check-fmt-modules | ||||||
|  |  | ||||||
|  | .PHONY: fmt | ||||||
|  | fmt: fmt-enos fmt-modules | ||||||
|  |  | ||||||
|  | .PHONY: check-fmt-enos | ||||||
|  | check-fmt-enos: | ||||||
|  | 	enos fmt --check --diff . | ||||||
|  |  | ||||||
|  | .PHONY: fmt-enos | ||||||
|  | fmt-enos: | ||||||
|  | 	enos fmt . | ||||||
|  |  | ||||||
|  | .PHONY: check-fmt-modules | ||||||
|  | check-fmt-modules: | ||||||
|  | 	terraform fmt -check -diff -recursive ./modules | ||||||
|  |  | ||||||
|  | .PHONY: fmt-modules | ||||||
|  | fmt-modules: | ||||||
|  | 	terraform fmt -diff -recursive ./modules | ||||||
							
								
								
									
										142
									
								
								enos/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								enos/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | |||||||
|  | # Enos | ||||||
|  |  | ||||||
|  | Enos is an quality testing framework that allows composing and executing quality | ||||||
|  | requirement scenarios as code. For Vault, it is currently used to perform | ||||||
|  | infrastructure integration testing using the artifacts that are created as part | ||||||
|  | of the `build` workflow. While intended to be executed via Github Actions using | ||||||
|  | the results of the `build` workflow, scenarios are also executable from a developer | ||||||
|  | machine that has the requisite dependencies and configuration. | ||||||
|  |  | ||||||
|  | Refer to the [Enos documentation](https://github.com/hashicorp/Enos-Docs) | ||||||
|  | for further information regarding installation, execution or composing Enos scenarios. | ||||||
|  |  | ||||||
|  | ## When to use Enos | ||||||
|  | Determining whether to use `vault.NewTestCluster()` or Enos for testing a feature | ||||||
|  | or scenario is ultimately up to the author. Sometimes one, the other, or both | ||||||
|  | might be appropriate depending on the requirements. Generally, `vault.NewTestCluster()` | ||||||
|  | is going to give you faster feedback and execution time, whereas Enos is going | ||||||
|  | to give you a real-world execution and validation of the requirement. Consider | ||||||
|  | the following cases as examples of when one might opt for an Enos scenario: | ||||||
|  |  | ||||||
|  | * The feature require third-party integrations. Whether that be networked | ||||||
|  |   dependencies like a real Consul backend, a real KMS key to test awskms | ||||||
|  |   auto-unseal, auto-join discovery using AWS tags, or Cloud hardware KMS's. | ||||||
|  | * The feature might behave differently under multiple configuration variants | ||||||
|  |   and therefore should be tested with both combinations, e.g. auto-unseal and | ||||||
|  |   manual shamir unseal or replication in HA mode with integrated storage or | ||||||
|  |   Consul storage. | ||||||
|  | * The scenario requires coordination between multiple targets. For example, | ||||||
|  |   consider the complex lifecycle event of migrating the seal type or storage, | ||||||
|  |   or manually triggering a raft disaster scenario by partitioning the network | ||||||
|  |   between the leader and follower nodes. Or perhaps an auto-pilot upgrade between | ||||||
|  |   a stable version of Vault and our candidate version. | ||||||
|  | * The scenario has specific deployment strategy requirements. For example, | ||||||
|  |   if we want to add a regression test for an issue that only arises when the | ||||||
|  |   software is deployed in a certain manner. | ||||||
|  | * The scenario needs to use actual build artifacts that will be promoted | ||||||
|  |   through the pipeline. | ||||||
|  |  | ||||||
|  | ## Requirements | ||||||
|  | * AWS access. HashiCorp Vault developers should use Doormat. | ||||||
|  | * Terraform >= 1.2 | ||||||
|  | * Enos >= v0.0.10. You can [install it from a release channel](https://github.com/hashicorp/Enos-Docs/blob/main/installation.md). | ||||||
|  | * Access to the QTI org in Terraform Cloud. HashiCorp Vault developers can | ||||||
|  |   access a shared token in 1Password or request their own in #team-quality on | ||||||
|  |   Slack. | ||||||
|  | * An SSH keypair in the AWS region you wish to run the scenario. You can use | ||||||
|  |   Doormat to log in to the AWS console to create or upload an existing keypair. | ||||||
|  | * A Vault install bundle downloaded from releases.hashicorp.com or Artifactory | ||||||
|  |   when using the `builder:crt` variants. When using the `builder:local` variants | ||||||
|  |   Enos will build a Vault bundle from the current branch for you. | ||||||
|  |  | ||||||
|  | ## Scenario Variables | ||||||
|  | In CI, each scenario is executed via Github Actions and has been configured using | ||||||
|  | environment variable inputs that follow the `ENOS_VAR_varname` pattern. | ||||||
|  |  | ||||||
|  | For local execution you can specify all the required variables using environment | ||||||
|  | variables, or you can update `enos.vars.hcl` with values and uncomment the lines. | ||||||
|  |  | ||||||
|  | Variables that are required: | ||||||
|  | * `aws_ssh_keypair_name` | ||||||
|  | * `aws_ssh_private_key_path` | ||||||
|  | * `tfc_api_token` | ||||||
|  | * `vault_bundle_path` | ||||||
|  | * `vault_license_path` (only required for non-OSS editions) | ||||||
|  |  | ||||||
|  | See [enos.vars.hcl](./enos.vars.hcl) or [enos-variables.hcl](./enos-variables.hcl) | ||||||
|  | for further descriptions of the variables. | ||||||
|  |  | ||||||
|  | ## Executing Scenarios | ||||||
|  | From the `enos` directory: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | # List all available scenarios | ||||||
|  | enos scenario list | ||||||
|  | # Run the smoke or upgrade scenario with an artifact that is built locally. Make sure | ||||||
|  | # the local machine has been configured as detailed in the requirements | ||||||
|  | # section. This will execute the scenario and clean up any resources if successful. | ||||||
|  | enos scenario run smoke builder:local | ||||||
|  | enos scenario run upgrade builder:local | ||||||
|  | # To run the same scenario variants that are run in CI, refer to the scenarios listed | ||||||
|  | # in .github/workflows/enos-run.yml under `jobs.enos.strategy.matrix.include`, | ||||||
|  | # adding `builder:local` to run locally. | ||||||
|  | enos scenario run smoke backend:consul consul_version:1.12.3 distro:ubuntu seal:awskms builder:local arch:amd64 edition:oss | ||||||
|  | # Launch an individual scenario but leave infrastructure up after execution | ||||||
|  | enos scenario launch smoke builder:local | ||||||
|  | # Check an individual scenario for validity. This is useful during scenario | ||||||
|  | # authoring and debugging. | ||||||
|  | enos scenario validate smoke builder:local | ||||||
|  | # If you've run the tests and desire to see the outputs, such as the URL or | ||||||
|  | # credentials, you can run the output command to see them. Please note that | ||||||
|  | # after "run" or destroy there will be no "outputs" as the infrastructure | ||||||
|  | # will have been destroyed and state cleared. | ||||||
|  | enos scenario output smoke builder:local | ||||||
|  | # Explicitly destroy all existing infrastructure | ||||||
|  | enos scenario destroy smoke builder:local | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Refer to the [Enos documentation](https://github.com/hashicorp/Enos-Docs) | ||||||
|  | for further information regarding installation, execution or composing scenarios. | ||||||
|  |  | ||||||
|  | # Scenarios | ||||||
|  | There are current two scenarios: `smoke` and `upgrade`. Both begin by building Vault | ||||||
|  | as specified by the selected `builder` variant (see Variants section below for more | ||||||
|  | information). | ||||||
|  |  | ||||||
|  | ## Smoke | ||||||
|  | The [`smoke` scenario](./enos-scenario-smoke.hcl) creates a Vault cluster using | ||||||
|  | the version from the current branch (either in CI or locally), with the backend | ||||||
|  | specified by the `backend` variant (`raft` or `consul`). Next, it unseals with the | ||||||
|  | appropriate method (`awskms` or `shamir`) and performs different verifications | ||||||
|  | depending on the backend and seal type. | ||||||
|  |  | ||||||
|  | ## Upgrade | ||||||
|  | The [`upgrade` scenario](./enos-scenario-upgrade.hcl) creates a Vault cluster using | ||||||
|  | the version specified in `vault_upgrade_initial_release`, with the backend specified | ||||||
|  | by the `backend` variant (`raft` or `consul`). Next, it upgrades the Vault binary | ||||||
|  | that is determined by the `builder` variant. After the upgrade, it verifies that | ||||||
|  | cluster is at the desired version, along with additional verifications. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Autopilot | ||||||
|  | The [`autopilot` scenario](./enos-scenario-autopilot.hcl) creates a Vault cluster using | ||||||
|  | the version specified in `vault_upgrade_initial_release`. Next, it creates additional | ||||||
|  | nodes with the candiate version of Vault as determined by the `builder` variant. | ||||||
|  | The module uses AWS auto-join to handle discovery and unseals with auto-unseal | ||||||
|  | or Shamir depending on the `seal` variant. After the new nodes have joined and been | ||||||
|  | unsealed, it waits for Autopilot to upgrade the new nodes and demote the old nodes. | ||||||
|  |  | ||||||
|  | # Variants | ||||||
|  | Both scenarios support a matrix of variants. In order to achieve broad coverage while | ||||||
|  | keeping test run time reasonable, the variants executed by the `enos-run` Github | ||||||
|  | Actions are tailored to maximize variant distribution per scenario. | ||||||
|  |  | ||||||
|  | ## `builder:crt` | ||||||
|  | This variant is designed for use in Github Actions. The `enos-run.yml` workflow | ||||||
|  | downloads the artifact built by the `build.yml` workflow, unzips it, and sets the | ||||||
|  | `vault_bundle_path` to the zip file and the `vault_local_binary_path` to the binary. | ||||||
|  |  | ||||||
|  | ## `builder:local` | ||||||
|  | This variant is for running the Enos scenario locally. It builds the Vault bundle | ||||||
|  | from the current branch, placing the bundle at the `vault_bundle_path` and the | ||||||
|  | unzipped Vault binary at the `vault_local_binary_path`. | ||||||
							
								
								
									
										96
									
								
								enos/enos-modules.hcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								enos/enos-modules.hcl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,96 @@ | |||||||
|  | module "autopilot_upgrade_storageconfig" { | ||||||
|  |   source = "./modules/autopilot_upgrade_storageconfig" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "az_finder" { | ||||||
|  |   source = "./modules/az_finder" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "backend_consul" { | ||||||
|  |   source = "app.terraform.io/hashicorp-qti/aws-consul/enos" | ||||||
|  |  | ||||||
|  |   project_name    = var.project_name | ||||||
|  |   environment     = "ci" | ||||||
|  |   common_tags     = var.tags | ||||||
|  |   ssh_aws_keypair = var.aws_ssh_keypair_name | ||||||
|  |  | ||||||
|  |   # Set this to a real license vault if using an Enterprise edition of Consul | ||||||
|  |   consul_license = var.backend_license_path == null ? "none" : file(abspath(var.backend_license_path)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "backend_raft" { | ||||||
|  |   source = "./modules/backend_raft" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "build_crt" { | ||||||
|  |   source = "./modules/build_crt" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "build_local" { | ||||||
|  |   source = "./modules/build_local" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "create_vpc" { | ||||||
|  |   source = "app.terraform.io/hashicorp-qti/aws-infra/enos" | ||||||
|  |  | ||||||
|  |   project_name      = var.project_name | ||||||
|  |   environment       = "ci" | ||||||
|  |   common_tags       = var.tags | ||||||
|  |   ami_architectures = ["amd64", "arm64"] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "get_local_version_from_make" { | ||||||
|  |   source = "./modules/get_local_version_from_make" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "read_license" { | ||||||
|  |   source = "./modules/read_license" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "vault_cluster" { | ||||||
|  |   source = "app.terraform.io/hashicorp-qti/aws-vault/enos" | ||||||
|  |   # source = "../../terraform-enos-aws-vault" | ||||||
|  |  | ||||||
|  |   common_tags       = var.tags | ||||||
|  |   environment       = "ci" | ||||||
|  |   instance_count    = var.vault_instance_count | ||||||
|  |   project_name      = var.project_name | ||||||
|  |   ssh_aws_keypair   = var.aws_ssh_keypair_name | ||||||
|  |   vault_install_dir = var.vault_install_dir | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "vault_upgrade" { | ||||||
|  |   source = "./modules/vault_upgrade" | ||||||
|  |  | ||||||
|  |   vault_install_dir    = var.vault_install_dir | ||||||
|  |   vault_instance_count = var.vault_instance_count | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "vault_verify_autopilot" { | ||||||
|  |   source = "./modules/vault_verify_autopilot" | ||||||
|  |  | ||||||
|  |   vault_autopilot_upgrade_status = "await-server-removal" | ||||||
|  |   vault_install_dir              = var.vault_install_dir | ||||||
|  |   vault_instance_count           = var.vault_instance_count | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "vault_verify_raft_auto_join_voter" { | ||||||
|  |   source = "./modules/vault_verify_raft_auto_join_voter" | ||||||
|  |  | ||||||
|  |   vault_install_dir    = var.vault_install_dir | ||||||
|  |   vault_instance_count = var.vault_instance_count | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "vault_verify_unsealed" { | ||||||
|  |   source = "./modules/vault_verify_unsealed" | ||||||
|  |  | ||||||
|  |   vault_install_dir    = var.vault_install_dir | ||||||
|  |   vault_instance_count = var.vault_instance_count | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module "vault_verify_version" { | ||||||
|  |   source = "./modules/vault_verify_version" | ||||||
|  |  | ||||||
|  |   vault_install_dir    = var.vault_install_dir | ||||||
|  |   vault_instance_count = var.vault_instance_count | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								enos/enos-providers.hcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								enos/enos-providers.hcl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | provider "aws" "default" { | ||||||
|  |   region = var.aws_region | ||||||
|  | } | ||||||
|  |  | ||||||
|  | provider "enos" "rhel" { | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       user             = "ec2-user" | ||||||
|  |       private_key_path = abspath(var.aws_ssh_private_key_path) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | provider "enos" "ubuntu" { | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       user             = "ubuntu" | ||||||
|  |       private_key_path = abspath(var.aws_ssh_private_key_path) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										252
									
								
								enos/enos-scenario-autopilot.hcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								enos/enos-scenario-autopilot.hcl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,252 @@ | |||||||
|  | scenario "autopilot" { | ||||||
|  |   matrix { | ||||||
|  |     arch    = ["amd64", "arm64"] | ||||||
|  |     builder = ["local", "crt"] | ||||||
|  |     distro  = ["ubuntu", "rhel"] | ||||||
|  |     edition = ["ent"] | ||||||
|  |     seal    = ["awskms", "shamir"] | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   terraform_cli = terraform_cli.default | ||||||
|  |   terraform     = terraform.default | ||||||
|  |   providers = [ | ||||||
|  |     provider.aws.default, | ||||||
|  |     provider.enos.ubuntu, | ||||||
|  |     provider.enos.rhel | ||||||
|  |   ] | ||||||
|  |  | ||||||
|  |   locals { | ||||||
|  |     build_tags = { | ||||||
|  |       "ent" = ["enterprise", "ent"] | ||||||
|  |     } | ||||||
|  |     bundle_path             = abspath(var.vault_bundle_path) | ||||||
|  |     dependencies_to_install = ["jq"] | ||||||
|  |     enos_provider = { | ||||||
|  |       rhel   = provider.enos.rhel | ||||||
|  |       ubuntu = provider.enos.ubuntu | ||||||
|  |     } | ||||||
|  |     tags = merge({ | ||||||
|  |       "Project Name" : var.project_name | ||||||
|  |       "Project" : "Enos", | ||||||
|  |       "Environment" : "ci" | ||||||
|  |     }, var.tags) | ||||||
|  |     vault_instance_types = { | ||||||
|  |       amd64 = "t3a.small" | ||||||
|  |       arm64 = "t4g.small" | ||||||
|  |     } | ||||||
|  |     vault_instance_type = coalesce(var.vault_instance_type, local.vault_instance_types[matrix.arch]) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "build_vault" { | ||||||
|  |     module = matrix.builder == "crt" ? module.build_crt : module.build_local | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       build_tags  = var.vault_local_build_tags != null ? var.vault_local_build_tags : local.build_tags[matrix.edition] | ||||||
|  |       bundle_path = local.bundle_path | ||||||
|  |       goarch      = matrix.arch | ||||||
|  |       goos        = "linux" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "find_azs" { | ||||||
|  |     module = module.az_finder | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       instance_type = [ | ||||||
|  |         local.vault_instance_type | ||||||
|  |       ] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "create_vpc" { | ||||||
|  |     module = module.create_vpc | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       ami_architectures = [matrix.arch] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "read_license" { | ||||||
|  |     module = module.read_license | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       file_name = abspath(joinpath(path.root, "./support/vault.hclic")) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "create_vault_cluster" { | ||||||
|  |     module = module.vault_cluster | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vpc, | ||||||
|  |       step.build_vault, | ||||||
|  |     ] | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       ami_id                  = step.create_vpc.ami_ids[matrix.distro][matrix.arch] | ||||||
|  |       common_tags             = local.tags | ||||||
|  |       dependencies_to_install = local.dependencies_to_install | ||||||
|  |       instance_type           = local.vault_instance_type | ||||||
|  |       kms_key_arn             = step.create_vpc.kms_key_arn | ||||||
|  |       storage_backend         = "raft" | ||||||
|  |       storage_backend_addl_config = { | ||||||
|  |         autopilot_upgrade_version = var.vault_autopilot_initial_release.version | ||||||
|  |       } | ||||||
|  |       unseal_method = matrix.seal | ||||||
|  |       vault_release = var.vault_autopilot_initial_release | ||||||
|  |       vault_license = step.read_license.license | ||||||
|  |       vpc_id        = step.create_vpc.vpc_id | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "get_local_version" { | ||||||
|  |     module = module.get_local_version_from_make | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "create_autopilot_upgrade_storageconfig" { | ||||||
|  |     module     = module.autopilot_upgrade_storageconfig | ||||||
|  |     depends_on = [step.get_local_version] | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_product_version = step.get_local_version.version | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "upgrade_vault_cluster_with_autopilot" { | ||||||
|  |     module = module.vault_cluster | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vault_cluster, | ||||||
|  |       step.create_autopilot_upgrade_storageconfig, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       ami_id                      = step.create_vpc.ami_ids[matrix.distro][matrix.arch] | ||||||
|  |       common_tags                 = local.tags | ||||||
|  |       dependencies_to_install     = local.dependencies_to_install | ||||||
|  |       instance_type               = local.vault_instance_type | ||||||
|  |       kms_key_arn                 = step.create_vpc.kms_key_arn | ||||||
|  |       storage_backend             = "raft" | ||||||
|  |       storage_backend_addl_config = step.create_autopilot_upgrade_storageconfig.storage_addl_config | ||||||
|  |       unseal_method               = matrix.seal | ||||||
|  |       vault_cluster_tag           = step.create_vault_cluster.vault_cluster_tag | ||||||
|  |       vault_init                  = false | ||||||
|  |       vault_license               = step.read_license.license | ||||||
|  |       vault_local_artifact_path   = local.bundle_path | ||||||
|  |       vault_node_prefix           = "upgrade_node" | ||||||
|  |       vault_root_token            = step.create_vault_cluster.vault_root_token | ||||||
|  |       vault_unseal_when_no_init   = matrix.seal == "shamir" | ||||||
|  |       vault_unseal_keys           = matrix.seal == "shamir" ? step.create_vault_cluster.vault_unseal_keys_hex : null | ||||||
|  |       vpc_id                      = step.create_vpc.vpc_id | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "verify_autopilot_upgraded_vault_cluster" { | ||||||
|  |     module     = module.vault_verify_autopilot | ||||||
|  |     depends_on = [step.upgrade_vault_cluster_with_autopilot] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_autopilot_upgrade_version = step.get_local_version.version | ||||||
|  |       vault_instances                 = step.create_vault_cluster.vault_instances | ||||||
|  |       vault_root_token                = step.create_vault_cluster.vault_root_token | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "verify_vault_unsealed" { | ||||||
|  |     module = module.vault_verify_unsealed | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vault_cluster, | ||||||
|  |       step.upgrade_vault_cluster_with_autopilot, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_instances  = step.create_vault_cluster.vault_instances | ||||||
|  |       vault_root_token = step.create_vault_cluster.vault_root_token | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "verify_raft_auto_join_voter" { | ||||||
|  |     module = module.vault_verify_raft_auto_join_voter | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vault_cluster, | ||||||
|  |       step.upgrade_vault_cluster_with_autopilot, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_instances  = step.create_vault_cluster.vault_instances | ||||||
|  |       vault_root_token = step.create_vault_cluster.vault_root_token | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_instance_ids" { | ||||||
|  |     description = "The Vault cluster instance IDs" | ||||||
|  |     value       = step.create_vault_cluster.instance_ids | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_pub_ips" { | ||||||
|  |     description = "The Vault cluster public IPs" | ||||||
|  |     value       = step.create_vault_cluster.instance_public_ips | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_priv_ips" { | ||||||
|  |     description = "The Vault cluster private IPs" | ||||||
|  |     value       = step.create_vault_cluster.instance_private_ips | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_key_id" { | ||||||
|  |     description = "The Vault cluster Key ID" | ||||||
|  |     value       = step.create_vault_cluster.key_id | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_root_token" { | ||||||
|  |     description = "The Vault cluster root token" | ||||||
|  |     value       = step.create_vault_cluster.vault_root_token | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_unseal_keys_b64" { | ||||||
|  |     description = "The Vault cluster unseal keys" | ||||||
|  |     value       = step.create_vault_cluster.vault_unseal_keys_b64 | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_unseal_keys_hex" { | ||||||
|  |     description = "The Vault cluster unseal keys hex" | ||||||
|  |     value       = step.create_vault_cluster.vault_unseal_keys_hex | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_tag" { | ||||||
|  |     description = "The Vault cluster tag" | ||||||
|  |     value       = step.create_vault_cluster.vault_cluster_tag | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "upgraded_vault_cluster_instance_ids" { | ||||||
|  |     description = "The Vault cluster instance IDs" | ||||||
|  |     value       = step.upgrade_vault_cluster_with_autopilot.instance_ids | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "upgraded_vault_cluster_pub_ips" { | ||||||
|  |     description = "The Vault cluster public IPs" | ||||||
|  |     value       = step.upgrade_vault_cluster_with_autopilot.instance_public_ips | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "upgraded_vault_cluster_priv_ips" { | ||||||
|  |     description = "The Vault cluster private IPs" | ||||||
|  |     value       = step.upgrade_vault_cluster_with_autopilot.instance_private_ips | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										206
									
								
								enos/enos-scenario-smoke.hcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								enos/enos-scenario-smoke.hcl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,206 @@ | |||||||
|  | scenario "smoke" { | ||||||
|  |   matrix { | ||||||
|  |     arch           = ["amd64", "arm64"] | ||||||
|  |     backend        = ["consul", "raft"] | ||||||
|  |     builder        = ["local", "crt"] | ||||||
|  |     consul_version = ["1.12.3", "1.11.7", "1.10.12"] | ||||||
|  |     distro         = ["ubuntu", "rhel"] | ||||||
|  |     edition        = ["oss", "ent"] | ||||||
|  |     seal           = ["awskms", "shamir"] | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   terraform_cli = terraform_cli.default | ||||||
|  |   terraform     = terraform.default | ||||||
|  |   providers = [ | ||||||
|  |     provider.aws.default, | ||||||
|  |     provider.enos.ubuntu, | ||||||
|  |     provider.enos.rhel | ||||||
|  |   ] | ||||||
|  |  | ||||||
|  |   locals { | ||||||
|  |     build_tags = { | ||||||
|  |       "oss" = ["ui"] | ||||||
|  |       "ent" = ["enterprise", "ent"] | ||||||
|  |     } | ||||||
|  |     bundle_path             = abspath(var.vault_bundle_path) | ||||||
|  |     dependencies_to_install = ["jq"] | ||||||
|  |     enos_provider = { | ||||||
|  |       rhel   = provider.enos.rhel | ||||||
|  |       ubuntu = provider.enos.ubuntu | ||||||
|  |     } | ||||||
|  |     tags = merge({ | ||||||
|  |       "Project Name" : var.project_name | ||||||
|  |       "Project" : "Enos", | ||||||
|  |       "Environment" : "ci" | ||||||
|  |     }, var.tags) | ||||||
|  |     vault_instance_types = { | ||||||
|  |       amd64 = "t3a.small" | ||||||
|  |       arm64 = "t4g.small" | ||||||
|  |     } | ||||||
|  |     vault_instance_type = coalesce(var.vault_instance_type, local.vault_instance_types[matrix.arch]) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "build_vault" { | ||||||
|  |     module = matrix.builder == "crt" ? module.build_crt : module.build_local | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       build_tags  = var.vault_local_build_tags != null ? var.vault_local_build_tags : local.build_tags[matrix.edition] | ||||||
|  |       bundle_path = local.bundle_path | ||||||
|  |       goarch      = matrix.arch | ||||||
|  |       goos        = "linux" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "find_azs" { | ||||||
|  |     module = module.az_finder | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       instance_type = [ | ||||||
|  |         var.backend_instance_type, | ||||||
|  |         local.vault_instance_type | ||||||
|  |       ] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "create_vpc" { | ||||||
|  |     module = module.create_vpc | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       ami_architectures  = [matrix.arch] | ||||||
|  |       availability_zones = step.find_azs.availability_zones | ||||||
|  |       common_tags        = local.tags | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "read_license" { | ||||||
|  |     skip_step = matrix.edition == "oss" | ||||||
|  |     module    = module.read_license | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       file_name = abspath(joinpath(path.root, "./support/vault.hclic")) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "create_backend_cluster" { | ||||||
|  |     module = "backend_${matrix.backend}" | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vpc, | ||||||
|  |       step.build_vault, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = provider.enos.ubuntu | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       ami_id      = step.create_vpc.ami_ids["ubuntu"][matrix.arch] | ||||||
|  |       common_tags = local.tags | ||||||
|  |       consul_release = { | ||||||
|  |         edition = var.backend_edition | ||||||
|  |         version = matrix.consul_version | ||||||
|  |       } | ||||||
|  |       instance_type = var.backend_instance_type | ||||||
|  |       kms_key_arn   = step.create_vpc.kms_key_arn | ||||||
|  |       vpc_id        = step.create_vpc.vpc_id | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "create_vault_cluster" { | ||||||
|  |     module = module.vault_cluster | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vpc, | ||||||
|  |       step.create_backend_cluster, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       ami_id                    = step.create_vpc.ami_ids[matrix.distro][matrix.arch] | ||||||
|  |       common_tags               = local.tags | ||||||
|  |       consul_cluster_tag        = step.create_backend_cluster.consul_cluster_tag | ||||||
|  |       dependencies_to_install   = local.dependencies_to_install | ||||||
|  |       instance_type             = local.vault_instance_type | ||||||
|  |       kms_key_arn               = step.create_vpc.kms_key_arn | ||||||
|  |       storage_backend           = matrix.backend | ||||||
|  |       unseal_method             = matrix.seal | ||||||
|  |       vault_local_artifact_path = local.bundle_path | ||||||
|  |       vault_license             = matrix.edition != "oss" ? step.read_license.license : null | ||||||
|  |       vpc_id                    = step.create_vpc.vpc_id | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "verify_vault_unsealed" { | ||||||
|  |     module = module.vault_verify_unsealed | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vault_cluster, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_instances  = step.create_vault_cluster.vault_instances | ||||||
|  |       vault_root_token = step.create_vault_cluster.vault_root_token | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "verify_raft_auto_join_voter" { | ||||||
|  |     skip_step = matrix.backend != "raft" | ||||||
|  |     module    = module.vault_verify_raft_auto_join_voter | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vault_cluster, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_instances  = step.create_vault_cluster.vault_instances | ||||||
|  |       vault_root_token = step.create_vault_cluster.vault_root_token | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_instance_ids" { | ||||||
|  |     description = "The Vault cluster instance IDs" | ||||||
|  |     value       = step.create_vault_cluster.instance_ids | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_pub_ips" { | ||||||
|  |     description = "The Vault cluster public IPs" | ||||||
|  |     value       = step.create_vault_cluster.instance_public_ips | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_priv_ips" { | ||||||
|  |     description = "The Vault cluster private IPs" | ||||||
|  |     value       = step.create_vault_cluster.instance_private_ips | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_key_id" { | ||||||
|  |     description = "The Vault cluster Key ID" | ||||||
|  |     value       = step.create_vault_cluster.key_id | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_root_token" { | ||||||
|  |     description = "The Vault cluster root token" | ||||||
|  |     value       = step.create_vault_cluster.vault_root_token | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_unseal_keys_b64" { | ||||||
|  |     description = "The Vault cluster unseal keys" | ||||||
|  |     value       = step.create_vault_cluster.vault_unseal_keys_b64 | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_unseal_keys_hex" { | ||||||
|  |     description = "The Vault cluster unseal keys hex" | ||||||
|  |     value       = step.create_vault_cluster.vault_unseal_keys_hex | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_tag" { | ||||||
|  |     description = "The Vault cluster tag" | ||||||
|  |     value       = step.create_vault_cluster.vault_cluster_tag | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										243
									
								
								enos/enos-scenario-upgrade.hcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								enos/enos-scenario-upgrade.hcl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,243 @@ | |||||||
|  | scenario "upgrade" { | ||||||
|  |   matrix { | ||||||
|  |     arch           = ["amd64", "arm64"] | ||||||
|  |     backend        = ["consul", "raft"] | ||||||
|  |     builder        = ["local", "crt"] | ||||||
|  |     consul_version = ["1.12.3", "1.11.7", "1.10.12"] | ||||||
|  |     distro         = ["ubuntu", "rhel"] | ||||||
|  |     edition        = ["oss", "ent"] | ||||||
|  |     seal           = ["awskms", "shamir"] | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   terraform_cli = terraform_cli.default | ||||||
|  |   terraform     = terraform.default | ||||||
|  |   providers = [ | ||||||
|  |     provider.aws.default, | ||||||
|  |     provider.enos.ubuntu, | ||||||
|  |     provider.enos.rhel | ||||||
|  |   ] | ||||||
|  |  | ||||||
|  |   locals { | ||||||
|  |     build_tags = { | ||||||
|  |       "oss" = ["ui"] | ||||||
|  |       "ent" = ["enterprise", "ent"] | ||||||
|  |     } | ||||||
|  |     bundle_path             = abspath(var.vault_bundle_path) | ||||||
|  |     dependencies_to_install = ["jq"] | ||||||
|  |     enos_provider = { | ||||||
|  |       rhel   = provider.enos.rhel | ||||||
|  |       ubuntu = provider.enos.ubuntu | ||||||
|  |     } | ||||||
|  |     tags = merge({ | ||||||
|  |       "Project Name" : var.project_name | ||||||
|  |       "Project" : "Enos", | ||||||
|  |       "Environment" : "ci" | ||||||
|  |     }, var.tags) | ||||||
|  |     vault_instance_types = { | ||||||
|  |       amd64 = "t3a.small" | ||||||
|  |       arm64 = "t4g.small" | ||||||
|  |     } | ||||||
|  |     vault_instance_type = coalesce(var.vault_instance_type, local.vault_instance_types[matrix.arch]) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "build_vault" { | ||||||
|  |     module = matrix.builder == "crt" ? module.build_crt : module.build_local | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       build_tags  = var.vault_local_build_tags != null ? var.vault_local_build_tags : local.build_tags[matrix.edition] | ||||||
|  |       bundle_path = local.bundle_path | ||||||
|  |       goarch      = matrix.arch | ||||||
|  |       goos        = "linux" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "find_azs" { | ||||||
|  |     module = module.az_finder | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       instance_type = [ | ||||||
|  |         var.backend_instance_type, | ||||||
|  |         local.vault_instance_type, | ||||||
|  |       ] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "create_vpc" { | ||||||
|  |     module = module.create_vpc | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       ami_architectures  = [matrix.arch] | ||||||
|  |       availability_zones = step.find_azs.availability_zones | ||||||
|  |       common_tags        = local.tags | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "read_license" { | ||||||
|  |     skip_step = matrix.edition == "oss" | ||||||
|  |     module    = module.read_license | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       file_name = abspath(joinpath(path.root, "./support/vault.hclic")) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "create_backend_cluster" { | ||||||
|  |     module = "backend_${matrix.backend}" | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vpc, | ||||||
|  |       step.build_vault, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = provider.enos.ubuntu | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       ami_id      = step.create_vpc.ami_ids["ubuntu"][matrix.arch] | ||||||
|  |       common_tags = local.tags | ||||||
|  |       consul_release = { | ||||||
|  |         edition = var.backend_edition | ||||||
|  |         version = matrix.consul_version | ||||||
|  |       } | ||||||
|  |       instance_type = var.backend_instance_type | ||||||
|  |       kms_key_arn   = step.create_vpc.kms_key_arn | ||||||
|  |       vpc_id        = step.create_vpc.vpc_id | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "create_vault_cluster" { | ||||||
|  |     module = module.vault_cluster | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vpc, | ||||||
|  |       step.create_backend_cluster, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       ami_id                  = step.create_vpc.ami_ids[matrix.distro][matrix.arch] | ||||||
|  |       common_tags             = local.tags | ||||||
|  |       consul_cluster_tag      = step.create_backend_cluster.consul_cluster_tag | ||||||
|  |       dependencies_to_install = local.dependencies_to_install | ||||||
|  |       instance_type           = local.vault_instance_type | ||||||
|  |       kms_key_arn             = step.create_vpc.kms_key_arn | ||||||
|  |       storage_backend         = matrix.backend | ||||||
|  |       unseal_method           = matrix.seal | ||||||
|  |       vault_release           = var.vault_upgrade_initial_release | ||||||
|  |       vault_license           = matrix.edition != "oss" ? step.read_license.license : null | ||||||
|  |       vpc_id                  = step.create_vpc.vpc_id | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "upgrade_vault" { | ||||||
|  |     module = module.vault_upgrade | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vault_cluster, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_api_addr          = "http://localhost:8200" | ||||||
|  |       vault_instances         = step.create_vault_cluster.vault_instances | ||||||
|  |       vault_local_bundle_path = local.bundle_path | ||||||
|  |       vault_unseal_keys       = matrix.seal == "shamir" ? step.create_vault_cluster.vault_unseal_keys_hex : null | ||||||
|  |       vault_seal_type         = matrix.seal | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "verify_vault_version" { | ||||||
|  |     module = module.vault_verify_version | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_backend_cluster, | ||||||
|  |       step.upgrade_vault, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_instances = step.create_vault_cluster.vault_instances | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "verify_vault_unsealed" { | ||||||
|  |     module = module.vault_verify_unsealed | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_vault_cluster, | ||||||
|  |       step.upgrade_vault, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_instances  = step.create_vault_cluster.vault_instances | ||||||
|  |       vault_root_token = step.create_vault_cluster.vault_root_token | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   step "verify_raft_auto_join_voter" { | ||||||
|  |     skip_step = matrix.backend != "raft" | ||||||
|  |     module    = module.vault_verify_raft_auto_join_voter | ||||||
|  |     depends_on = [ | ||||||
|  |       step.create_backend_cluster, | ||||||
|  |       step.upgrade_vault, | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     providers = { | ||||||
|  |       enos = local.enos_provider[matrix.distro] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     variables { | ||||||
|  |       vault_instances  = step.create_vault_cluster.vault_instances | ||||||
|  |       vault_root_token = step.create_vault_cluster.vault_root_token | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_instance_ids" { | ||||||
|  |     description = "The Vault cluster instance IDs" | ||||||
|  |     value       = step.create_vault_cluster.instance_ids | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_pub_ips" { | ||||||
|  |     description = "The Vault cluster public IPs" | ||||||
|  |     value       = step.create_vault_cluster.instance_public_ips | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_priv_ips" { | ||||||
|  |     description = "The Vault cluster private IPs" | ||||||
|  |     value       = step.create_vault_cluster.instance_private_ips | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_key_id" { | ||||||
|  |     description = "The Vault cluster Key ID" | ||||||
|  |     value       = step.create_vault_cluster.key_id | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_root_token" { | ||||||
|  |     description = "The Vault cluster root token" | ||||||
|  |     value       = step.create_vault_cluster.vault_root_token | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_unseal_keys_b64" { | ||||||
|  |     description = "The Vault cluster unseal keys" | ||||||
|  |     value       = step.create_vault_cluster.vault_unseal_keys_b64 | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_unseal_keys_hex" { | ||||||
|  |     description = "The Vault cluster unseal keys hex" | ||||||
|  |     value       = step.create_vault_cluster.vault_unseal_keys_hex | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   output "vault_cluster_tag" { | ||||||
|  |     description = "The Vault cluster tag" | ||||||
|  |     value       = step.create_vault_cluster.vault_cluster_tag | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								enos/enos-terraform.hcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								enos/enos-terraform.hcl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | terraform_cli "default" { | ||||||
|  |   plugin_cache_dir = var.terraform_plugin_cache_dir != null ? abspath(var.terraform_plugin_cache_dir) : null | ||||||
|  |  | ||||||
|  |   credentials "app.terraform.io" { | ||||||
|  |     token = var.tfc_api_token | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /* | ||||||
|  |   provider_installation { | ||||||
|  |     dev_overrides = { | ||||||
|  |       "app.terraform.io/hashicorp-qti/enos" = abspath("../../enos-provider") | ||||||
|  |     } | ||||||
|  |     direct {} | ||||||
|  |   } | ||||||
|  |   */ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | terraform "default" { | ||||||
|  |   required_version = ">= 1.2.0" | ||||||
|  |  | ||||||
|  |   required_providers { | ||||||
|  |     aws = { | ||||||
|  |       source = "hashicorp/aws" | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     enos = { | ||||||
|  |       source = "app.terraform.io/hashicorp-qti/enos" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										111
									
								
								enos/enos-variables.hcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								enos/enos-variables.hcl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | variable "aws_region" { | ||||||
|  |   description = "The AWS region where we'll create infrastructure" | ||||||
|  |   type        = string | ||||||
|  |   default     = "us-west-1" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "aws_ssh_keypair_name" { | ||||||
|  |   description = "The AWS keypair to use for SSH" | ||||||
|  |   type        = string | ||||||
|  |   default     = "enos-ci-ssh-key" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "aws_ssh_private_key_path" { | ||||||
|  |   description = "The path to the AWS keypair private key" | ||||||
|  |   type        = string | ||||||
|  |   default     = "./support/private_key.pem" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "backend_edition" { | ||||||
|  |   description = "The backend release edition if applicable" | ||||||
|  |   type        = string | ||||||
|  |   default     = "oss" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "backend_instance_type" { | ||||||
|  |   description = "The instance type to use for the Vault backend" | ||||||
|  |   type        = string | ||||||
|  |   default     = "t3.small" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "backend_license_path" { | ||||||
|  |   description = "The license for the backend if applicable (Consul Enterprise)" | ||||||
|  |   type        = string | ||||||
|  |   default     = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "project_name" { | ||||||
|  |   description = "The description of the project" | ||||||
|  |   type        = string | ||||||
|  |   default     = "vault-enos-integration" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "tags" { | ||||||
|  |   description = "Tags that will be applied to infrastructure resources that support tagging" | ||||||
|  |   type        = map(string) | ||||||
|  |   default     = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "terraform_plugin_cache_dir" { | ||||||
|  |   description = "The directory to cache Terraform modules and providers" | ||||||
|  |   type        = string | ||||||
|  |   default     = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "tfc_api_token" { | ||||||
|  |   description = "The Terraform Cloud QTI Organization API token." | ||||||
|  |   type        = string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_autopilot_initial_release" { | ||||||
|  |   description = "The Vault release to deploy before upgrading with autopilot" | ||||||
|  |   default = { | ||||||
|  |     edition = "ent" | ||||||
|  |     version = "1.11.0" | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_bundle_path" { | ||||||
|  |   description = "Path to CRT generated or local vault.zip bundle" | ||||||
|  |   type        = string | ||||||
|  |   default     = "/tmp/vault.zip" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_install_dir" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The directory where the vault binary will be installed" | ||||||
|  |   default     = "/opt/vault/bin" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instance_type" { | ||||||
|  |   description = "The instance type to use for the Vault backend" | ||||||
|  |   type        = string | ||||||
|  |   default     = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instance_count" { | ||||||
|  |   description = "How many instances to create for the Vault cluster" | ||||||
|  |   type        = number | ||||||
|  |   default     = 3 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_license_path" { | ||||||
|  |   description = "The path to a valid Vault enterprise edition license. This is only required for non-oss editions" | ||||||
|  |   type        = string | ||||||
|  |   default     = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_local_build_tags" { | ||||||
|  |   description = "The build tags to pass to the Go compiler for builder:local variants" | ||||||
|  |   type        = list(string) | ||||||
|  |   default     = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_upgrade_initial_release" { | ||||||
|  |   description = "The Vault release to deploy before upgrading" | ||||||
|  |   default = { | ||||||
|  |     edition = "oss" | ||||||
|  |     // vault 1.10.5 has a known issue with retry_join. | ||||||
|  |     version = "1.10.4" | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								enos/enos.vars.hcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								enos/enos.vars.hcl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | # aws_region is the AWS region where we'll create infrastructure | ||||||
|  | # for the smoke scenario | ||||||
|  | # aws_region = "us-west-1" | ||||||
|  |  | ||||||
|  | # aws_ssh_keypair_name is the AWS keypair to use for SSH | ||||||
|  | # aws_ssh_keypair_name = "enos-ci-ssh-key" | ||||||
|  |  | ||||||
|  | # aws_ssh_private_key_path is the path to the AWS keypair private key | ||||||
|  | # aws_ssh_private_key_path = "./support/private_key.pem" | ||||||
|  |  | ||||||
|  | # backend_instance_type is the instance type to use for the Vault backend | ||||||
|  | # backend_instance_type = "t3.small" | ||||||
|  |  | ||||||
|  | # tags are a map of tags that will be applied to infrastructure resources that | ||||||
|  | # support tagging. | ||||||
|  | # tags = { "Project Name" : "Vault", "Something Cool" : "Value" } | ||||||
|  |  | ||||||
|  | # terraform_plugin_cache_dir is the directory to cache Terraform modules and providers. | ||||||
|  | # It must exist. | ||||||
|  | # terraform_plugin_cache_dir = "/Users/<user>/.terraform/plugin-cache-dir | ||||||
|  |  | ||||||
|  | # tfc_api_token is the Terraform Cloud QTI Organization API token. We need this | ||||||
|  | # to download the enos Terraform provider and the enos Terraform modules. | ||||||
|  | # tfc_api_token = "XXXXX.atlasv1.XXXXX..." | ||||||
|  |  | ||||||
|  | # vault_bundle_path is the path to CRT generated or local vault.zip bundle. When | ||||||
|  | # using the "builder:local" variant a bundle will be built from the current branch. | ||||||
|  | # In CI it will use the output of the build workflow. | ||||||
|  | # vault_bundle_path = "./dist/vault.zip" | ||||||
|  |  | ||||||
|  | # vault_install_dir is the directory where the vault binary will be installed on | ||||||
|  | # the remote machines. | ||||||
|  | # vault_install_dir = "/opt/vault/bin" | ||||||
|  |  | ||||||
|  | # vault_local_binary_path is the path of the local binary that we're upgrading to. | ||||||
|  | # vault_local_binary_path = "./support/vault" | ||||||
|  |  | ||||||
|  | # vault_instance_type is the instance type to use for the Vault backend | ||||||
|  | # vault_instance_type = "t3.small" | ||||||
|  |  | ||||||
|  | # vault_instance_count is how many instances to create for the Vault cluster. | ||||||
|  | # vault_instance_count = 3 | ||||||
|  |  | ||||||
|  | # vault_license_path is the path to a valid Vault enterprise edition license. | ||||||
|  | # This is only required for non-oss editions" | ||||||
|  | # vault_license_path = "./support/vault.hclic" | ||||||
|  |  | ||||||
|  | # vault_upgrade_initial_release is the Vault release to deploy before upgrading. | ||||||
							
								
								
									
										7
									
								
								enos/modules/autopilot_upgrade_storageconfig/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								enos/modules/autopilot_upgrade_storageconfig/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | variable "vault_product_version" {} | ||||||
|  |  | ||||||
|  | output "storage_addl_config" { | ||||||
|  |   value = { | ||||||
|  |     autopilot_upgrade_version = var.vault_product_version | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								enos/modules/az_finder/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								enos/modules/az_finder/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | terraform { | ||||||
|  |   required_providers { | ||||||
|  |     aws = { | ||||||
|  |       source = "hashicorp/aws" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "instance_type" { | ||||||
|  |   default = ["t3.small"] | ||||||
|  |   type    = list(string) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | data "aws_ec2_instance_type_offerings" "infra" { | ||||||
|  |   filter { | ||||||
|  |     name   = "instance-type" | ||||||
|  |     values = var.instance_type | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   location_type = "availability-zone" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | output "availability_zones" { | ||||||
|  |   value = data.aws_ec2_instance_type_offerings.infra.locations | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								enos/modules/backend_raft/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								enos/modules/backend_raft/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | // Shim module to handle the fact that Vault doesn't actually need a backend module | ||||||
|  | terraform { | ||||||
|  |   required_providers { | ||||||
|  |     aws = { | ||||||
|  |       source = "hashicorp/aws" | ||||||
|  |     } | ||||||
|  |     enos = { | ||||||
|  |       source = "app.terraform.io/hashicorp-qti/enos" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "ami_id" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  | variable "common_tags" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  | variable "consul_license" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  | variable "consul_release" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  | variable "environment" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  | variable "instance_type" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  | variable "kms_key_arn" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  | variable "project_name" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  | variable "ssh_aws_keypair" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  | variable "vpc_id" { | ||||||
|  |   default = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | output "consul_cluster_tag" { | ||||||
|  |   value = null | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								enos/modules/build_crt/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								enos/modules/build_crt/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | # Shim module since CRT provided things will use the crt_bundle_path variable | ||||||
|  | variable "bundle_path" { | ||||||
|  |   default = "/tmp/vault.zip" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "build_tags" { | ||||||
|  |   default = ["ui"] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "goarch" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The Go architecture target" | ||||||
|  |   default     = "amd64" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "goos" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The Go OS target" | ||||||
|  |   default     = "linux" | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								enos/modules/build_local/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								enos/modules/build_local/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | terraform { | ||||||
|  |   required_providers { | ||||||
|  |     enos = { | ||||||
|  |       source = "hashicorp.com/qti/enos" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "bundle_path" { | ||||||
|  |   type    = string | ||||||
|  |   default = "/tmp/vault.zip" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "build_tags" { | ||||||
|  |   type        = list(string) | ||||||
|  |   description = "The build tags to pass to the Go compiler" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "goarch" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The Go architecture target" | ||||||
|  |   default     = "amd64" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "goos" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The Go OS target" | ||||||
|  |   default     = "linux" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_local_exec" "build" { | ||||||
|  |   content = templatefile("${path.module}/templates/build.sh", { | ||||||
|  |     bundle_path = var.bundle_path, | ||||||
|  |     build_tags  = join(" ", var.build_tags) | ||||||
|  |     goarch      = var.goarch | ||||||
|  |     goos        = var.goos | ||||||
|  |   }) | ||||||
|  | } | ||||||
							
								
								
									
										39
									
								
								enos/modules/build_local/templates/build.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										39
									
								
								enos/modules/build_local/templates/build.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | set -eux -o pipefail | ||||||
|  |  | ||||||
|  | # Requirements | ||||||
|  | npm install --global yarn || true | ||||||
|  |  | ||||||
|  | # Set up the environment for building Vault. | ||||||
|  | root_dir="$(git rev-parse --show-toplevel)" | ||||||
|  |  | ||||||
|  | pushd "$root_dir" > /dev/null | ||||||
|  |  | ||||||
|  | export GO_TAGS=${build_tags} | ||||||
|  | export CGO_ENABLED=0 | ||||||
|  |  | ||||||
|  | IFS="-" read -r BASE_VERSION _other <<< "$(make version)" | ||||||
|  | export VAULT_VERSION=$BASE_VERSION | ||||||
|  |  | ||||||
|  | build_date="$(make build-date)" | ||||||
|  | export VAULT_BUILD_DATE=$build_date | ||||||
|  |  | ||||||
|  | revision="$(git rev-parse HEAD)" | ||||||
|  | export VAULT_REVISION=$revision | ||||||
|  | popd > /dev/null | ||||||
|  |  | ||||||
|  | # Go to the UI directory of the Vault repo and build the UI | ||||||
|  | pushd "$root_dir/ui" > /dev/null | ||||||
|  | yarn install --ignore-optional | ||||||
|  | npm rebuild node-sass | ||||||
|  | yarn --verbose run build | ||||||
|  | popd > /dev/null | ||||||
|  |  | ||||||
|  | # Build for linux/amd64 and create a bundle since we're deploying it to linux/amd64 | ||||||
|  | pushd "$root_dir" > /dev/null | ||||||
|  | export GOARCH=${goarch} | ||||||
|  | export GOOS=${goos} | ||||||
|  | make build | ||||||
|  |  | ||||||
|  | zip -r -j ${bundle_path} dist/ | ||||||
|  | popd > /dev/null | ||||||
							
								
								
									
										15
									
								
								enos/modules/get_local_version_from_make/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								enos/modules/get_local_version_from_make/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | terraform { | ||||||
|  |   required_providers { | ||||||
|  |     enos = { | ||||||
|  |       source = "app.terraform.io/hashicorp-qti/enos" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_local_exec" "get_version" { | ||||||
|  |   scripts = ["${path.module}/scripts/version.sh"] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | output "version" { | ||||||
|  |   value = trimspace(enos_local_exec.get_version.stdout) | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								enos/modules/get_local_version_from_make/scripts/version.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										10
									
								
								enos/modules/get_local_version_from_make/scripts/version.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | #!/bin/env bash | ||||||
|  | set -eu -o pipefail | ||||||
|  |  | ||||||
|  | # Set up the environment for building Vault. | ||||||
|  | root_dir="$(git rev-parse --show-toplevel)" | ||||||
|  |  | ||||||
|  | pushd "$root_dir" > /dev/null | ||||||
|  |  | ||||||
|  | IFS="-" read -r VAULT_VERSION _other <<< "$(make version)" | ||||||
|  | echo $VAULT_VERSION | ||||||
							
								
								
									
										5
									
								
								enos/modules/read_license/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								enos/modules/read_license/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | variable "file_name" {} | ||||||
|  |  | ||||||
|  | output "license" { | ||||||
|  |   value = file(var.file_name) | ||||||
|  | } | ||||||
							
								
								
									
										163
									
								
								enos/modules/vault_upgrade/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								enos/modules/vault_upgrade/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,163 @@ | |||||||
|  | terraform { | ||||||
|  |   required_providers { | ||||||
|  |     aws = { | ||||||
|  |       source = "hashicorp/aws" | ||||||
|  |     } | ||||||
|  |     enos = { | ||||||
|  |       source = "app.terraform.io/hashicorp-qti/enos" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_api_addr" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The API address of the Vault cluster" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_install_dir" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The directory where the Vault binary will be installed" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instance_count" { | ||||||
|  |   type        = number | ||||||
|  |   description = "How many vault instances are in the cluster" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instances" { | ||||||
|  |   type = map(object({ | ||||||
|  |     private_ip = string | ||||||
|  |     public_ip  = string | ||||||
|  |   })) | ||||||
|  |   description = "The vault cluster instances that were created" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_local_bundle_path" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The path to the local Vault (vault.zip) bundle" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_seal_type" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The Vault seal type" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_unseal_keys" { | ||||||
|  |   type        = list(string) | ||||||
|  |   description = "The keys to use to unseal Vault when not using auto-unseal" | ||||||
|  |   default     = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | locals { | ||||||
|  |   instances = { | ||||||
|  |     for idx in range(var.vault_instance_count) : idx => { | ||||||
|  |       public_ip  = values(var.vault_instances)[idx].public_ip | ||||||
|  |       private_ip = values(var.vault_instances)[idx].private_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   followers      = toset([for idx in range(var.vault_instance_count - 1) : tostring(idx)]) | ||||||
|  |   follower_ips   = compact(split(" ", enos_remote_exec.get_follower_public_ips.stdout)) | ||||||
|  |   vault_bin_path = "${var.vault_install_dir}/vault" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_bundle_install" "upgrade_vault_binary" { | ||||||
|  |   for_each = local.instances | ||||||
|  |  | ||||||
|  |   destination = var.vault_install_dir | ||||||
|  |   path        = var.vault_local_bundle_path | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = each.value.public_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_remote_exec" "get_leader_public_ip" { | ||||||
|  |   depends_on = [enos_bundle_install.upgrade_vault_binary] | ||||||
|  |  | ||||||
|  |   content = templatefile("${path.module}/templates/get-leader-public-ip.sh", { | ||||||
|  |     vault_install_dir = var.vault_install_dir, | ||||||
|  |     vault_instances   = jsonencode(local.instances) | ||||||
|  |   }) | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = local.instances[0].public_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_remote_exec" "get_follower_public_ips" { | ||||||
|  |   depends_on = [enos_bundle_install.upgrade_vault_binary] | ||||||
|  |  | ||||||
|  |   content = templatefile("${path.module}/templates/get-follower-public-ips.sh", { | ||||||
|  |     vault_install_dir = var.vault_install_dir, | ||||||
|  |     vault_instances   = jsonencode(local.instances) | ||||||
|  |   }) | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = local.instances[0].public_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_remote_exec" "restart_followers" { | ||||||
|  |   for_each   = local.followers | ||||||
|  |   depends_on = [enos_remote_exec.get_follower_public_ips] | ||||||
|  |  | ||||||
|  |   content = file("${path.module}/templates/restart-vault.sh") | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = trimspace(local.follower_ips[tonumber(each.key)]) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_vault_unseal" "followers" { | ||||||
|  |   depends_on = [enos_remote_exec.restart_followers] | ||||||
|  |   for_each = { | ||||||
|  |     for idx, follower in local.followers : idx => follower | ||||||
|  |     if var.vault_seal_type == "shamir" | ||||||
|  |   } | ||||||
|  |   bin_path    = local.vault_bin_path | ||||||
|  |   vault_addr  = var.vault_api_addr | ||||||
|  |   seal_type   = var.vault_seal_type | ||||||
|  |   unseal_keys = var.vault_unseal_keys | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = trimspace(local.follower_ips[each.key]) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_remote_exec" "restart_leader" { | ||||||
|  |   depends_on = [enos_vault_unseal.followers] | ||||||
|  |  | ||||||
|  |   content = file("${path.module}/templates/restart-vault.sh") | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = trimspace(enos_remote_exec.get_leader_public_ip.stdout) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_vault_unseal" "leader" { | ||||||
|  |   count      = var.vault_seal_type == "shamir" ? 1 : 0 | ||||||
|  |   depends_on = [enos_remote_exec.restart_leader] | ||||||
|  |  | ||||||
|  |   bin_path    = local.vault_bin_path | ||||||
|  |   vault_addr  = var.vault_api_addr | ||||||
|  |   seal_type   = var.vault_seal_type | ||||||
|  |   unseal_keys = var.vault_unseal_keys | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = trimspace(enos_remote_exec.get_leader_public_ip.stdout) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,16 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | binpath=${vault_install_dir}/vault | ||||||
|  | export VAULT_ADDR="http://localhost:8200" | ||||||
|  |  | ||||||
|  | instances='${vault_instances}' | ||||||
|  |  | ||||||
|  | # Find the leader | ||||||
|  | leader_address=$($binpath status -format json | jq '.leader_address | rtrimstr(":8200") | ltrimstr("http://")') | ||||||
|  |  | ||||||
|  | # Get the public ip addresses of the followers | ||||||
|  | follower_ips=$(jq ".[] | select(.private_ip!=$leader_address) | .public_ip" <<< "$instances") | ||||||
|  |  | ||||||
|  | echo "$follower_ips" | sed 's/\"//g' | tr '\n' ' ' | ||||||
							
								
								
									
										15
									
								
								enos/modules/vault_upgrade/templates/get-leader-public-ip.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								enos/modules/vault_upgrade/templates/get-leader-public-ip.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | binpath=${vault_install_dir}/vault | ||||||
|  | export VAULT_ADDR="http://localhost:8200" | ||||||
|  |  | ||||||
|  | instances='${vault_instances}' | ||||||
|  |  | ||||||
|  | # Find the leader | ||||||
|  | leader_address=$($binpath status -format json | jq '.leader_address | rtrimstr(":8200") | ltrimstr("http://")') | ||||||
|  |  | ||||||
|  | # Get the public ip address of the leader | ||||||
|  | leader_public=$(jq ".[] | select(.private_ip==$leader_address) | .public_ip" <<< "$instances") | ||||||
|  | echo "$leader_public" | sed 's/\"//g' | ||||||
							
								
								
									
										5
									
								
								enos/modules/vault_upgrade/templates/restart-vault.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								enos/modules/vault_upgrade/templates/restart-vault.sh
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | set -eux | ||||||
|  |  | ||||||
|  | sudo systemctl restart vault | ||||||
							
								
								
									
										68
									
								
								enos/modules/vault_verify_autopilot/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								enos/modules/vault_verify_autopilot/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | terraform { | ||||||
|  |   required_providers { | ||||||
|  |     enos = { | ||||||
|  |       source = "app.terraform.io/hashicorp-qti/enos" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_install_dir" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The directory where the Vault binary will be installed" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instance_count" { | ||||||
|  |   type        = number | ||||||
|  |   description = "How many vault instances are in the cluster" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instances" { | ||||||
|  |   type = map(object({ | ||||||
|  |     private_ip = string | ||||||
|  |     public_ip  = string | ||||||
|  |   })) | ||||||
|  |   description = "The vault cluster instances that were created" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_root_token" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The vault root token" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_autopilot_upgrade_version" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The directory where the Vault binary will be installed" | ||||||
|  |   default     = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_autopilot_upgrade_status" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The directory where the Vault binary will be installed" | ||||||
|  |   default     = null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | locals { | ||||||
|  |   public_ips = { | ||||||
|  |     for idx in range(var.vault_instance_count) : idx => { | ||||||
|  |       public_ip  = values(var.vault_instances)[idx].public_ip | ||||||
|  |       private_ip = values(var.vault_instances)[idx].private_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_remote_exec" "smoke-verify-autopilot" { | ||||||
|  |   for_each = local.public_ips | ||||||
|  |  | ||||||
|  |   content = templatefile("${path.module}/templates/smoke-verify-autopilot.sh", { | ||||||
|  |     vault_install_dir               = var.vault_install_dir | ||||||
|  |     vault_token                     = var.vault_root_token | ||||||
|  |     vault_autopilot_upgrade_status  = var.vault_autopilot_upgrade_status, | ||||||
|  |     vault_autopilot_upgrade_version = var.vault_autopilot_upgrade_version, | ||||||
|  |   }) | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = each.value.public_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								enos/modules/vault_verify_autopilot/templates/smoke-verify-autopilot.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										34
									
								
								enos/modules/vault_verify_autopilot/templates/smoke-verify-autopilot.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | #!/bin/bash | ||||||
|  |  | ||||||
|  | token="${vault_token}" | ||||||
|  | autopilot_version="${vault_autopilot_upgrade_version}" | ||||||
|  | autopilot_status="${vault_autopilot_upgrade_status}" | ||||||
|  |  | ||||||
|  | export VAULT_ADDR="http://localhost:8200" | ||||||
|  | export VAULT_TOKEN="$token" | ||||||
|  |  | ||||||
|  | function fail() { | ||||||
|  | 	echo "$1" 1>&2 | ||||||
|  | 	exit 1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | count=0 | ||||||
|  | retries=7 | ||||||
|  | while :; do | ||||||
|  |     state=$(${vault_install_dir}/vault read -format=json sys/storage/raft/autopilot/state) | ||||||
|  |     status="$(jq -r '.data.upgrade_info.status' <<< "$state")" | ||||||
|  |     target_version="$(jq -r '.data.upgrade_info.target_version' <<< "$state")" | ||||||
|  |  | ||||||
|  |     if [ "$status" = "$autopilot_status" ] && [ "$target_version" = "$autopilot_version" ]; then | ||||||
|  |         exit 0 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     wait=$((2 ** count)) | ||||||
|  |     count=$((count + 1)) | ||||||
|  |     if [ "$count" -lt "$retries" ]; then | ||||||
|  |         echo "$state" | ||||||
|  |         sleep "$wait" | ||||||
|  |     else | ||||||
|  |         fail "Autopilot did not get into the correct status" | ||||||
|  |     fi | ||||||
|  | done | ||||||
							
								
								
									
										62
									
								
								enos/modules/vault_verify_raft_auto_join_voter/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								enos/modules/vault_verify_raft_auto_join_voter/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | terraform { | ||||||
|  |   required_providers { | ||||||
|  |     enos = { | ||||||
|  |       source = "app.terraform.io/hashicorp-qti/enos" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_cluster_addr_port" { | ||||||
|  |   description = "The Raft cluster address port" | ||||||
|  |   type        = string | ||||||
|  |   default     = "8201" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_install_dir" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The directory where the Vault binary will be installed" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instance_count" { | ||||||
|  |   type        = number | ||||||
|  |   description = "How many vault instances are in the cluster" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instances" { | ||||||
|  |   type = map(object({ | ||||||
|  |     private_ip = string | ||||||
|  |     public_ip  = string | ||||||
|  |   })) | ||||||
|  |   description = "The vault cluster instances that were created" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_root_token" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The vault root token" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | locals { | ||||||
|  |   instances = { | ||||||
|  |     for idx in range(var.vault_instance_count) : idx => { | ||||||
|  |       public_ip  = values(var.vault_instances)[idx].public_ip | ||||||
|  |       private_ip = values(var.vault_instances)[idx].private_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_remote_exec" "verify_raft_auto_join_voter" { | ||||||
|  |   for_each = local.instances | ||||||
|  |  | ||||||
|  |   content = templatefile("${path.module}/templates/verify-raft-auto-join-voter.sh", { | ||||||
|  |     vault_cluster_addr      = "${each.value.private_ip}:${var.vault_cluster_addr_port}" | ||||||
|  |     vault_install_dir       = var.vault_install_dir | ||||||
|  |     vault_local_binary_path = "${var.vault_install_dir}/vault" | ||||||
|  |     vault_token             = var.vault_root_token | ||||||
|  |   }) | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = each.value.public_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,47 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | binpath=${vault_install_dir}/vault | ||||||
|  |  | ||||||
|  | fail() { | ||||||
|  |   echo "$1" 2>&1 | ||||||
|  |   return 1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | retry() { | ||||||
|  |   local retries=$1 | ||||||
|  |   shift | ||||||
|  |   local count=0 | ||||||
|  |  | ||||||
|  |   until "$@"; do | ||||||
|  |     exit=$? | ||||||
|  |     wait=$((2 ** count)) | ||||||
|  |     count=$((count + 1)) | ||||||
|  |     if [ "$count" -lt "$retries" ]; then | ||||||
|  |       sleep "$wait" | ||||||
|  |       echo "retry $count" | ||||||
|  |     else | ||||||
|  |       return "$exit" | ||||||
|  |     fi | ||||||
|  |   done | ||||||
|  |  | ||||||
|  |   return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | check_voter_status() { | ||||||
|  |   voter_status=$($binpath operator raft list-peers -format json | jq -Mr --argjson expected "true" '.data.config.servers[] | select(.address=="${vault_cluster_addr}") | .voter == $expected') | ||||||
|  |  | ||||||
|  |   if [[ "$voter_status" != 'true' ]]; then | ||||||
|  |     fail "expected ${vault_cluster_addr} to be raft voter, got raft status for node: $($binpath operator raft list-peers -format json | jq '.data.config.servers[] | select(.address==${vault_cluster_addr})')" | ||||||
|  |   fi | ||||||
|  | } | ||||||
|  |  | ||||||
|  | test -x "$binpath" || fail "unable to locate vault binary at $binpath" | ||||||
|  |  | ||||||
|  | export VAULT_ADDR='http://127.0.0.1:8200' | ||||||
|  | export VAULT_TOKEN='${vault_token}' | ||||||
|  |  | ||||||
|  | # Retry a few times because it can take some time for things to settle after | ||||||
|  | # all the nodes are unsealed | ||||||
|  | retry 5 check_voter_status | ||||||
							
								
								
									
										62
									
								
								enos/modules/vault_verify_unsealed/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								enos/modules/vault_verify_unsealed/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | terraform { | ||||||
|  |   required_providers { | ||||||
|  |     enos = { | ||||||
|  |       source = "app.terraform.io/hashicorp-qti/enos" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_cluster_addr_port" { | ||||||
|  |   description = "The Raft cluster address port" | ||||||
|  |   type        = string | ||||||
|  |   default     = "8201" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_install_dir" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The directory where the Vault binary will be installed" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instance_count" { | ||||||
|  |   type        = number | ||||||
|  |   description = "How many vault instances are in the cluster" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instances" { | ||||||
|  |   type = map(object({ | ||||||
|  |     private_ip = string | ||||||
|  |     public_ip  = string | ||||||
|  |   })) | ||||||
|  |   description = "The vault cluster instances that were created" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_root_token" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The vault root token" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | locals { | ||||||
|  |   instances = { | ||||||
|  |     for idx in range(var.vault_instance_count) : idx => { | ||||||
|  |       public_ip  = values(var.vault_instances)[idx].public_ip | ||||||
|  |       private_ip = values(var.vault_instances)[idx].private_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_remote_exec" "verify_raft_auto_join_voter" { | ||||||
|  |   for_each = local.instances | ||||||
|  |  | ||||||
|  |   content = templatefile("${path.module}/templates/verify-vault-node-unsealed.sh", { | ||||||
|  |     vault_cluster_addr      = "${each.value.private_ip}:${var.vault_cluster_addr_port}" | ||||||
|  |     vault_install_dir       = var.vault_install_dir | ||||||
|  |     vault_local_binary_path = "${var.vault_install_dir}/vault" | ||||||
|  |     vault_token             = var.vault_root_token | ||||||
|  |   }) | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = each.value.public_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,20 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | binpath=${vault_install_dir}/vault | ||||||
|  |  | ||||||
|  | fail() { | ||||||
|  |   echo "$1" 1>&2 | ||||||
|  |   return 1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | test -x "$binpath" || fail "unable to locate vault binary at $binpath" | ||||||
|  |  | ||||||
|  | export VAULT_ADDR='http://127.0.0.1:8200' | ||||||
|  | export VAULT_TOKEN='${vault_token}' | ||||||
|  |  | ||||||
|  | unseal_status=$($binpath status -format json | jq -Mr --argjson expected "false" '.sealed == $expected') | ||||||
|  | if [[ "$unseal_status" != 'true' ]]; then | ||||||
|  |   fail "expected ${vault_cluster_addr} to be unsealed, got unseal status: $unseal_status" | ||||||
|  | fi | ||||||
							
								
								
									
										48
									
								
								enos/modules/vault_verify_version/main.tf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								enos/modules/vault_verify_version/main.tf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | terraform { | ||||||
|  |   required_providers { | ||||||
|  |     enos = { | ||||||
|  |       source = "app.terraform.io/hashicorp-qti/enos" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_install_dir" { | ||||||
|  |   type        = string | ||||||
|  |   description = "The directory where the Vault binary will be installed" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instance_count" { | ||||||
|  |   type        = number | ||||||
|  |   description = "How many vault instances are in the cluster" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | variable "vault_instances" { | ||||||
|  |   type = map(object({ | ||||||
|  |     private_ip = string | ||||||
|  |     public_ip  = string | ||||||
|  |   })) | ||||||
|  |   description = "The vault cluster instances that were created" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | locals { | ||||||
|  |   instances = { | ||||||
|  |     for idx in range(var.vault_instance_count) : idx => { | ||||||
|  |       public_ip  = values(var.vault_instances)[idx].public_ip | ||||||
|  |       private_ip = values(var.vault_instances)[idx].private_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | resource "enos_remote_exec" "verify_all_nodes_have_updated_version" { | ||||||
|  |   for_each = local.instances | ||||||
|  |  | ||||||
|  |   content = templatefile("${path.module}/templates/verify-cluster-version.sh", { | ||||||
|  |     vault_install_dir = var.vault_install_dir, | ||||||
|  |   }) | ||||||
|  |  | ||||||
|  |   transport = { | ||||||
|  |     ssh = { | ||||||
|  |       host = each.value.public_ip | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,37 @@ | |||||||
|  | #!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | # The Vault smoke test to verify the Vault version installed | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | binpath=${vault_install_dir}/vault | ||||||
|  |  | ||||||
|  | fail() { | ||||||
|  | 	echo "$1" 1>&2 | ||||||
|  | 	exit 1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | test -x "$binpath" || fail "unable to locate vault binary at $binpath" | ||||||
|  |  | ||||||
|  | binary_version_full=$($binpath version) | ||||||
|  | # Get the Vault build tag | ||||||
|  | binary_version=$(cut -d ' ' -f2 <<< $binary_version_full) | ||||||
|  | # Strip the leading v | ||||||
|  | semantic=$${binary_version:1} | ||||||
|  | # Get the build timestamp | ||||||
|  | build_date=$(cut -d ' ' -f5 <<< $binary_version_full) | ||||||
|  |  | ||||||
|  | export VAULT_ADDR='http://127.0.0.1:8200' | ||||||
|  |  | ||||||
|  | # Ensure that the cluster version and build time match the binary installed | ||||||
|  | vault_status=$("$binpath" status -format json) | ||||||
|  | result=$(jq -Mr \ | ||||||
|  |   --arg version "$semantic" \ | ||||||
|  |   --arg build_date "$build_date" \ | ||||||
|  |   'select(.version == $version) | .build_date == $build_date' \ | ||||||
|  |   <<< $vault_status | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | if [[ "$result" != "true" ]]; then | ||||||
|  |   fail "expected version $binary_version with build_date $build_date, got status $vault_status" | ||||||
|  | fi | ||||||
		Reference in New Issue
	
	Block a user
	 Ryan Cragun
					Ryan Cragun