Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
babc45b758 | ||
|
|
c7338b3aa8 | ||
|
|
d738671047 | ||
|
|
8ebe3fba5e | ||
|
|
513fcec72e | ||
|
|
796a7b53b8 | ||
|
|
d1069ef892 | ||
|
|
d912257828 | ||
|
|
d7d7319c85 | ||
|
|
2efc03a8ae | ||
|
|
8c933816a5 | ||
|
|
3e539fec8a | ||
|
|
e5ba1a0127 | ||
|
|
2df4b6561b | ||
|
|
bfc592880f | ||
|
|
e9f7b89ad2 | ||
|
|
08f651b123 | ||
|
|
19ecce6754 | ||
|
|
570627f875 | ||
|
|
142a9984c6 | ||
|
|
c9e2843dbd | ||
|
|
efb153e034 | ||
|
|
00f16a445f | ||
|
|
c2481702ba | ||
|
|
f9cd0e893e | ||
|
|
1e3ebf2263 | ||
|
|
957b816a01 | ||
|
|
02f7efc80a | ||
|
|
740d268e63 | ||
|
|
eb7244bb65 | ||
|
|
182352b6d4 | ||
|
|
0d53402fa5 | ||
|
|
f52a0b32c3 | ||
|
|
e21b7db0c4 | ||
|
|
e47a4569cf | ||
|
|
6cfb1e3c12 | ||
|
|
4d69cde767 | ||
|
|
5004d88de5 | ||
|
|
9cd88a7864 | ||
|
|
84385332f4 | ||
|
|
63fad8e763 | ||
|
|
c2c25838bd | ||
|
|
53ee95cb05 | ||
|
|
4db46625d3 | ||
|
|
3521817758 | ||
|
|
d180d5ba0d | ||
|
|
8001b12fa2 | ||
|
|
af60d2e30b | ||
|
|
1b6ecc392f | ||
|
|
b3b98a085b | ||
|
|
85f9a3d081 | ||
|
|
39563fb317 | ||
|
|
bdf9efdcaa | ||
|
|
f95483bd7f | ||
|
|
a8d679d118 | ||
|
|
8ec00c0b42 | ||
|
|
278925e5b5 | ||
|
|
06ee60eecf | ||
|
|
f0ba588a35 | ||
|
|
d26c389669 | ||
|
|
ab26f51db1 | ||
|
|
514fa81a99 | ||
|
|
395dda1006 | ||
|
|
67d786dbef | ||
|
|
05c94cf96a | ||
|
|
f87fa8036e | ||
|
|
388f4d8b33 | ||
|
|
e625176e36 | ||
|
|
2dc5699ae2 | ||
|
|
ad8dcfcc24 | ||
|
|
02a9fbd98c | ||
|
|
0dc805c4e8 | ||
|
|
c42dad6b09 | ||
|
|
7dbcc88daf | ||
|
|
80a9e65997 | ||
|
|
7055507cfe | ||
|
|
55383a53b5 | ||
|
|
a665f6409a | ||
|
|
6f51147c7c | ||
|
|
fea6f4b662 | ||
|
|
347f5760a4 | ||
|
|
b126bdcdb6 | ||
|
|
77c8f52d90 | ||
|
|
eeb5fc43d2 | ||
|
|
8a8df155a6 | ||
|
|
895b06d90c | ||
|
|
0ed435d80b | ||
|
|
6bfd56cd02 | ||
|
|
4590d94f77 | ||
|
|
4f6a9d95e8 | ||
|
|
4db8e98628 | ||
|
|
88171adae2 | ||
|
|
0fcadd690a | ||
|
|
ce487f406f | ||
|
|
c4989de229 | ||
|
|
a17e75224f | ||
|
|
6aeb82110e | ||
|
|
67ef83e347 | ||
|
|
86a99ae47a | ||
|
|
afb376b135 | ||
|
|
faee60fcf8 | ||
|
|
f818017976 | ||
|
|
22fac2f569 | ||
|
|
2c5a595592 | ||
|
|
7124548774 | ||
|
|
8d82258cf5 | ||
|
|
584aabacbb | ||
|
|
01c68bcae8 | ||
|
|
07e332f79b | ||
|
|
f2300e6f96 | ||
|
|
0423202f9d | ||
|
|
1e1b10da59 | ||
|
|
5a5654bce0 | ||
|
|
4ac6cf3ee1 | ||
|
|
3e664429b3 | ||
|
|
fa432c79ba | ||
|
|
4352dff7ec | ||
|
|
3d6e8f8e46 | ||
|
|
357c83d9ca | ||
|
|
1c1c095a66 | ||
|
|
f9fd811205 | ||
|
|
ad43c0bec0 | ||
|
|
5d6d277186 | ||
|
|
4590e7f8c8 | ||
|
|
47c3f92f5c | ||
|
|
490476a5e5 | ||
|
|
a256b763ae | ||
|
|
f6539b969c | ||
|
|
695e28a38b | ||
|
|
b7b11dd817 | ||
|
|
b9bc73d4cf | ||
|
|
e847f5fde7 | ||
|
|
53c2a5769c | ||
|
|
ed1bf21505 | ||
|
|
6a23fc20f9 | ||
|
|
41653b2ccd | ||
|
|
398eaf8406 | ||
|
|
c71ba43a3d | ||
|
|
1153ea44ee | ||
|
|
2020819648 |
No files matched your search
+30
-6
@@ -9,12 +9,36 @@ updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
# Check for updates to GitHub Actions every weekday
|
||||
interval: "daily"
|
||||
# Check for updates to GitHub Actions every Sunday
|
||||
interval: "weekly"
|
||||
day: "sunday"
|
||||
groups:
|
||||
# Group all GitHub Actions updates into a single PR
|
||||
actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
# Maintain dependencies for Go modules
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
directories:
|
||||
- "/"
|
||||
- "/plugins/kms/mains/alicloudkms"
|
||||
- "/plugins/kms/mains/awskms"
|
||||
- "/plugins/kms/mains/azurekeyvault"
|
||||
- "/plugins/kms/mains/gcpckms"
|
||||
- "/plugins/kms/mains/ocikms"
|
||||
- "/plugins/kms/mains/transit"
|
||||
schedule:
|
||||
# Check for updates to Go modules every weekday
|
||||
interval: "daily"
|
||||
# Check for updates to Go modules every Sunday
|
||||
interval: "weekly"
|
||||
day: "sunday"
|
||||
groups:
|
||||
# Group all Go module updates into one PR for version updates
|
||||
# and one for security updates.
|
||||
go:
|
||||
patterns:
|
||||
- "*"
|
||||
applies-to: "version-updates"
|
||||
go-security:
|
||||
patterns:
|
||||
- "*"
|
||||
applies-to: "security-updates"
|
||||
@@ -0,0 +1,11 @@
|
||||
## PCI review checklist
|
||||
|
||||
<!-- heimdall_github_prtemplate:grc-pci_dss-2024-01-05 -->
|
||||
|
||||
- [ ] I have documented a clear reason for, and description of, the change I am making.
|
||||
|
||||
- [ ] If applicable, I've documented a plan to revert these changes if they require more than reverting the pull request.
|
||||
|
||||
- [ ] If applicable, I've documented the impact of any changes to security controls.
|
||||
|
||||
Examples of changes to security controls include using new access control methods, adding or removing logging pipelines, etc.
|
||||
@@ -8,7 +8,7 @@ jobs:
|
||||
actionlint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Check workflow files
|
||||
uses: docker://docker.mirror.hashicorp.services/rhysd/actionlint@sha256:02ccb6d91e4cb4a7b21eb99d5274d257e81ae667688d730e89d7ea0d6d35db91
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# This workflow builds the product for all supported platforms and uploads the resulting
|
||||
# binaries as Actions artifacts. The workflow also uploads a build metadata file
|
||||
# (metadata.json) -- and a Terraform Registry manifest file (terraform-registry-manifest.json).
|
||||
#
|
||||
# Reference: https://github.com/hashicorp/terraform-provider-crt-example/blob/main/.github/workflows/README.md
|
||||
#
|
||||
|
||||
name: build
|
||||
|
||||
# We default to running this workflow on every push to every branch.
|
||||
# This provides fast feedback when build issues occur, so they can be
|
||||
# fixed prior to being merged to the main branch.
|
||||
#
|
||||
# If you want to opt out of this, and only run the build on certain branches
|
||||
# please refer to the documentation on branch filtering here:
|
||||
#
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onpushbranchestagsbranches-ignoretags-ignore
|
||||
#
|
||||
on: [workflow_dispatch, push]
|
||||
|
||||
env:
|
||||
PKG_NAME: "terraform-provider-boundary"
|
||||
|
||||
jobs:
|
||||
# Detects the Go version to use for builds.
|
||||
get-go-version:
|
||||
name: "Detect Go toolchain version"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
go-version: ${{ steps.get-go-version.outputs.go-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Detect Go version
|
||||
id: get-go-version
|
||||
# We use .go-version as our source of truth for current Go version,
|
||||
# because "goenv" can react to it automatically.
|
||||
run: |
|
||||
echo "Building with Go $(cat .go-version)"
|
||||
echo "go-version=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
|
||||
with:
|
||||
go-version: "${{ steps.get-go-version.outputs.go-version }}"
|
||||
cache: false
|
||||
|
||||
# Parses the version/VERSION file. Reference: https://github.com/hashicorp/actions-set-product-version/blob/main/README.md
|
||||
#
|
||||
# > This action should be implemented in product repo `build.yml` files. The action is intended to grab the version
|
||||
# > from the version file at the beginning of the build, then passes those versions (along with metadata, where
|
||||
# > necessary) to any workflow jobs that need version information.
|
||||
set-product-version:
|
||||
name: "Parse version file"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
product-version: ${{ steps.set-product-version.outputs.product-version }}
|
||||
product-base-version: ${{ steps.set-product-version.outputs.base-product-version }}
|
||||
product-prerelease-version: ${{ steps.set-product-version.outputs.prerelease-product-version }}
|
||||
product-minor-version: ${{ steps.set-product-version.outputs.minor-product-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Set variables
|
||||
id: set-product-version
|
||||
uses: hashicorp/actions-set-product-version@v2
|
||||
|
||||
# Creates metadata.json file containing build metadata for consumption by CRT workflows.
|
||||
#
|
||||
# Reference: https://github.com/hashicorp/actions-generate-metadata/blob/main/README.md
|
||||
generate-metadata-file:
|
||||
needs: set-product-version
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
filepath: ${{ steps.generate-metadata-file.outputs.filepath }}
|
||||
steps:
|
||||
- name: "Checkout directory"
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Generate metadata file
|
||||
id: generate-metadata-file
|
||||
uses: hashicorp/actions-generate-metadata@v1
|
||||
with:
|
||||
version: ${{ needs.set-product-version.outputs.product-version }}
|
||||
product: ${{ env.PKG_NAME }}
|
||||
repositoryOwner: "hashicorp"
|
||||
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||
with:
|
||||
name: metadata.json
|
||||
path: ${{ steps.generate-metadata-file.outputs.filepath }}
|
||||
|
||||
# Uploads an Actions artifact named terraform-registry-manifest.json.zip.
|
||||
#
|
||||
# The artifact contains a single file with a filename that Terraform Registry expects
|
||||
# (example: terraform-provider-crt-example_2.3.6-alpha1_manifest.json). The file contents
|
||||
# are identical to the terraform-registry-manifest.json file in the source repository.
|
||||
upload-terraform-registry-manifest-artifact:
|
||||
needs: set-product-version
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout directory"
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
path: ${{ env.PKG_NAME }}
|
||||
- name: "Copy manifest from checkout directory to a file with the desired name"
|
||||
id: terraform-registry-manifest
|
||||
run: |
|
||||
name="${{ env.PKG_NAME }}"
|
||||
version="${{ needs.set-product-version.outputs.product-version }}"
|
||||
|
||||
source="${name}/terraform-registry-manifest.json"
|
||||
destination="${name}_${version}_manifest.json"
|
||||
|
||||
cp "$source" "$destination"
|
||||
echo "filename=$destination" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||
with:
|
||||
name: terraform-registry-manifest.json
|
||||
path: ${{ steps.terraform-registry-manifest.outputs.filename }}
|
||||
if-no-files-found: error
|
||||
|
||||
# Builds the product for supported platforms.
|
||||
#
|
||||
# With `reproducible: report`, this job also reports whether the build is reproducible,
|
||||
# but does not enforce it.
|
||||
#
|
||||
# Reference: https://github.com/hashicorp/actions-go-build/blob/main/README.md
|
||||
build:
|
||||
needs:
|
||||
- get-go-version
|
||||
- set-product-version
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
goos: [freebsd, windows, linux, darwin]
|
||||
goarch: ["386", "amd64", "arm", "arm64"]
|
||||
exclude:
|
||||
- goos: freebsd
|
||||
goarch: arm64
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
- goos: darwin
|
||||
goarch: 386
|
||||
- goos: darwin
|
||||
goarch: arm
|
||||
|
||||
name: Go ${{ needs.get-go-version.outputs.go-version }} ${{ matrix.goos }} ${{ matrix.goarch }} build
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: hashicorp/actions-go-build@v1
|
||||
env:
|
||||
CGO_ENABLED: 0
|
||||
BASE_VERSION: ${{ needs.set-product-version.outputs.product-base-version }}
|
||||
PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.product-prerelease-version}}
|
||||
METADATA_VERSION: ${{ env.METADATA }}
|
||||
with:
|
||||
bin_name: "${{ env.PKG_NAME }}_v${{ needs.set-product-version.outputs.product-version }}_x5"
|
||||
product_name: ${{ env.PKG_NAME }}
|
||||
product_version: ${{ needs.set-product-version.outputs.product-version }}
|
||||
go_version: ${{ needs.get-go-version.outputs.go-version }}
|
||||
os: ${{ matrix.goos }}
|
||||
arch: ${{ matrix.goarch }}
|
||||
reproducible: report
|
||||
instructions: |
|
||||
go mod download && ./scripts/plugins-all.sh
|
||||
go build \
|
||||
-o "$BIN_PATH" \
|
||||
-trimpath \
|
||||
-buildvcs=false \
|
||||
-ldflags "-s -w -X 'main.version=${{ needs.set-product-version.outputs.product-version }}'"
|
||||
cp LICENSE "$TARGET_DIR/LICENSE.txt"
|
||||
|
||||
whats-next:
|
||||
needs:
|
||||
- build
|
||||
- generate-metadata-file
|
||||
- upload-terraform-registry-manifest-artifact
|
||||
runs-on: ubuntu-latest
|
||||
name: "What's next?"
|
||||
steps:
|
||||
- name: "Write a helpful summary"
|
||||
run: |
|
||||
github_dot_com="${{ github.server_url }}"
|
||||
owner_with_name="${{ github.repository }}"
|
||||
ref="${{ github.ref }}"
|
||||
|
||||
{
|
||||
echo "### What's next?"
|
||||
echo "#### For a release branch (see \`.release/ci.hcl\`)"
|
||||
echo "After this \`build\` workflow run completes succesfully, you can expect the CRT \`prepare\` workflow to begin momentarily."
|
||||
echo "To find the \`prepare\` workflow run, [view the checks for this commit]($github_dot_com/$owner_with_name/commits/$ref)"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
+39
-20
@@ -22,7 +22,7 @@ jobs:
|
||||
id: boundary-team-role
|
||||
run: |
|
||||
TEAM="boundary"
|
||||
ROLE="$(hub api orgs/hashicorp/teams/${TEAM}/memberships/${{ github.actor }} | jq -r '.role | select(.!=null)')"
|
||||
ROLE="$(gh api orgs/hashicorp/teams/${TEAM}/memberships/${{ github.actor }} | jq -r '.role | select(.!=null)')"
|
||||
if [[ -n "${ROLE}" ]]; then
|
||||
echo "Actor ${{ github.actor }} is a ${TEAM} team member, skipping ticket creation"
|
||||
else
|
||||
@@ -32,13 +32,6 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.JIRA_SYNC_GITHUB_TOKEN }}
|
||||
|
||||
- name: Login
|
||||
uses: atlassian/gajira-login@45fd029b9f1d6d8926c6f04175aa80c0e42c9026 # v3.0.1
|
||||
env:
|
||||
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
|
||||
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
|
||||
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
|
||||
|
||||
- name: Set ticket type
|
||||
if: github.event.action == 'opened' && !steps.boundary-team-role.outputs.role
|
||||
id: set-ticket-type
|
||||
@@ -52,6 +45,10 @@ jobs:
|
||||
- name: Create ticket
|
||||
if: github.event.action == 'opened' && !steps.boundary-team-role.outputs.role
|
||||
uses: tomhjp/gh-action-jira-create@3ed1789cad3521292e591a7cfa703215ec1348bf # v0.2.1
|
||||
env:
|
||||
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
|
||||
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
|
||||
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
|
||||
with:
|
||||
project: ICU
|
||||
issuetype: "GH Issue"
|
||||
@@ -64,6 +61,10 @@ jobs:
|
||||
if: github.event.action != 'opened'
|
||||
id: search
|
||||
uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2
|
||||
env:
|
||||
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
|
||||
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
|
||||
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
|
||||
with:
|
||||
# cf[10089] is Issue Link custom field
|
||||
jql: 'issuetype = "GH Issue" and cf[10089]="${{ github.event.issue.html_url || github.event.pull_request.html_url }}"'
|
||||
@@ -71,20 +72,38 @@ jobs:
|
||||
- name: Sync comment
|
||||
if: github.event.action == 'created' && steps.search.outputs.issue
|
||||
uses: tomhjp/gh-action-jira-comment@6eb6b9ead70221916b6badd118c24535ed220bd9 # v0.2.0
|
||||
env:
|
||||
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
|
||||
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
|
||||
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
|
||||
with:
|
||||
issue: ${{ steps.search.outputs.issue }}
|
||||
comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}"
|
||||
|
||||
- name: Close ticket
|
||||
if: (github.event.action == 'closed' || github.event.action == 'deleted') && steps.search.outputs.issue
|
||||
uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1
|
||||
with:
|
||||
issue: ${{ steps.search.outputs.issue }}
|
||||
transition: Done
|
||||
- name: Transitions
|
||||
id: transitions
|
||||
if: steps.search.outputs.issue
|
||||
run: |
|
||||
if [[ "${{ github.event.action }}" == "closed" || "${{ github.event.action }}" == "deleted" ]]; then
|
||||
echo "Closing ticket"
|
||||
echo "name=Done" >> "$GITHUB_OUTPUT"
|
||||
elif [[ "${{ github.event.action }}" == "reopened" ]]; then
|
||||
echo "Reopening ticket"
|
||||
echo "name='Reopen'" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Reopen ticket
|
||||
if: github.event.action == 'reopened' && steps.search.outputs.issue
|
||||
uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1
|
||||
with:
|
||||
issue: ${{ steps.search.outputs.issue }}
|
||||
transition: "To Do"
|
||||
# Transition issue API reference: https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-transitions-post
|
||||
- name: Transition ticket
|
||||
if: steps.transitions.outputs.name
|
||||
run: |
|
||||
transitions="$(curl --silent \
|
||||
--url "${{ secrets.JIRA_BASE_URL }}rest/api/3/issue/${{ steps.search.outputs.issue }}/transitions" \
|
||||
--user "${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }}" \
|
||||
--header "Accept: application/json")"
|
||||
id="$(echo "${transitions}" | jq -r '.transitions[] | select(.name == "${{ steps.transitions.outputs.name }}") | .id')"
|
||||
curl --silent \
|
||||
--url "${{ secrets.JIRA_BASE_URL }}rest/api/3/issue/${{ steps.search.outputs.issue }}/transitions" \
|
||||
--user "${{ secrets.JIRA_USER_EMAIL }}:${{ secrets.JIRA_API_TOKEN }}" \
|
||||
--header "Accept: application/json" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "$(printf '{"transition": {"id": "%s"}}' "${id}")"
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
name: "Check for uncommitted changes from make gen"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
- name: Determine Go version
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
echo "Building with Go $(cat .go-version)"
|
||||
echo "go-version=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
|
||||
with:
|
||||
go-version: "${{ steps.get-go-version.outputs.go-version }}"
|
||||
- name: Running go mod tidy
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
go-version:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.go-version.outputs.go-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- id: go-version
|
||||
# We use .go-version as our source of truth for current Go
|
||||
# version, because "goenv" can react to it automatically.
|
||||
run: |
|
||||
echo "Building with Go $(cat .go-version)"
|
||||
echo "go-version=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
release-notes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Generate Release Notes
|
||||
run: sed -n -e "1{/# /d;}" -e "2{/^$/d;}" -e "/# $(git describe --abbrev=0 --exclude="$(git describe --abbrev=0 --match='v*.*.*' --tags)" --match='v*.*.*' --tags | tr -d v)/q;p" CHANGELOG.md > release-notes.txt
|
||||
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
with:
|
||||
name: release-notes
|
||||
path: release-notes.txt
|
||||
retention-days: 1
|
||||
terraform-provider-release:
|
||||
name: 'Terraform Provider Release'
|
||||
needs: [go-version, release-notes]
|
||||
uses: hashicorp/ghaction-terraform-provider-release/.github/workflows/hashicorp.yml@v3
|
||||
secrets:
|
||||
hc-releases-github-token: '${{ secrets.HASHI_RELEASES_GITHUB_TOKEN }}'
|
||||
hc-releases-host-staging: '${{ secrets.HC_RELEASES_HOST_STAGING }}'
|
||||
hc-releases-host-prod: '${{ secrets.HC_RELEASES_HOST_PROD }}'
|
||||
hc-releases-key-prod: '${{ secrets.HC_RELEASES_KEY_PROD }}'
|
||||
hc-releases-key-staging: '${{ secrets.HC_RELEASES_KEY_STAGING }}'
|
||||
hc-releases-terraform-registry-sync-token: '${{ secrets.TF_PROVIDER_RELEASE_TERRAFORM_REGISTRY_SYNC_TOKEN }}'
|
||||
setup-signore-github-token: '${{ secrets.HASHI_SIGNORE_GITHUB_TOKEN }}'
|
||||
signore-client-id: '${{ secrets.SIGNORE_CLIENT_ID }}'
|
||||
signore-client-secret: '${{ secrets.SIGNORE_CLIENT_SECRET }}'
|
||||
with:
|
||||
release-notes: true
|
||||
setup-go-version: '${{ needs.go-version.outputs.version }}'
|
||||
# Product Version (e.g. v1.2.3 or github.ref_name)
|
||||
product-version: '${{ github.ref_name }}'
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Determine go version
|
||||
id: get-go-version
|
||||
# We use .go-version as our source of truth for current Go
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
echo "Building with Go $(cat .go-version)"
|
||||
echo "go-version=$(cat .go-version)" >> "$GITHUB_OUTPUT"
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
|
||||
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
|
||||
with:
|
||||
go-version: "${{ steps.get-go-version.outputs.go-version }}"
|
||||
cache: false
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
echo "go-build=$(go env GOCACHE)" >> "$GITHUB_OUTPUT"
|
||||
echo "go-mod=$(go env GOMODCACHE)" >> "$GITHUB_OUTPUT"
|
||||
- name: Set up Go modules cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: |
|
||||
${{ steps.go-cache-paths.outputs.go-build }}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.21.5
|
||||
1.25.1
|
||||
@@ -1,78 +0,0 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
archives:
|
||||
- files:
|
||||
# Ensure only built binary is archived
|
||||
- 'none*'
|
||||
format: zip
|
||||
name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}'
|
||||
before:
|
||||
hooks:
|
||||
- 'go mod download'
|
||||
- './scripts/plugins-all.sh'
|
||||
builds:
|
||||
- # Binary naming only required for Terraform CLI 0.12
|
||||
binary: '{{ .ProjectName }}_v{{ .Version }}_x5'
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
flags:
|
||||
- -trimpath
|
||||
goos:
|
||||
- darwin
|
||||
- freebsd
|
||||
- linux
|
||||
- windows
|
||||
goarch:
|
||||
- '386'
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
ignore:
|
||||
- goarch: arm
|
||||
goos: windows
|
||||
- goarch: arm64
|
||||
goos: freebsd
|
||||
- goarch: arm64
|
||||
goos: windows
|
||||
ldflags:
|
||||
- -s -w -X main.Version={{.Version}}
|
||||
mod_timestamp: '{{ .CommitTimestamp }}'
|
||||
checksum:
|
||||
algorithm: sha256
|
||||
extra_files:
|
||||
- glob: 'terraform-registry-manifest.json'
|
||||
name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
|
||||
name_template: '{{ .ProjectName }}_{{ .Version }}_SHA256SUMS'
|
||||
publishers:
|
||||
- checksum: true
|
||||
# Terraform CLI 0.10 - 0.11 perform discovery via HTTP headers on releases.hashicorp.com
|
||||
# For providers which have existed since those CLI versions, exclude
|
||||
# discovery by setting the protocol version headers to 5.
|
||||
cmd: hc-releases upload -product {{ .ProjectName }} -version {{ .Version }} -file={{ .ArtifactPath }}={{ .ArtifactName }} -header=x-terraform-protocol-version=5 -header=x-terraform-protocol-versions=5.0
|
||||
env:
|
||||
- HC_RELEASES_HOST={{ .Env.HC_RELEASES_HOST }}
|
||||
- HC_RELEASES_KEY={{ .Env.HC_RELEASES_KEY }}
|
||||
extra_files:
|
||||
- glob: 'terraform-registry-manifest.json'
|
||||
name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
|
||||
name: upload
|
||||
signature: true
|
||||
release:
|
||||
extra_files:
|
||||
- glob: 'terraform-registry-manifest.json'
|
||||
name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
|
||||
ids:
|
||||
- none
|
||||
signs:
|
||||
- args: ["sign", "--dearmor", "--file", "${artifact}", "--out", "${signature}"]
|
||||
artifacts: checksum
|
||||
cmd: signore
|
||||
signature: ${artifact}.sig
|
||||
- args: ["sign", "--dearmor", "--file", "${artifact}", "--out", "${signature}"]
|
||||
artifacts: checksum
|
||||
cmd: signore
|
||||
id: key-id
|
||||
signature: ${artifact}.72D7468F.sig
|
||||
snapshot:
|
||||
name_template: "{{ .Tag }}-next"
|
||||
@@ -0,0 +1,96 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# Reference: https://github.com/hashicorp/crt-core-helloworld/blob/main/.release/ci.hcl (private repository)
|
||||
#
|
||||
# One way to validate this file, with a local build of the orchestrator (an internal repo):
|
||||
#
|
||||
# $ GITHUB_TOKEN="not-used" orchestrator parse config -use-v2 -local-config=.release/ci.hcl
|
||||
|
||||
schema = "2"
|
||||
|
||||
project "terraform-provider-boundary" {
|
||||
// team is currently unused and has no meaning
|
||||
// but is required to be non-empty by CRT orchestator
|
||||
team = "_UNUSED_"
|
||||
|
||||
slack {
|
||||
notification_channel = "C01BWLSMJ03" // #proj-boundary-release-engineering
|
||||
}
|
||||
|
||||
github {
|
||||
organization = "hashicorp"
|
||||
repository = "terraform-provider-boundary"
|
||||
release_branches = ["main", "release/**"]
|
||||
}
|
||||
}
|
||||
|
||||
event "merge" {
|
||||
}
|
||||
|
||||
event "build" {
|
||||
action "build" {
|
||||
depends = ["merge"]
|
||||
|
||||
organization = "hashicorp"
|
||||
repository = "terraform-provider-boundary"
|
||||
workflow = "build"
|
||||
}
|
||||
}
|
||||
|
||||
event "prepare" {
|
||||
# `prepare` is the Common Release Tooling (CRT) artifact processing workflow.
|
||||
# It prepares artifacts for potential promotion to staging and production.
|
||||
# For example, it scans and signs artifacts.
|
||||
|
||||
depends = ["build"]
|
||||
|
||||
action "prepare" {
|
||||
organization = "hashicorp"
|
||||
repository = "crt-workflows-common"
|
||||
workflow = "prepare"
|
||||
depends = ["build"]
|
||||
}
|
||||
|
||||
notification {
|
||||
on = "fail"
|
||||
}
|
||||
}
|
||||
|
||||
event "trigger-staging" {
|
||||
}
|
||||
|
||||
event "promote-staging" {
|
||||
action "promote-staging" {
|
||||
organization = "hashicorp"
|
||||
repository = "crt-workflows-common"
|
||||
workflow = "promote-staging"
|
||||
depends = null
|
||||
config = "release-metadata.hcl"
|
||||
}
|
||||
|
||||
depends = ["trigger-staging"]
|
||||
|
||||
notification {
|
||||
on = "always"
|
||||
}
|
||||
}
|
||||
|
||||
event "trigger-production" {
|
||||
}
|
||||
|
||||
event "promote-production" {
|
||||
action "promote-production" {
|
||||
organization = "hashicorp"
|
||||
repository = "crt-workflows-common"
|
||||
workflow = "promote-production"
|
||||
depends = null
|
||||
config = ""
|
||||
}
|
||||
|
||||
depends = ["trigger-production"]
|
||||
|
||||
notification {
|
||||
on = "always"
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,6 @@
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
url_source_repository = "https://github.com/hashicorp/terraform-provider-boundary"
|
||||
url_project_website = "https://registry.terraform.io/providers/hashicorp/boundary"
|
||||
url_license = "https://github.com/hashicorp/terraform-provider-boundary/blob/main/LICENSE"
|
||||
url_release_notes = "https://github.com/hashicorp/terraform-provider-boundary/blob/main/CHANGELOG.md"
|
||||
@@ -0,0 +1,14 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# Reference: https://github.com/hashicorp/security-scanner/blob/main/CONFIG.md#binary (private repository)
|
||||
|
||||
binary {
|
||||
secrets {
|
||||
all = true
|
||||
}
|
||||
go_modules = true
|
||||
osv = true
|
||||
oss_index = false
|
||||
nvd = false
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
schema = 1
|
||||
artifacts {
|
||||
# This should match the `matrix` in .github/workflows/build.yml
|
||||
zip = [
|
||||
"terraform-provider-boundary_${version}_darwin_amd64.zip",
|
||||
"terraform-provider-boundary_${version}_darwin_arm64.zip",
|
||||
"terraform-provider-boundary_${version}_freebsd_386.zip",
|
||||
"terraform-provider-boundary_${version}_freebsd_amd64.zip",
|
||||
"terraform-provider-boundary_${version}_freebsd_arm.zip",
|
||||
"terraform-provider-boundary_${version}_linux_386.zip",
|
||||
"terraform-provider-boundary_${version}_linux_amd64.zip",
|
||||
"terraform-provider-boundary_${version}_linux_arm.zip",
|
||||
"terraform-provider-boundary_${version}_linux_arm64.zip",
|
||||
"terraform-provider-boundary_${version}_windows_386.zip",
|
||||
"terraform-provider-boundary_${version}_windows_amd64.zip",
|
||||
]
|
||||
}
|
||||
+68
-1
@@ -2,6 +2,73 @@
|
||||
|
||||
Canonical reference for changes, improvements, and bugfixes for the Boundary Terraform provider.
|
||||
|
||||
## Next
|
||||
|
||||
## 1.5.1 (Feb 2nd, 2026)
|
||||
|
||||
### New and Improved
|
||||
|
||||
* Adds support for Vault LDAP Credential Store.
|
||||
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/778))
|
||||
|
||||
## 1.5.0 (December 19th, 2025)
|
||||
|
||||
### New and Improved
|
||||
|
||||
* Adds support for Password credentials.
|
||||
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/758))
|
||||
|
||||
|
||||
## 1.4.0 (September 25th, 2025)
|
||||
|
||||
### New and Improved
|
||||
|
||||
* Adds support for new RDP target type and Username, Password, and Domain credentials.
|
||||
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/735))
|
||||
|
||||
## 1.3.1 (July 11th, 2025)
|
||||
|
||||
### Bug Fix
|
||||
|
||||
* Fixes a problem where the KMS plugins were not being bundled in the provider's
|
||||
binary ([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/717))
|
||||
|
||||
## 1.3.0 (July 9th, 2025)
|
||||
|
||||
### Known Issues
|
||||
|
||||
* `Error configuring kms: plugin is nil`: This error message may occur when you
|
||||
attempt to use KMS plugin functionality. The [KMS plugins](plugins/kms/mains)
|
||||
were not bundled in this Terraform provider release and thus any functionality
|
||||
related to this will not work.
|
||||
|
||||
### New and Improved
|
||||
|
||||
* Updates various dependencies across the provider
|
||||
([Example PR](https://github.com/hashicorp/terraform-provider-boundary/pull/708))
|
||||
|
||||
## 1.2.0 (October 21, 2024)
|
||||
|
||||
### New and Improved
|
||||
|
||||
* Introduces support for specifying a worker filter in dynamic host catalogs
|
||||
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/626))
|
||||
|
||||
### Deprecations/Changes
|
||||
|
||||
* With Boundary 0.15, a deprecation notice was put under the `grant_scope_id`
|
||||
field, and a new `grant_scope_ids` field was introduced to replace it. With
|
||||
Boundary v0.17.1 and Boundary API v0.0.52, `grant_scope_id` support was
|
||||
entirely removed. `grant_scope_id` support has now been removed from this TF
|
||||
provider.
|
||||
|
||||
## 1.1.15 (May 1, 2024)
|
||||
|
||||
### New and Improved
|
||||
|
||||
* Add support for a target alias as a resource
|
||||
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/571))
|
||||
|
||||
## 1.1.14 (February 14, 2024)
|
||||
|
||||
### New and Improved
|
||||
@@ -328,4 +395,4 @@ Update provider to handle new domain errors ([PR](https://github.com/hashicorp/t
|
||||
|
||||
## 0.1.0 (October 14, 2020)
|
||||
|
||||
Initial release!
|
||||
Initial release!
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# These owners will be the default owners for everything in
|
||||
# the repo, unless a later match takes precedence.
|
||||
|
||||
@hashicorp/boundary
|
||||
* @hashicorp/boundary
|
||||
@@ -97,10 +97,10 @@ Please see our detailed docs for individual resource usage. Below is a complex e
|
||||
|
||||
```hcl
|
||||
provider "boundary" {
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_id = "ampw_1234567890" # changeme
|
||||
password_auth_method_login_name = "myuser" # changeme
|
||||
password_auth_method_password = "passpass" # changeme
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_id = "ampw_1234567890" # changeme
|
||||
auth_method_login_name = "myuser" # changeme
|
||||
auth_method_password = "passpass" # changeme
|
||||
}
|
||||
|
||||
variable "users" {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
page_title: "boundary_auth_method Data Source - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The boundaryauthmethod data source allows you to find a Boundary auth method.
|
||||
The boundary_auth_method data source allows you to find a Boundary auth method.
|
||||
---
|
||||
|
||||
# boundary_auth_method (Data Source)
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "boundary_role Data Source - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The boundary_role data source allows you to find a Boundary role.
|
||||
---
|
||||
|
||||
# boundary_role (Data Source)
|
||||
|
||||
The boundary_role data source allows you to find a Boundary role.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
# Role from the global scope
|
||||
data "boundary_role" "global_role" {
|
||||
name = "global_role_one"
|
||||
}
|
||||
|
||||
# Role from an org scope
|
||||
data "boundary_scope" "org" {
|
||||
name = "org_one"
|
||||
scope_id = "global"
|
||||
}
|
||||
|
||||
data "boundary_role" "org_role" {
|
||||
name = "org_role_one"
|
||||
scope_id = data.boundary_scope.org.id
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `name` (String) The name of the role to retrieve.
|
||||
|
||||
### Optional
|
||||
|
||||
- `scope_id` (String) The scope ID in which the resource is created. Defaults `global` if unset.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `description` (String) The description of the retrieved role.
|
||||
- `grant_scope_ids` (Set of String) The list of scope IDs for the role's grants.
|
||||
- `grant_strings` (Set of String) The list of stringified grants for the role.
|
||||
- `id` (String) The ID of the retrieved role.
|
||||
- `principal_ids` (Set of String) The list of principal (user or group) IDs added as principals on the role.
|
||||
- `scope` (List of Object) (see [below for nested schema](#nestedatt--scope))
|
||||
|
||||
<a id="nestedatt--scope"></a>
|
||||
### Nested Schema for `scope`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `description` (String)
|
||||
- `id` (String)
|
||||
- `name` (String)
|
||||
- `parent_scope_id` (String)
|
||||
- `type` (String)
|
||||
+11
-11
@@ -15,23 +15,23 @@ Do not keep your authentication password in HCL for production environments, use
|
||||
|
||||
```terraform
|
||||
provider "boundary" {
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_id = "ampw_1234567890" # changeme
|
||||
password_auth_method_login_name = "myuser" # changeme
|
||||
password_auth_method_password = "passpass" # changeme
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_id = "ampw_1234567890" # changeme
|
||||
auth_method_login_name = "myuser" # changeme
|
||||
auth_method_password = "passpass" # changeme
|
||||
}
|
||||
|
||||
provider "boundary" {
|
||||
addr = "http://127.0.0.1:9200"
|
||||
password_auth_method_login_name = "myuser"
|
||||
password_auth_method_password = "passpass"
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_login_name = "myuser"
|
||||
auth_method_password = "passpass"
|
||||
}
|
||||
|
||||
provider "boundary" {
|
||||
addr = "http://127.0.0.1:9200"
|
||||
password_auth_method_login_name = "myuser"
|
||||
password_auth_method_password = "passpass"
|
||||
scope_id = "s_1234567890"
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_login_name = "myuser"
|
||||
auth_method_password = "passpass"
|
||||
scope_id = "s_1234567890"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ resource "boundary_user" "einstein" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_account_ldap.foo <my-id>
|
||||
```
|
||||
@@ -56,6 +56,8 @@ resource "boundary_account_password" "jeff" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_account_password.foo <my-id>
|
||||
```
|
||||
@@ -0,0 +1,108 @@
|
||||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "boundary_alias_target Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The target alias resource allows you to configure a Boundary target alias.
|
||||
---
|
||||
|
||||
# boundary_alias_target (Resource)
|
||||
|
||||
The target alias resource allows you to configure a Boundary target alias.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "global scope"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_host_catalog_static" "foo" {
|
||||
name = "test"
|
||||
description = "test catalog"
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_host_static" "foo" {
|
||||
name = "foo"
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
address = "10.0.0.1"
|
||||
}
|
||||
|
||||
resource "boundary_host_static" "bar" {
|
||||
name = "bar"
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
address = "127.0.0.1"
|
||||
}
|
||||
|
||||
resource "boundary_host_set_static" "foo" {
|
||||
name = "foo"
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
|
||||
host_ids = [
|
||||
boundary_host_static.foo.id,
|
||||
boundary_host_static.bar.id,
|
||||
]
|
||||
}
|
||||
|
||||
resource "boundary_target" "foo" {
|
||||
name = "foo"
|
||||
description = "Foo target"
|
||||
type = "tcp"
|
||||
default_port = "22"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set_static.foo.id,
|
||||
]
|
||||
}
|
||||
|
||||
resource "boundary_alias_target" "example_alias_target" {
|
||||
name = "example_alias_target"
|
||||
description = "Example alias to target foo using host boundary_host_static.bar"
|
||||
scope_id = "global"
|
||||
value = "example.bar.foo.boundary"
|
||||
destination_id = boundary_target.foo.id
|
||||
authorize_session_host_id = boundary_host_static.bar.id
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `scope_id` (String) The scope ID.
|
||||
- `value` (String) The value of the alias.
|
||||
|
||||
### Optional
|
||||
|
||||
- `authorize_session_host_id` (String) The host id to pass to Boundary when performing an authorize session action.
|
||||
- `description` (String) The alias description.
|
||||
- `destination_id` (String) The destination of the alias.
|
||||
- `name` (String) The alias name. Defaults to the resource name.
|
||||
- `type` (String) The type of alias; hardcoded.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `id` (String) The ID of the account.
|
||||
|
||||
## Import
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_alias_target.example_alias_target <my-id>
|
||||
```
|
||||
@@ -25,6 +25,12 @@ resource "boundary_auth_method" "password" {
|
||||
scope_id = boundary_scope.org.id
|
||||
type = "password"
|
||||
}
|
||||
|
||||
resource "boundary_auth_method" "password_is_primary" {
|
||||
scope_id = boundary_scope.org.id
|
||||
type = "password"
|
||||
is_primary_for_scope = true
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
@@ -38,6 +44,7 @@ resource "boundary_auth_method" "password" {
|
||||
### Optional
|
||||
|
||||
- `description` (String) The auth method description.
|
||||
- `is_primary_for_scope` (Boolean) When true, makes this auth method the primary auth method for the scope in which it resides.
|
||||
- `min_login_name_length` (Number, Deprecated) The minimum login name length.
|
||||
- `min_password_length` (Number, Deprecated) The minimum password length.
|
||||
- `name` (String) The auth method name. Defaults to the resource name.
|
||||
@@ -50,6 +57,8 @@ resource "boundary_auth_method" "password" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_auth_method.foo <my-id>
|
||||
```
|
||||
@@ -3,7 +3,7 @@
|
||||
page_title: "boundary_auth_method_ldap Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The LDAP auth method resource allows you to configure a Boundary authmethodldap.
|
||||
The LDAP auth method resource allows you to configure a Boundary auth_method_ldap.
|
||||
---
|
||||
|
||||
# boundary_auth_method_ldap (Resource)
|
||||
@@ -83,6 +83,8 @@ resource "boundary_auth_method_ldap" "forumsys_ldap" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_auth_method_ldap.foo <my-id>
|
||||
```
|
||||
@@ -3,7 +3,7 @@
|
||||
page_title: "boundary_auth_method_oidc Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The OIDC auth method resource allows you to configure a Boundary authmethodoidc.
|
||||
The OIDC auth method resource allows you to configure a Boundary auth_method_oidc.
|
||||
---
|
||||
|
||||
# boundary_auth_method_oidc (Resource)
|
||||
@@ -94,6 +94,8 @@ resource "boundary_auth_method_oidc" "oidc_with_multiple_prompts" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_auth_method_oidc.foo <my-id>
|
||||
```
|
||||
@@ -3,14 +3,33 @@
|
||||
page_title: "boundary_auth_method_password Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The auth method resource allows you to configure a Boundary authmethodpassword.
|
||||
The auth method resource allows you to configure a Boundary auth_method_password.
|
||||
---
|
||||
|
||||
# boundary_auth_method_password (Resource)
|
||||
|
||||
The auth method resource allows you to configure a Boundary auth_method_password.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "My first scope!"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_auth_method_password" "password" {
|
||||
scope_id = boundary_scope.org.id
|
||||
}
|
||||
|
||||
resource "boundary_auth_method_password" "password_is_primary" {
|
||||
scope_id = boundary_scope.org.id
|
||||
is_primary_for_scope = true
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
@@ -22,6 +41,7 @@ The auth method resource allows you to configure a Boundary auth_method_password
|
||||
### Optional
|
||||
|
||||
- `description` (String) The auth method description.
|
||||
- `is_primary_for_scope` (Boolean) When true, makes this auth method the primary auth method for the scope in which it resides.
|
||||
- `min_login_name_length` (Number) The minimum login name length.
|
||||
- `min_password_length` (Number) The minimum password length.
|
||||
- `name` (String) The auth method name. Defaults to the resource name.
|
||||
@@ -30,3 +50,13 @@ The auth method resource allows you to configure a Boundary auth_method_password
|
||||
### Read-Only
|
||||
|
||||
- `id` (String) The ID of the account.
|
||||
|
||||
## Import
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_auth_method_password.foo <my-id>
|
||||
```
|
||||
@@ -64,6 +64,8 @@ resource "boundary_credential_json" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_json.example_json <my-id>
|
||||
```
|
||||
@@ -110,6 +110,8 @@ resource "boundary_credential_library_vault" "quz" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_library_vault.foo <my-id>
|
||||
```
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "boundary_credential_library_vault_ldap Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The credential library for Vault LDAP resource allows you to configure a Boundary credential library for Vault LDAP.
|
||||
---
|
||||
|
||||
# boundary_credential_library_vault_ldap (Resource)
|
||||
|
||||
The credential library for Vault LDAP resource allows you to configure a Boundary credential library for Vault LDAP.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "My first scope!"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_credential_store_vault" "foo" {
|
||||
name = "foo"
|
||||
description = "My first Vault credential store!"
|
||||
address = "http://127.0.0.1:8200" # change to Vault address
|
||||
token = "s.0ufRo6XEGU2jOqnIr7OlFYP5" # change to valid Vault token
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_credential_library_vault_ldap" "foo-static" {
|
||||
name = "foo"
|
||||
description = "My first static Vault LDAP credential library!"
|
||||
credential_store_id = boundary_credential_store_vault.foo.id
|
||||
path = "ldap/static-cred/foo" # change to Vault backend path
|
||||
}
|
||||
|
||||
resource "boundary_credential_library_vault_ldap" "bar-dynamic" {
|
||||
name = "bar"
|
||||
description = "My first dynamic Vault LDAP credential library!"
|
||||
credential_store_id = boundary_credential_store_vault.foo.id
|
||||
path = "ldap/creds/bar" # change to Vault backend path
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `credential_store_id` (String) The ID of the credential store that this library belongs to.
|
||||
- `path` (String) The path in Vault to request credentials from.
|
||||
|
||||
### Optional
|
||||
|
||||
- `description` (String) The Vault LDAP credential library description.
|
||||
- `name` (String) The Vault LDAP credential library name. Defaults to the resource name.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `id` (String) The ID of the Vault LDAP credential library.
|
||||
|
||||
## Import
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_library_vault_ldap.foo <my-id>
|
||||
```
|
||||
@@ -107,6 +107,8 @@ resource "boundary_credential_library_vault_ssh_certificate" "baz" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_library_vault_ssh_certificate.foo <my-id>
|
||||
```
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "boundary_credential_password Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The password credential resource allows you to configure a credential using a password.
|
||||
---
|
||||
|
||||
# boundary_credential_password (Resource)
|
||||
|
||||
The password credential resource allows you to configure a credential using a password.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "global scope"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_credential_store_static" "example" {
|
||||
name = "example_static_credential_store"
|
||||
description = "My first static credential store!"
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_credential_password" "example" {
|
||||
name = "example_password"
|
||||
description = "My first password credential!"
|
||||
credential_store_id = boundary_credential_store_static.example.id
|
||||
password = "my-password"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `credential_store_id` (String) The credential store in which to save this password credential.
|
||||
- `password` (String, Sensitive) The password of this password credential.
|
||||
|
||||
### Optional
|
||||
|
||||
- `description` (String) The description of this password credential.
|
||||
- `name` (String) The name of this password credential. Defaults to the resource name.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `id` (String) The ID of this password credential.
|
||||
- `password_hmac` (String) The password hmac.
|
||||
|
||||
## Import
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_password.example <my-id>
|
||||
```
|
||||
@@ -69,6 +69,8 @@ resource "boundary_credential_ssh_private_key" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_ssh_private_key.example_ssh_private_key <my-id>
|
||||
```
|
||||
@@ -55,6 +55,8 @@ resource "boundary_credential_store_static" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_store_static.example_static_credential_store <my-id>
|
||||
```
|
||||
@@ -68,6 +68,8 @@ resource "boundary_credential_store_vault" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_store_vault.foo <my-id>
|
||||
```
|
||||
@@ -66,6 +66,8 @@ resource "boundary_credential_username_password" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_username_password.example_username_password <my-id>
|
||||
```
|
||||
@@ -0,0 +1,75 @@
|
||||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "boundary_credential_username_password_domain Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The username-password-domain credential resource allows you to configure a credential using a username, password and domain.
|
||||
---
|
||||
|
||||
# boundary_credential_username_password_domain (Resource)
|
||||
|
||||
The username-password-domain credential resource allows you to configure a credential using a username, password and domain.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "global scope"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_credential_store_static" "example" {
|
||||
name = "example_static_credential_store"
|
||||
description = "My first static credential store!"
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_credential_username_password_domain" "example" {
|
||||
name = "example_username_password_domain"
|
||||
description = "My first username password domain credential!"
|
||||
credential_store_id = boundary_credential_store_static.example.id
|
||||
username = "my-username"
|
||||
password = "my-password"
|
||||
domain = "my-domain"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `credential_store_id` (String) The credential store in which to save this username-password-domain credential.
|
||||
- `password` (String, Sensitive) The password of this username-password-domain credential.
|
||||
|
||||
### Optional
|
||||
|
||||
- `description` (String) The description of this username-password-domain credential.
|
||||
- `domain` (String) The domain of this username-password-domain credential. This field is required unless provided as part of the username field instead (see username field description).
|
||||
- `name` (String) The name of this username-password-domain credential. Defaults to the resource name.
|
||||
- `username` (String) This field is required even though it is marked as optional. The username of this username-password-domain credential. Can also contain a domain if provided as username@domain or domain\username
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `id` (String) The ID of this username-password-domain credential.
|
||||
- `password_hmac` (String) The password hmac.
|
||||
|
||||
## Import
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_username_password_domain.example_username_password_domain <my-id>
|
||||
```
|
||||
@@ -66,6 +66,8 @@ resource "boundary_host" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_host.foo <my-id>
|
||||
```
|
||||
@@ -57,6 +57,8 @@ resource "boundary_host_catalog" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_host_catalog.foo <my-id>
|
||||
```
|
||||
@@ -94,6 +94,7 @@ resource "boundary_host_catalog_plugin" "azure_example" {
|
||||
- `plugin_name` (String) The name of the plugin that should back the resource. This or plugin_id must be defined.
|
||||
- `secrets_hmac` (String) The HMAC'd secrets value returned from the server.
|
||||
- `secrets_json` (String, Sensitive) The secrets for the host catalog. Either values encoded with the "jsonencode" function, pre-escaped JSON string, or a file:// or env:// path. Set to a string "null" to clear any existing values. NOTE: Unlike "attributes_json", removing this block will NOT clear secrets from the host catalog; this allows injecting secrets for one call, then removing them for storage.
|
||||
- `worker_filter` (String) HCP Only. A filter used to control which PKI workers can handle dynamic host catalog requests.
|
||||
|
||||
### Read-Only
|
||||
|
||||
@@ -103,6 +104,8 @@ resource "boundary_host_catalog_plugin" "azure_example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_host_catalog_plugin.foo <my-id>
|
||||
```
|
||||
@@ -55,6 +55,8 @@ resource "boundary_host_catalog_static" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_host_catalog_static.foo <my-id>
|
||||
```
|
||||
@@ -81,6 +81,8 @@ resource "boundary_host_set" "web" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_host_set.foo <my-id>
|
||||
```
|
||||
@@ -3,7 +3,7 @@
|
||||
page_title: "boundary_host_set_plugin Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The hostsetplugin resource allows you to configure a Boundary host set. Host sets are always part of a host catalog, so a host catalog resource should be used inline or you should have the host catalog ID in hand to successfully configure a host set.
|
||||
The host_set_plugin resource allows you to configure a Boundary host set. Host sets are always part of a host catalog, so a host catalog resource should be used inline or you should have the host catalog ID in hand to successfully configure a host set.
|
||||
---
|
||||
|
||||
# boundary_host_set_plugin (Resource)
|
||||
@@ -140,6 +140,8 @@ resource "boundary_host_set_plugin" "foodev" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_host_set_plugin.foo <my-id>
|
||||
```
|
||||
@@ -3,7 +3,7 @@
|
||||
page_title: "boundary_host_set_static Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The hostsetstatic resource allows you to configure a Boundary host set. Host sets are always part of a host catalog, so a host catalog resource should be used inline or you should have the host catalog ID in hand to successfully configure a host set.
|
||||
The host_set_static resource allows you to configure a Boundary host set. Host sets are always part of a host catalog, so a host catalog resource should be used inline or you should have the host catalog ID in hand to successfully configure a host set.
|
||||
---
|
||||
|
||||
# boundary_host_set_static (Resource)
|
||||
@@ -77,6 +77,8 @@ resource "boundary_host_set_static" "web" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_host_set_static.foo <my-id>
|
||||
```
|
||||
@@ -64,6 +64,8 @@ resource "boundary_host_static" "example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_host_static.foo <my-id>
|
||||
```
|
||||
@@ -64,6 +64,8 @@ resource "boundary_managed_group_ldap" "forumsys_scientists" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_managed_group_ldap.foo <my-id>
|
||||
```
|
||||
@@ -127,7 +127,6 @@ resource "boundary_role" "readonly" {
|
||||
### Optional
|
||||
|
||||
- `description` (String) The role description.
|
||||
- `grant_scope_id` (String, Deprecated) For Boundary 0.15+, use `grant_scope_ids` instead. The scope for which the grants in the role should apply.
|
||||
- `grant_scope_ids` (Set of String) A list of scopes for which the grants in this role should apply, which can include the special values "this", "children", or "descendants"
|
||||
- `grant_strings` (Set of String) A list of stringified grants for the role.
|
||||
- `name` (String) The role name. Defaults to the resource name.
|
||||
|
||||
@@ -87,6 +87,8 @@ resource "boundary_storage_bucket" "aws_dynamic_credentials_example" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_storage_bucket.foo <my-id>
|
||||
```
|
||||
+32
-20
@@ -50,35 +50,30 @@ resource "boundary_credential_library_vault" "foo" {
|
||||
credential_type = "username_password"
|
||||
}
|
||||
|
||||
resource "boundary_host_catalog" "foo" {
|
||||
resource "boundary_host_catalog_static" "foo" {
|
||||
name = "test"
|
||||
description = "test catalog"
|
||||
scope_id = boundary_scope.project.id
|
||||
type = "static"
|
||||
}
|
||||
|
||||
resource "boundary_host" "foo" {
|
||||
type = "static"
|
||||
resource "boundary_host_static" "foo" {
|
||||
name = "foo"
|
||||
host_catalog_id = boundary_host_catalog.foo.id
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
address = "10.0.0.1"
|
||||
}
|
||||
|
||||
resource "boundary_host" "bar" {
|
||||
type = "static"
|
||||
resource "boundary_host_static" "bar" {
|
||||
name = "bar"
|
||||
host_catalog_id = boundary_host_catalog.foo.id
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
address = "10.0.0.1"
|
||||
}
|
||||
|
||||
resource "boundary_host_set" "foo" {
|
||||
type = "static"
|
||||
resource "boundary_host_set_static" "foo" {
|
||||
name = "foo"
|
||||
host_catalog_id = boundary_host_catalog.foo.id
|
||||
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
host_ids = [
|
||||
boundary_host.foo.id,
|
||||
boundary_host.bar.id,
|
||||
boundary_host_static.foo.id,
|
||||
boundary_host_static.bar.id,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -93,7 +88,7 @@ resource "boundary_storage_bucket" "aws_example" {
|
||||
"access_key_id" = "aws_access_key_id_value",
|
||||
"secret_access_key" = "aws_secret_access_key_value"
|
||||
})
|
||||
worker_filter = "\"pki\" in \"/tags/type\""
|
||||
egress_worker_filter = "\"egress\" in \"/tags/type\""
|
||||
}
|
||||
|
||||
resource "boundary_target" "foo" {
|
||||
@@ -103,7 +98,7 @@ resource "boundary_target" "foo" {
|
||||
default_port = "22"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set.foo.id
|
||||
boundary_host_set_static.foo.id
|
||||
]
|
||||
brokered_credential_source_ids = [
|
||||
boundary_credential_library_vault.foo.id
|
||||
@@ -112,12 +107,12 @@ resource "boundary_target" "foo" {
|
||||
|
||||
resource "boundary_target" "ssh_foo" {
|
||||
name = "ssh_foo"
|
||||
description = "Ssh target"
|
||||
description = "SSH target"
|
||||
type = "ssh"
|
||||
default_port = "22"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set.foo.id
|
||||
boundary_host_set_static.foo.id
|
||||
]
|
||||
injected_application_credential_source_ids = [
|
||||
boundary_credential_library_vault.foo.id
|
||||
@@ -126,12 +121,12 @@ resource "boundary_target" "ssh_foo" {
|
||||
|
||||
resource "boundary_target" "ssh_session_recording_foo" {
|
||||
name = "ssh_foo"
|
||||
description = "Ssh target"
|
||||
description = "SSH target"
|
||||
type = "ssh"
|
||||
default_port = "22"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set.foo.id
|
||||
boundary_host_set_static.foo.id
|
||||
]
|
||||
injected_application_credential_source_ids = [
|
||||
boundary_credential_library_vault.foo.id
|
||||
@@ -140,6 +135,21 @@ resource "boundary_target" "ssh_session_recording_foo" {
|
||||
storage_bucket_id = boundary_storage_bucket.aws_example
|
||||
}
|
||||
|
||||
resource "boundary_target" "rdp_foo" {
|
||||
name = "rdp_foo"
|
||||
description = "RDP target"
|
||||
type = "rdp"
|
||||
default_port = "3389"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set_static.foo.id
|
||||
]
|
||||
injected_application_credential_source_ids = [
|
||||
boundary_credential_library_vault.foo.id
|
||||
]
|
||||
egress_worker_filter = "\"egress\" in \"/tags/type\""
|
||||
}
|
||||
|
||||
resource "boundary_target" "address_foo" {
|
||||
name = "address_foo"
|
||||
description = "Foo target with an address"
|
||||
@@ -184,6 +194,8 @@ resource "boundary_target" "address_foo" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_target.foo <my-id>
|
||||
```
|
||||
@@ -62,6 +62,8 @@ resource "boundary_user" "jeff" {
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
terraform import boundary_user.foo <my-id>
|
||||
```
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "boundary_worker Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
@@ -12,16 +11,22 @@ The resource allows you to create a self-managed worker object.
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Controller-led worker
|
||||
|
||||
```terraform
|
||||
resource "boundary_worker" "controller_led" {
|
||||
scope_id = "global"
|
||||
name = "worker 1"
|
||||
name = "controller-led-worker-1"
|
||||
description = "self managed worker with controller led auth"
|
||||
}
|
||||
```
|
||||
|
||||
### Worker-led worker
|
||||
|
||||
```terraform
|
||||
resource "boundary_worker" "worker_led" {
|
||||
scope_id = "global"
|
||||
name = "worker 2"
|
||||
name = "worker-led-worker-1"
|
||||
description = "self managed worker with worker led auth"
|
||||
worker_generated_auth_token = var.worker_generated_auth_token
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Role from the global scope
|
||||
data "boundary_role" "global_role" {
|
||||
name = "global_role_one"
|
||||
}
|
||||
|
||||
# Role from an org scope
|
||||
data "boundary_scope" "org" {
|
||||
name = "org_one"
|
||||
scope_id = "global"
|
||||
}
|
||||
|
||||
data "boundary_role" "org_role" {
|
||||
name = "org_role_one"
|
||||
scope_id = data.boundary_scope.org.id
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
provider "boundary" {
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_id = "ampw_1234567890" # changeme
|
||||
password_auth_method_login_name = "myuser" # changeme
|
||||
password_auth_method_password = "passpass" # changeme
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_id = "ampw_1234567890" # changeme
|
||||
auth_method_login_name = "myuser" # changeme
|
||||
auth_method_password = "passpass" # changeme
|
||||
}
|
||||
|
||||
provider "boundary" {
|
||||
addr = "http://127.0.0.1:9200"
|
||||
password_auth_method_login_name = "myuser"
|
||||
password_auth_method_password = "passpass"
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_login_name = "myuser"
|
||||
auth_method_password = "passpass"
|
||||
}
|
||||
|
||||
provider "boundary" {
|
||||
addr = "http://127.0.0.1:9200"
|
||||
password_auth_method_login_name = "myuser"
|
||||
password_auth_method_password = "passpass"
|
||||
scope_id = "s_1234567890"
|
||||
addr = "http://127.0.0.1:9200"
|
||||
auth_method_login_name = "myuser"
|
||||
auth_method_password = "passpass"
|
||||
scope_id = "s_1234567890"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
terraform import boundary_alias_target.example_alias_target <my-id>
|
||||
@@ -0,0 +1,62 @@
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "global scope"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_host_catalog_static" "foo" {
|
||||
name = "test"
|
||||
description = "test catalog"
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_host_static" "foo" {
|
||||
name = "foo"
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
address = "10.0.0.1"
|
||||
}
|
||||
|
||||
resource "boundary_host_static" "bar" {
|
||||
name = "bar"
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
address = "127.0.0.1"
|
||||
}
|
||||
|
||||
resource "boundary_host_set_static" "foo" {
|
||||
name = "foo"
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
|
||||
host_ids = [
|
||||
boundary_host_static.foo.id,
|
||||
boundary_host_static.bar.id,
|
||||
]
|
||||
}
|
||||
|
||||
resource "boundary_target" "foo" {
|
||||
name = "foo"
|
||||
description = "Foo target"
|
||||
type = "tcp"
|
||||
default_port = "22"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set_static.foo.id,
|
||||
]
|
||||
}
|
||||
|
||||
resource "boundary_alias_target" "example_alias_target" {
|
||||
name = "example_alias_target"
|
||||
description = "Example alias to target foo using host boundary_host_static.bar"
|
||||
scope_id = "global"
|
||||
value = "example.bar.foo.boundary"
|
||||
destination_id = boundary_target.foo.id
|
||||
authorize_session_host_id = boundary_host_static.bar.id
|
||||
}
|
||||
@@ -10,3 +10,9 @@ resource "boundary_auth_method" "password" {
|
||||
scope_id = boundary_scope.org.id
|
||||
type = "password"
|
||||
}
|
||||
|
||||
resource "boundary_auth_method" "password_is_primary" {
|
||||
scope_id = boundary_scope.org.id
|
||||
type = "password"
|
||||
is_primary_for_scope = true
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
terraform import boundary_auth_method_password.foo <my-id>
|
||||
@@ -0,0 +1,16 @@
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "My first scope!"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_auth_method_password" "password" {
|
||||
scope_id = boundary_scope.org.id
|
||||
}
|
||||
|
||||
resource "boundary_auth_method_password" "password_is_primary" {
|
||||
scope_id = boundary_scope.org.id
|
||||
is_primary_for_scope = true
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
terraform import boundary_credential_library_vault_ldap.foo <my-id>
|
||||
@@ -0,0 +1,36 @@
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "My first scope!"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_credential_store_vault" "foo" {
|
||||
name = "foo"
|
||||
description = "My first Vault credential store!"
|
||||
address = "http://127.0.0.1:8200" # change to Vault address
|
||||
token = "s.0ufRo6XEGU2jOqnIr7OlFYP5" # change to valid Vault token
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_credential_library_vault_ldap" "foo-static" {
|
||||
name = "foo"
|
||||
description = "My first static Vault LDAP credential library!"
|
||||
credential_store_id = boundary_credential_store_vault.foo.id
|
||||
path = "ldap/static-cred/foo" # change to Vault backend path
|
||||
}
|
||||
|
||||
resource "boundary_credential_library_vault_ldap" "bar-dynamic" {
|
||||
name = "bar"
|
||||
description = "My first dynamic Vault LDAP credential library!"
|
||||
credential_store_id = boundary_credential_store_vault.foo.id
|
||||
path = "ldap/creds/bar" # change to Vault backend path
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
terraform import boundary_credential_password.example <my-id>
|
||||
@@ -0,0 +1,27 @@
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "global scope"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_credential_store_static" "example" {
|
||||
name = "example_static_credential_store"
|
||||
description = "My first static credential store!"
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_credential_password" "example" {
|
||||
name = "example_password"
|
||||
description = "My first password credential!"
|
||||
credential_store_id = boundary_credential_store_static.example.id
|
||||
password = "my-password"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
terraform import boundary_credential_username_password_domain.example_username_password_domain <my-id>
|
||||
@@ -0,0 +1,29 @@
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "global scope"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_credential_store_static" "example" {
|
||||
name = "example_static_credential_store"
|
||||
description = "My first static credential store!"
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_credential_username_password_domain" "example" {
|
||||
name = "example_username_password_domain"
|
||||
description = "My first username password domain credential!"
|
||||
credential_store_id = boundary_credential_store_static.example.id
|
||||
username = "my-username"
|
||||
password = "my-password"
|
||||
domain = "my-domain"
|
||||
}
|
||||
@@ -35,35 +35,30 @@ resource "boundary_credential_library_vault" "foo" {
|
||||
credential_type = "username_password"
|
||||
}
|
||||
|
||||
resource "boundary_host_catalog" "foo" {
|
||||
resource "boundary_host_catalog_static" "foo" {
|
||||
name = "test"
|
||||
description = "test catalog"
|
||||
scope_id = boundary_scope.project.id
|
||||
type = "static"
|
||||
}
|
||||
|
||||
resource "boundary_host" "foo" {
|
||||
type = "static"
|
||||
resource "boundary_host_static" "foo" {
|
||||
name = "foo"
|
||||
host_catalog_id = boundary_host_catalog.foo.id
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
address = "10.0.0.1"
|
||||
}
|
||||
|
||||
resource "boundary_host" "bar" {
|
||||
type = "static"
|
||||
resource "boundary_host_static" "bar" {
|
||||
name = "bar"
|
||||
host_catalog_id = boundary_host_catalog.foo.id
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
address = "10.0.0.1"
|
||||
}
|
||||
|
||||
resource "boundary_host_set" "foo" {
|
||||
type = "static"
|
||||
resource "boundary_host_set_static" "foo" {
|
||||
name = "foo"
|
||||
host_catalog_id = boundary_host_catalog.foo.id
|
||||
|
||||
host_catalog_id = boundary_host_catalog_static.foo.id
|
||||
host_ids = [
|
||||
boundary_host.foo.id,
|
||||
boundary_host.bar.id,
|
||||
boundary_host_static.foo.id,
|
||||
boundary_host_static.bar.id,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -78,7 +73,7 @@ resource "boundary_storage_bucket" "aws_example" {
|
||||
"access_key_id" = "aws_access_key_id_value",
|
||||
"secret_access_key" = "aws_secret_access_key_value"
|
||||
})
|
||||
worker_filter = "\"pki\" in \"/tags/type\""
|
||||
egress_worker_filter = "\"egress\" in \"/tags/type\""
|
||||
}
|
||||
|
||||
resource "boundary_target" "foo" {
|
||||
@@ -88,7 +83,7 @@ resource "boundary_target" "foo" {
|
||||
default_port = "22"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set.foo.id
|
||||
boundary_host_set_static.foo.id
|
||||
]
|
||||
brokered_credential_source_ids = [
|
||||
boundary_credential_library_vault.foo.id
|
||||
@@ -97,12 +92,12 @@ resource "boundary_target" "foo" {
|
||||
|
||||
resource "boundary_target" "ssh_foo" {
|
||||
name = "ssh_foo"
|
||||
description = "Ssh target"
|
||||
description = "SSH target"
|
||||
type = "ssh"
|
||||
default_port = "22"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set.foo.id
|
||||
boundary_host_set_static.foo.id
|
||||
]
|
||||
injected_application_credential_source_ids = [
|
||||
boundary_credential_library_vault.foo.id
|
||||
@@ -111,12 +106,12 @@ resource "boundary_target" "ssh_foo" {
|
||||
|
||||
resource "boundary_target" "ssh_session_recording_foo" {
|
||||
name = "ssh_foo"
|
||||
description = "Ssh target"
|
||||
description = "SSH target"
|
||||
type = "ssh"
|
||||
default_port = "22"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set.foo.id
|
||||
boundary_host_set_static.foo.id
|
||||
]
|
||||
injected_application_credential_source_ids = [
|
||||
boundary_credential_library_vault.foo.id
|
||||
@@ -125,6 +120,21 @@ resource "boundary_target" "ssh_session_recording_foo" {
|
||||
storage_bucket_id = boundary_storage_bucket.aws_example
|
||||
}
|
||||
|
||||
resource "boundary_target" "rdp_foo" {
|
||||
name = "rdp_foo"
|
||||
description = "RDP target"
|
||||
type = "rdp"
|
||||
default_port = "3389"
|
||||
scope_id = boundary_scope.project.id
|
||||
host_source_ids = [
|
||||
boundary_host_set_static.foo.id
|
||||
]
|
||||
injected_application_credential_source_ids = [
|
||||
boundary_credential_library_vault.foo.id
|
||||
]
|
||||
egress_worker_filter = "\"egress\" in \"/tags/type\""
|
||||
}
|
||||
|
||||
resource "boundary_target" "address_foo" {
|
||||
name = "address_foo"
|
||||
description = "Foo target with an address"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
resource "boundary_worker" "controller_led" {
|
||||
scope_id = "global"
|
||||
name = "controller-led-worker-1"
|
||||
description = "self managed worker with controller led auth"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
resource "boundary_worker" "controller_led" {
|
||||
scope_id = "global"
|
||||
name = "worker 1"
|
||||
description = "self managed worker with controller-led auth"
|
||||
worker_generated_auth_token = var.worker_generated_auth_token
|
||||
}
|
||||
|
||||
resource "boundary_worker" "worker_led" {
|
||||
scope_id = "global"
|
||||
name = "worker 2"
|
||||
description = "self managed worker with worker-led auth"
|
||||
worker_generated_auth_token = var.worker_generated_auth_token
|
||||
}
|
||||
+1
-7
@@ -1,12 +1,6 @@
|
||||
resource "boundary_worker" "controller_led" {
|
||||
scope_id = "global"
|
||||
name = "worker 1"
|
||||
description = "self managed worker with controller led auth"
|
||||
}
|
||||
|
||||
resource "boundary_worker" "worker_led" {
|
||||
scope_id = "global"
|
||||
name = "worker 2"
|
||||
name = "worker-led-worker-1"
|
||||
description = "self managed worker with worker led auth"
|
||||
worker_generated_auth_token = var.worker_generated_auth_token
|
||||
}
|
||||
@@ -1,131 +1,134 @@
|
||||
module github.com/hashicorp/terraform-provider-boundary
|
||||
|
||||
go 1.21.5
|
||||
go 1.25.1
|
||||
|
||||
require (
|
||||
github.com/YakDriver/regexache v0.23.0
|
||||
github.com/hashicorp/boundary v0.15.0
|
||||
github.com/hashicorp/boundary/api v0.0.46-0.20240209231500-1b1c8b3bf9a6
|
||||
github.com/hashicorp/boundary/sdk v0.0.43-0.20240209231500-1b1c8b3bf9a6
|
||||
github.com/hashicorp/cap v0.5.0
|
||||
github.com/YakDriver/regexache v0.25.0
|
||||
github.com/hashicorp/boundary v0.21.0
|
||||
github.com/hashicorp/boundary/api v0.0.59
|
||||
github.com/hashicorp/boundary/sdk v0.0.56
|
||||
github.com/hashicorp/cap v0.12.0
|
||||
github.com/hashicorp/cap/ldap v0.0.0-20240206183135-ed8f24513744
|
||||
github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.16
|
||||
github.com/hashicorp/go-secure-stdlib/configutil/v2 v2.0.11
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8
|
||||
github.com/hashicorp/go-secure-stdlib/pluginutil/v2 v2.0.6
|
||||
github.com/hashicorp/terraform-plugin-docs v0.18.0
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.32.0
|
||||
github.com/jimlambrt/gldap v0.1.9
|
||||
github.com/hashicorp/go-cty v1.5.0
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.19
|
||||
github.com/hashicorp/go-secure-stdlib/configutil/v2 v2.0.13
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0
|
||||
github.com/hashicorp/go-secure-stdlib/pluginutil/v2 v2.0.8
|
||||
github.com/hashicorp/terraform-plugin-docs v0.24.0
|
||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1
|
||||
github.com/jimlambrt/gldap v0.1.14
|
||||
github.com/kr/pretty v0.3.1
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/crypto v0.19.0
|
||||
mvdan.cc/gofumpt v0.6.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
golang.org/x/crypto v0.45.0
|
||||
mvdan.cc/gofumpt v0.9.2
|
||||
)
|
||||
|
||||
require (
|
||||
al.essio.dev/pkg/shellescape v1.5.1 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 // indirect
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect
|
||||
github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.6 // indirect
|
||||
github.com/agext/levenshtein v1.2.2 // indirect
|
||||
github.com/alessio/shellescape v1.4.1 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/armon/go-radix v1.0.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||
github.com/cenkalti/backoff/v3 v3.0.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/containerd/continuity v0.3.0 // indirect
|
||||
github.com/coreos/go-oidc/v3 v3.8.0 // indirect
|
||||
github.com/danieljoos/wincred v1.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/cli v23.0.1+incompatible // indirect
|
||||
github.com/docker/docker v24.0.7+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/containerd/continuity v0.4.5 // indirect
|
||||
github.com/coreos/go-oidc/v3 v3.11.0 // indirect
|
||||
github.com/danieljoos/wincred v1.2.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v27.4.1+incompatible // indirect
|
||||
github.com/docker/docker v28.5.2+incompatible // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.5.1-0.20231206184617-48ba0b76bc88 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.7.0 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/glebarez/sqlite v1.9.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
|
||||
github.com/go-ldap/ldap/v3 v3.4.6 // indirect
|
||||
github.com/glebarez/go-sqlite v1.22.0 // indirect
|
||||
github.com/glebarez/sqlite v1.11.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||
github.com/go-jose/go-jose/v3 v3.0.4 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.2 // indirect
|
||||
github.com/go-ldap/ldap/v3 v3.4.12 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-migrate/migrate/v4 v4.16.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/golang-migrate/migrate/v4 v4.19.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
|
||||
github.com/hashicorp/cli v1.1.6 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
|
||||
github.com/hashicorp/cli v1.1.7 // indirect
|
||||
github.com/hashicorp/dbassert v0.0.0-20231012105025-1bc1bd88e22b // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/eventlogger v0.2.6-0.20231025104552-802587e608f0 // indirect
|
||||
github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20231025104552-802587e608f0 // indirect
|
||||
github.com/hashicorp/go-bexpr v0.1.13 // indirect
|
||||
github.com/hashicorp/eventlogger v0.2.11 // indirect
|
||||
github.com/hashicorp/eventlogger/filters/encrypt v0.1.8-0.20231208142215-efdb51ec090d // indirect
|
||||
github.com/hashicorp/go-bexpr v0.1.15 // indirect
|
||||
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-dbw v0.1.1 // indirect
|
||||
github.com/hashicorp/go-hclog v1.5.0 // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20231124110655-4315424d22d0 // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.5 // indirect
|
||||
github.com/hashicorp/go-dbw v0.1.5-0.20240909162114-6cee92b3da36 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20241126174344-f3b1a41a15fd // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.8 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.6.0 // indirect
|
||||
github.com/hashicorp/go-plugin v1.7.0 // indirect
|
||||
github.com/hashicorp/go-rate v0.0.0-20231204194614-cc8d401f70ab // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/gatedwriter v0.1.1 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/kv-builder v0.1.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/listenerutil v0.1.9 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/listenerutil v0.1.10 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/mlock v0.1.3 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/permitpool v1.0.0 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/reloadutil v0.1.1 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.3 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.5 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.6.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.19.1 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/hc-install v0.9.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.1-vault-7 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.24.0 // indirect
|
||||
github.com/hashicorp/logutils v1.0.0 // indirect
|
||||
github.com/hashicorp/nodeenrollment v0.2.9 // indirect
|
||||
github.com/hashicorp/terraform-exec v0.20.0 // indirect
|
||||
github.com/hashicorp/terraform-json v0.21.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-go v0.21.0 // indirect
|
||||
github.com/hashicorp/nodeenrollment v0.2.14 // indirect
|
||||
github.com/hashicorp/terraform-exec v0.24.0 // indirect
|
||||
github.com/hashicorp/terraform-json v0.27.2 // indirect
|
||||
github.com/hashicorp/terraform-plugin-go v0.29.0 // indirect
|
||||
github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect
|
||||
github.com/hashicorp/terraform-registry-address v0.2.3 // indirect
|
||||
github.com/hashicorp/terraform-registry-address v0.4.0 // indirect
|
||||
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
|
||||
github.com/hashicorp/vault/api v1.10.0 // indirect
|
||||
github.com/hashicorp/vault/sdk v0.3.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/hashicorp/vault/api v1.22.0 // indirect
|
||||
github.com/hashicorp/vault/sdk v0.11.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.15 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.14.1 // indirect
|
||||
github.com/jackc/pgconn v1.14.3 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgtype v1.14.0 // indirect
|
||||
github.com/jackc/pgx/v4 v4.18.1 // indirect
|
||||
github.com/jackc/pgx/v5 v5.4.3 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.3.3 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.7.6 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jefferai/go-libsecret v0.0.0-20210525195240-b53481abef97 // indirect
|
||||
github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f // indirect
|
||||
github.com/jefferai/keyring v1.1.7-0.20220316160357-58a74bb55891 // indirect
|
||||
@@ -134,11 +137,10 @@ require (
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a // indirect
|
||||
github.com/mitchellh/cli v1.1.5 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
@@ -147,65 +149,70 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/pointerstructure v1.2.1 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/sys/user v0.4.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/opencontainers/runc v1.1.12 // indirect
|
||||
github.com/ory/dockertest/v3 v3.10.0 // indirect
|
||||
github.com/pires/go-proxyproto v0.7.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/opencontainers/runc v1.2.8 // indirect
|
||||
github.com/ory/dockertest/v3 v3.12.0 // indirect
|
||||
github.com/pires/go-proxyproto v0.8.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/posener/complete v1.2.3 // indirect
|
||||
github.com/prometheus/client_golang v1.17.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.11.1 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.66.1 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/russross/blackfriday v1.6.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
github.com/sethvargo/go-diceware v0.3.0 // indirect
|
||||
github.com/sethvargo/go-diceware v0.5.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
github.com/xo/dburl v0.16.0 // indirect
|
||||
github.com/yuin/goldmark v1.6.0 // indirect
|
||||
github.com/xo/dburl v0.23.1 // indirect
|
||||
github.com/yuin/goldmark v1.7.7 // indirect
|
||||
github.com/yuin/goldmark-meta v1.1.0 // indirect
|
||||
github.com/zalando/go-keyring v0.2.3 // indirect
|
||||
github.com/zclconf/go-cty v1.14.2 // indirect
|
||||
github.com/zalando/go-keyring v0.2.6 // indirect
|
||||
github.com/zclconf/go-cty v1.17.0 // indirect
|
||||
go.abhg.dev/goldmark/frontmatter v0.2.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/oauth2 v0.14.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/term v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
|
||||
golang.org/x/mod v0.30.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.38.0 // indirect
|
||||
golang.org/x/term v0.37.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
golang.org/x/tools v0.39.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect
|
||||
google.golang.org/grpc v1.61.0 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250929231259-57b25ae835d4 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect
|
||||
google.golang.org/grpc v1.76.0 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/postgres v1.5.4 // indirect
|
||||
gorm.io/driver/sqlite v1.5.4 // indirect
|
||||
gorm.io/gorm v1.25.5 // indirect
|
||||
modernc.org/libc v1.22.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.5.0 // indirect
|
||||
modernc.org/sqlite v1.23.1 // indirect
|
||||
gorm.io/driver/postgres v1.6.0 // indirect
|
||||
gorm.io/driver/sqlite v1.5.6 // indirect
|
||||
gorm.io/gorm v1.25.11 // indirect
|
||||
modernc.org/libc v1.41.0 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.7.2 // indirect
|
||||
modernc.org/sqlite v1.28.0 // indirect
|
||||
)
|
||||
@@ -56,4 +56,8 @@ const (
|
||||
ParentScopeIdKey = "parent_scope_id"
|
||||
// GroupMemberIdsKey is used for common "member_ids" resource attribute
|
||||
GroupMemberIdsKey = "member_ids"
|
||||
// ValueKey is used for common "value" resource attribute
|
||||
ValueKey = "value"
|
||||
// DestinationIdKey is used for common "destination_id" resource attribute
|
||||
DestinationIdKey = "destination_id"
|
||||
)
|
||||
@@ -0,0 +1,162 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/roles"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
)
|
||||
|
||||
func dataSourceRole() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Description: "The boundary_role data source allows you to find a Boundary role.",
|
||||
ReadContext: dataSourceRoleRead,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
NameKey: {
|
||||
Description: "The name of the role to retrieve.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: validation.StringIsNotEmpty,
|
||||
},
|
||||
ScopeIdKey: {
|
||||
Description: "The scope ID in which the resource is created. Defaults `global` if unset.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Default: "global",
|
||||
ValidateFunc: validation.StringIsNotEmpty,
|
||||
},
|
||||
IDKey: {
|
||||
Description: "The ID of the retrieved role.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
DescriptionKey: {
|
||||
Description: "The description of the retrieved role.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
ScopeKey: {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
IDKey: {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
NameKey: {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
TypeKey: {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
DescriptionKey: {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
ParentScopeIdKey: {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
rolePrincipalIdsKey: {
|
||||
Description: "The list of principal (user or group) IDs added as principals on the role.",
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Computed: true,
|
||||
},
|
||||
roleGrantStringsKey: {
|
||||
Description: "The list of stringified grants for the role.",
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Computed: true,
|
||||
},
|
||||
roleGrantScopeIdsKey: {
|
||||
Description: "The list of scope IDs for the role's grants.",
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func dataSourceRoleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
|
||||
name := d.Get(NameKey).(string)
|
||||
scopeId := d.Get(ScopeIdKey).(string)
|
||||
|
||||
rcl := roles.NewClient(md.client)
|
||||
rolesList, err := rcl.List(ctx, scopeId,
|
||||
roles.WithFilter(FilterWithItemNameMatches(name)),
|
||||
)
|
||||
if err != nil {
|
||||
return diag.Errorf("error calling list role: %v", err)
|
||||
}
|
||||
roles := rolesList.GetItems()
|
||||
if roles == nil {
|
||||
return diag.Errorf("no roles found")
|
||||
}
|
||||
if len(roles) == 0 {
|
||||
return diag.Errorf("no matching role found")
|
||||
}
|
||||
if len(roles) > 1 {
|
||||
return diag.Errorf("error found more than 1 role")
|
||||
}
|
||||
|
||||
rrr, err := rcl.Read(ctx, roles[0].Id)
|
||||
if err != nil {
|
||||
if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return diag.Errorf("error calling read role: %v", err)
|
||||
}
|
||||
if rrr == nil {
|
||||
return diag.Errorf("role nil after read")
|
||||
}
|
||||
|
||||
if err := setFromRoleRead(d, *rrr.Item); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setFromRoleRead(d *schema.ResourceData, role roles.Role) error {
|
||||
if err := d.Set(NameKey, role.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(DescriptionKey, role.Description); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(ScopeIdKey, role.ScopeId); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(roleGrantStringsKey, role.GrantStrings); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(roleGrantScopeIdsKey, role.GrantScopeIds); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(rolePrincipalIdsKey, role.PrincipalIds); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.Set(ScopeKey, flattenScopeInfo(role.Scope))
|
||||
d.SetId(role.Id)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/testing/controller"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
testRoleName = "my_role"
|
||||
)
|
||||
|
||||
var roleReadGlobal = fmt.Sprintf(`
|
||||
resource "boundary_user" "user" {
|
||||
name = "my_user"
|
||||
scope_id = "global"
|
||||
}
|
||||
|
||||
resource "boundary_role" "role" {
|
||||
name = "%s"
|
||||
description = "test role global"
|
||||
scope_id = "global"
|
||||
grant_strings = [
|
||||
"ids=*;type=*;actions=read"
|
||||
]
|
||||
principal_ids = [ boundary_user.user.id ]
|
||||
}
|
||||
|
||||
data "boundary_role" "role" {
|
||||
depends_on = [ boundary_role.role ]
|
||||
name = "%s"
|
||||
}
|
||||
`, testRoleName, testRoleName)
|
||||
|
||||
var roleReadOrg = fmt.Sprintf(`
|
||||
resource "boundary_user" "user" {
|
||||
name = "my_user"
|
||||
scope_id = "global"
|
||||
}
|
||||
|
||||
resource "boundary_role" "role" {
|
||||
name = "%s"
|
||||
description = "test role org"
|
||||
scope_id = boundary_scope.org1.id
|
||||
grant_strings = [
|
||||
"ids=*;type=*;actions=read"
|
||||
]
|
||||
principal_ids = [ boundary_user.user.id ]
|
||||
}
|
||||
|
||||
data "boundary_role" "role" {
|
||||
depends_on = [ boundary_role.role ]
|
||||
name = "%s"
|
||||
scope_id = boundary_scope.org1.id
|
||||
}
|
||||
`, testRoleName, testRoleName)
|
||||
|
||||
func TestAccRoleReadGlobal(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
dataSourceName := "data.boundary_role.role"
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testConfig(url, roleReadGlobal),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttrSet(dataSourceName, IDKey),
|
||||
resource.TestCheckResourceAttrSet(dataSourceName, ScopeIdKey),
|
||||
resource.TestCheckResourceAttr(dataSourceName, NameKey, testRoleName),
|
||||
resource.TestCheckResourceAttrSet(dataSourceName, DescriptionKey),
|
||||
resource.TestCheckResourceAttr(dataSourceName, fmt.Sprintf("%s.#", roleGrantStringsKey), "1"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, fmt.Sprintf("%s.0", roleGrantStringsKey), "ids=*;type=*;actions=read"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, fmt.Sprintf("%s.#", roleGrantScopeIdsKey), "1"),
|
||||
resource.TestCheckResourceAttrSet(dataSourceName, "scope.0.id"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, "scope.0.name", "global"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, "scope.0.type", "global"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, fmt.Sprintf("%s.#", rolePrincipalIdsKey), "1"),
|
||||
resource.TestCheckResourceAttrPair(dataSourceName, fmt.Sprintf("%s.0", rolePrincipalIdsKey), "boundary_user.user", "id"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccRoleReadOrg(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
dataSourceName := "data.boundary_role.role"
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testConfig(url, fooOrg, roleReadOrg),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttrSet(dataSourceName, IDKey),
|
||||
resource.TestCheckResourceAttrSet(dataSourceName, ScopeIdKey),
|
||||
resource.TestCheckResourceAttr(dataSourceName, NameKey, testRoleName),
|
||||
resource.TestCheckResourceAttrSet(dataSourceName, DescriptionKey),
|
||||
resource.TestCheckResourceAttr(dataSourceName, fmt.Sprintf("%s.#", roleGrantStringsKey), "1"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, fmt.Sprintf("%s.0", roleGrantStringsKey), "ids=*;type=*;actions=read"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, fmt.Sprintf("%s.#", roleGrantScopeIdsKey), "1"),
|
||||
resource.TestCheckResourceAttrSet(dataSourceName, "scope.0.id"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, "scope.0.name", "org1"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, "scope.0.type", "org"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, fmt.Sprintf("%s.#", rolePrincipalIdsKey), "1"),
|
||||
resource.TestCheckResourceAttrPair(dataSourceName, fmt.Sprintf("%s.0", rolePrincipalIdsKey), "boundary_user.user", "id"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func TestAccUserDataSource_globalAdminUser(t *testing.T) {
|
||||
resource.TestCheckResourceAttr(dataSourceName, LoginNameKey, "testuser"),
|
||||
resource.TestMatchResourceAttr(dataSourceName, IDKey, regexache.MustCompile(`^u_.+`)),
|
||||
resource.TestMatchResourceAttr(dataSourceName, PrimaryAccountIdKey, regexache.MustCompile(`^acctpw_.+`)),
|
||||
resource.TestCheckResourceAttr(dataSourceName, "authorized_actions.#", "7"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, "authorized_actions.#", "8"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, "scope.0.name", "global"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, "scope.0.id", "global"),
|
||||
resource.TestCheckResourceAttr(dataSourceName, "scope.0.type", "global"),
|
||||
|
||||
@@ -98,15 +98,19 @@ func New() *schema.Provider {
|
||||
"boundary_account_password": resourceAccountPassword(),
|
||||
"boundary_account_oidc": resourceAccountOidc(),
|
||||
"boundary_account_ldap": resourceAccountLdap(),
|
||||
"boundary_alias_target": resourceAliasTarget(),
|
||||
"boundary_auth_method": resourceAuthMethod(),
|
||||
"boundary_auth_method_password": resourceAuthMethodPassword(),
|
||||
"boundary_auth_method_oidc": resourceAuthMethodOidc(),
|
||||
"boundary_auth_method_ldap": resourceAuthMethodLdap(),
|
||||
"boundary_credential_library_vault": resourceCredentialLibraryVault(),
|
||||
"boundary_credential_library_vault_ssh_certificate": resourceCredentialLibraryVaultSshCertificate(),
|
||||
"boundary_credential_library_vault_ldap": resourceCredentialLibraryVaultLdap(),
|
||||
"boundary_credential_store_vault": resourceCredentialStoreVault(),
|
||||
"boundary_credential_store_static": resourceCredentialStoreStatic(),
|
||||
"boundary_credential_username_password": resourceCredentialUsernamePassword(),
|
||||
"boundary_credential_username_password_domain": resourceCredentialUsernamePasswordDomain(),
|
||||
"boundary_credential_password": resourceCredentialPassword(),
|
||||
"boundary_credential_ssh_private_key": resourceCredentialSshPrivateKey(),
|
||||
"boundary_credential_json": resourceCredentialJson(),
|
||||
"boundary_managed_group": resourceManagedGroup(),
|
||||
@@ -135,6 +139,7 @@ func New() *schema.Provider {
|
||||
"boundary_group": dataSourceGroup(),
|
||||
"boundary_scope": dataSourceScope(),
|
||||
"boundary_user": dataSourceUser(),
|
||||
"boundary_role": dataSourceRole(),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,19 @@ provider "boundary" {
|
||||
|
||||
func testConfigWithDefaultAuthMethod(url string, res ...string) string {
|
||||
provider := fmt.Sprintf(`
|
||||
provider "boundary" {
|
||||
addr = "%s"
|
||||
auth_method_login_name = "%s"
|
||||
auth_method_password = "%s"
|
||||
}`, url, tcLoginName, tcPassword)
|
||||
|
||||
c := []string{provider}
|
||||
c = append(c, res...)
|
||||
return strings.Join(c, "\n")
|
||||
}
|
||||
|
||||
func testConfigWithDeprecatedAuthMethod(url string, res ...string) string {
|
||||
provider := fmt.Sprintf(`
|
||||
provider "boundary" {
|
||||
addr = "%s"
|
||||
password_auth_method_login_name = "%s"
|
||||
@@ -256,6 +269,28 @@ func TestConfigWithDefaultAuthMethod(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigWithDeprecatedAuthMethod(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
IsUnitTest: true,
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckScopeResourceDestroy(t, provider),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testConfigWithDeprecatedAuthMethod(url, fooOrg, firstProjectFoo, secondProject),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.org1"),
|
||||
testProviderTokenExists(provider),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigWithoutAMPWCredentials(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
|
||||
@@ -92,7 +92,7 @@ resource "boundary_user" "alice" {
|
||||
|
||||
resource "boundary_role" "ldap_principal" {
|
||||
scope_id = boundary_scope.global.id
|
||||
grant_scope_ids = [boundary_scope.global.id]
|
||||
grant_scope_ids = ["this"]
|
||||
grant_strings = ["ids=*;type=*;actions=*"]
|
||||
principal_ids = [boundary_user.alice.id]
|
||||
}`
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/aliases"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
aliasTypeTarget = "target"
|
||||
|
||||
aliasTargetAuthorizeSessionHostIdKey = "authorize_session_host_id"
|
||||
)
|
||||
|
||||
func resourceAliasTarget() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Description: "The target alias resource allows you to configure a Boundary target alias.",
|
||||
|
||||
CreateContext: resourceTargetAliasCreate,
|
||||
ReadContext: resourceTargetAliasRead,
|
||||
UpdateContext: resourceTargetAliasUpdate,
|
||||
DeleteContext: resourceTargetAliasDelete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
StateContext: schema.ImportStatePassthroughContext,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
IDKey: {
|
||||
Description: "The ID of the account.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
NameKey: {
|
||||
Description: "The alias name. Defaults to the resource name.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
DescriptionKey: {
|
||||
Description: "The alias description.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
ScopeIdKey: {
|
||||
Description: "The scope ID.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
ValueKey: {
|
||||
Description: "The value of the alias.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
DestinationIdKey: {
|
||||
Description: "The destination of the alias.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
// Target specific configurable parameters
|
||||
aliasTargetAuthorizeSessionHostIdKey: {
|
||||
Description: "The host id to pass to Boundary when performing an authorize session action.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
TypeKey: {
|
||||
Description: "The type of alias; hardcoded.",
|
||||
Type: schema.TypeString,
|
||||
Default: aliasTypeTarget,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func setFromTargetAliasResponseMap(d *schema.ResourceData, raw map[string]interface{}) error {
|
||||
if err := d.Set(NameKey, raw["name"]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(DescriptionKey, raw["description"]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(ScopeIdKey, raw["scope_id"]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(ValueKey, raw["value"]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(DestinationIdKey, raw["destination_id"]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(TypeKey, raw["type"]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if attrsVal, ok := raw["attributes"]; ok {
|
||||
attrs := attrsVal.(map[string]interface{})
|
||||
tarAttrs, err := aliases.AttributesMapToTargetAliasAttributes(attrs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tarAttrs.AuthorizeSessionArguments != nil && tarAttrs.AuthorizeSessionArguments.HostId != "" {
|
||||
if err := d.Set(aliasTargetAuthorizeSessionHostIdKey, tarAttrs.AuthorizeSessionArguments.HostId); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.SetId(raw["id"].(string))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceTargetAliasCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
|
||||
var scopeId string
|
||||
if scopeIdVal, ok := d.GetOk(ScopeIdKey); ok {
|
||||
scopeId = scopeIdVal.(string)
|
||||
} else {
|
||||
return diag.Errorf("no scope ID provided")
|
||||
}
|
||||
|
||||
var typeStr string
|
||||
if typeVal, ok := d.GetOk(TypeKey); ok {
|
||||
typeStr = typeVal.(string)
|
||||
} else {
|
||||
return diag.Errorf("no type provided")
|
||||
}
|
||||
|
||||
opts := []aliases.Option{}
|
||||
|
||||
if typeVal, ok := d.GetOk(ValueKey); ok {
|
||||
opts = append(opts, aliases.WithValue(typeVal.(string)))
|
||||
} else {
|
||||
return diag.Errorf("no alias value provided")
|
||||
}
|
||||
|
||||
if nameVal, ok := d.GetOk(NameKey); ok {
|
||||
opts = append(opts, aliases.WithName(nameVal.(string)))
|
||||
}
|
||||
|
||||
if descVal, ok := d.GetOk(DescriptionKey); ok {
|
||||
opts = append(opts, aliases.WithDescription(descVal.(string)))
|
||||
}
|
||||
|
||||
if destVal, ok := d.GetOk(DestinationIdKey); ok {
|
||||
opts = append(opts, aliases.WithDestinationId(destVal.(string)))
|
||||
}
|
||||
|
||||
if hostIdVal, ok := d.GetOk(aliasTargetAuthorizeSessionHostIdKey); ok {
|
||||
opts = append(opts, aliases.WithTargetAliasAuthorizeSessionArgumentsHostId(hostIdVal.(string)))
|
||||
}
|
||||
|
||||
aliasClient := aliases.NewClient(md.client)
|
||||
|
||||
alcr, err := aliasClient.Create(ctx, typeStr, scopeId, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error creating alias: %v", err)
|
||||
}
|
||||
if alcr == nil {
|
||||
return diag.Errorf("nil alias after create")
|
||||
}
|
||||
|
||||
if err := setFromTargetAliasResponseMap(d, alcr.GetResponse().Map); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceTargetAliasRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
alClient := aliases.NewClient(md.client)
|
||||
|
||||
alrr, err := alClient.Read(ctx, d.Id())
|
||||
if err != nil {
|
||||
if apiErr := api.AsServerError(err); apiErr.Response().StatusCode() == http.StatusNotFound {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return diag.Errorf("error reading auth method: %v", err)
|
||||
}
|
||||
if alrr == nil {
|
||||
return diag.Errorf("auth method nil after read")
|
||||
}
|
||||
|
||||
if err := setFromTargetAliasResponseMap(d, alrr.GetResponse().Map); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceTargetAliasUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
alClient := aliases.NewClient(md.client)
|
||||
|
||||
opts := []aliases.Option{}
|
||||
|
||||
if d.HasChange(NameKey) {
|
||||
opts = append(opts, aliases.DefaultName())
|
||||
if nameVal, ok := d.GetOk(NameKey); ok {
|
||||
opts = append(opts, aliases.WithName(nameVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(DescriptionKey) {
|
||||
opts = append(opts, aliases.DefaultDescription())
|
||||
if descVal, ok := d.GetOk(DescriptionKey); ok {
|
||||
opts = append(opts, aliases.WithDescription(descVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(ValueKey) {
|
||||
if valVal, ok := d.GetOk(ValueKey); ok {
|
||||
opts = append(opts, aliases.WithValue(valVal.(string)))
|
||||
} else {
|
||||
return diag.Errorf("no value provided")
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(DestinationIdKey) {
|
||||
opts = append(opts, aliases.DefaultDestinationId())
|
||||
if destId, ok := d.GetOk(DestinationIdKey); ok {
|
||||
opts = append(opts, aliases.WithDestinationId(destId.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(aliasTargetAuthorizeSessionHostIdKey) {
|
||||
opts = append(opts, aliases.DefaultTargetAliasAuthorizeSessionArgumentsHostId())
|
||||
if authSessHostId, ok := d.GetOk(aliasTargetAuthorizeSessionHostIdKey); ok {
|
||||
opts = append(opts, aliases.WithTargetAliasAuthorizeSessionArgumentsHostId(authSessHostId.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts) > 0 {
|
||||
opts = append(opts, aliases.WithAutomaticVersioning(true))
|
||||
alur, err := alClient.Update(ctx, d.Id(), 0, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error updating auth method: %v", err)
|
||||
}
|
||||
|
||||
if err := setFromTargetAliasResponseMap(d, alur.GetResponse().Map); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceTargetAliasDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := aliases.NewClient(md.client)
|
||||
|
||||
_, err := client.Delete(ctx, d.Id())
|
||||
if err != nil {
|
||||
return diag.Errorf("error deleting alias: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/aliases"
|
||||
"github.com/hashicorp/boundary/testing/controller"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
||||
)
|
||||
|
||||
type aliasDestroyType string
|
||||
|
||||
const (
|
||||
targetAliasType aliasDestroyType = "boundary_alias_target"
|
||||
|
||||
targetAliasResc = "boundary_alias_target.example"
|
||||
targetAliasName = "foo"
|
||||
targetAliasDesc = "the foo"
|
||||
targetAliasValue = "value.example"
|
||||
targetAliasValueUpdated = "value.example.updated"
|
||||
targetAliasNamespace = "target"
|
||||
targetAliasUpdate = "_random"
|
||||
)
|
||||
|
||||
var fooBarTarget = `
|
||||
resource "boundary_target" "foo" {
|
||||
type = "tcp"
|
||||
name = "test"
|
||||
description = "test target"
|
||||
default_port = 22
|
||||
address = "127.0.0.1"
|
||||
scope_id = boundary_scope.proj1.id
|
||||
depends_on = [boundary_role.proj1_admin]
|
||||
}`
|
||||
|
||||
var aliasId string
|
||||
|
||||
func targetAliasResource(name string, description string, value string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "boundary_alias_target" "example" {
|
||||
name = "%s"
|
||||
description = "%s"
|
||||
value = "%s"
|
||||
scope_id = "global"
|
||||
destination_id = boundary_target.foo.id
|
||||
authorize_session_host_id = "hst_1234567890"
|
||||
depends_on = [boundary_target.foo]
|
||||
}`, name, description, value)
|
||||
}
|
||||
|
||||
func TestAccAliasTarget(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
res := targetAliasResource(targetAliasName, targetAliasDesc, targetAliasValue)
|
||||
|
||||
resUpdate := targetAliasResource(targetAliasName+targetAliasUpdate,
|
||||
targetAliasDesc+targetAliasUpdate, targetAliasValueUpdated)
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckAliasResourceDestroy(t, provider, targetAliasType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, fooBarTarget, res),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(targetAliasResc, NameKey, targetAliasName),
|
||||
resource.TestCheckResourceAttr(targetAliasResc, DescriptionKey, targetAliasDesc),
|
||||
resource.TestCheckResourceAttr(targetAliasResc, ValueKey, targetAliasValue),
|
||||
|
||||
testAccCheckAliasResourceExists(provider, targetAliasResc),
|
||||
),
|
||||
},
|
||||
importStep(targetAliasResc),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, fooBarTarget, resUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(targetAliasResc, NameKey, targetAliasName+targetAliasUpdate),
|
||||
resource.TestCheckResourceAttr(targetAliasResc, DescriptionKey, targetAliasDesc+targetAliasUpdate),
|
||||
resource.TestCheckResourceAttr(targetAliasResc, ValueKey, targetAliasValueUpdated),
|
||||
|
||||
testAccCheckAliasResourceExists(provider, targetAliasResc),
|
||||
),
|
||||
},
|
||||
importStep(targetAliasResc),
|
||||
{
|
||||
// Run a plan only update and verify no changes
|
||||
PlanOnly: true,
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, fooBarTarget, resUpdate),
|
||||
},
|
||||
importStep(targetAliasResc),
|
||||
{
|
||||
// update again but apply a preConfig to externally update resource
|
||||
// TODO: Boundary currently causes an error on moving back to a previously
|
||||
// used token, for now verify that a plan only step had changes
|
||||
PreConfig: func() { targetAliasExternalUpdate(t, provider) },
|
||||
PlanOnly: true,
|
||||
ExpectNonEmptyPlan: true,
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, fooBarTarget, resUpdate),
|
||||
},
|
||||
importStep(targetAliasResc),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func targetAliasExternalUpdate(t *testing.T, testProvider *schema.Provider) {
|
||||
if aliasId == "" {
|
||||
t.Fatal("aliasId must be set before testing an external update")
|
||||
}
|
||||
|
||||
md := testProvider.Meta().(*metaData)
|
||||
ac := aliases.NewClient(md.client)
|
||||
ar, err := ac.Read(context.Background(), aliasId)
|
||||
if err != nil {
|
||||
t.Fatal(fmt.Errorf("got an error reading %q: %w", storeId, err))
|
||||
}
|
||||
|
||||
// update alias options
|
||||
var opts []aliases.Option
|
||||
opts = append(opts, aliases.WithDescription("this is an updated description, my guy"))
|
||||
|
||||
_, err = ac.Update(context.Background(), ar.Item.Id, ar.Item.Version, opts...)
|
||||
if err != nil {
|
||||
t.Fatal(fmt.Errorf("got an error updating %q: %w", ar.Item.Id, err))
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAliasResourceExists(testProvider *schema.Provider, name string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("not found: %s", name)
|
||||
}
|
||||
|
||||
id := rs.Primary.ID
|
||||
if id == "" {
|
||||
return fmt.Errorf("no ID is set")
|
||||
}
|
||||
aliasId = id
|
||||
|
||||
md := testProvider.Meta().(*metaData)
|
||||
c := aliases.NewClient(md.client)
|
||||
if _, err := c.Read(context.Background(), id); err != nil {
|
||||
return fmt.Errorf("got an error reading %q: %w", id, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckAliasResourceDestroy(t *testing.T, testProvider *schema.Provider, typ aliasDestroyType) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
if testProvider.Meta() == nil {
|
||||
t.Fatal("got nil provider metadata")
|
||||
}
|
||||
md := testProvider.Meta().(*metaData)
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
switch rs.Type {
|
||||
case string(typ):
|
||||
id := rs.Primary.ID
|
||||
|
||||
c := aliases.NewClient(md.client)
|
||||
_, err := c.Read(context.Background(), id)
|
||||
if apiErr := api.AsServerError(err); apiErr == nil || apiErr.Response().StatusCode() != http.StatusNotFound {
|
||||
return fmt.Errorf("didn't get a 404 when reading destroyed target alias %q: %v", id, err)
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,11 @@ func resourceAuthMethod() *schema.Resource {
|
||||
Computed: true,
|
||||
Deprecated: "Will be removed in favor of using attributes parameter",
|
||||
},
|
||||
authmethodIsPrimaryForScopeKey: {
|
||||
Description: "When true, makes this auth method the primary auth method for the scope in which it resides.",
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -91,6 +96,10 @@ func setFromAuthMethodResponseMap(d *schema.ResourceData, raw map[string]interfa
|
||||
return err
|
||||
}
|
||||
|
||||
if p, ok := raw[authmethodIsPrimaryForScopeKey]; ok {
|
||||
d.Set(authmethodIsPrimaryForScopeKey, p.(bool))
|
||||
}
|
||||
|
||||
switch raw["type"].(string) {
|
||||
case authmethodTypePassword:
|
||||
if attrsVal, ok := raw["attributes"]; ok {
|
||||
@@ -160,6 +169,19 @@ func resourceAuthMethodCreate(ctx context.Context, d *schema.ResourceData, meta
|
||||
return diag.Errorf("nil auth method after create")
|
||||
}
|
||||
|
||||
amid := amcr.GetResponse().Map["id"].(string)
|
||||
|
||||
// update scope when set to primary
|
||||
if p, ok := d.GetOk(authmethodIsPrimaryForScopeKey); ok {
|
||||
if p.(bool) {
|
||||
if err := updateScopeWithPrimaryAuthMethodId(ctx, scopeId, amid, meta); err != nil {
|
||||
return diag.Errorf("%v", err)
|
||||
}
|
||||
|
||||
amcr.GetResponse().Map[authmethodIsPrimaryForScopeKey] = true
|
||||
}
|
||||
}
|
||||
|
||||
if err := setFromAuthMethodResponseMap(d, amcr.GetResponse().Map); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
@@ -183,6 +205,15 @@ func resourceAuthMethodRead(ctx context.Context, d *schema.ResourceData, meta in
|
||||
return diag.Errorf("auth method nil after read")
|
||||
}
|
||||
|
||||
serr, isPrimary := readScopeIsPrimaryAuthMethodId(ctx, amrr.GetResponse().Map["scope_id"].(string), amrr.GetResponse().Map["id"].(string), meta)
|
||||
if serr != nil {
|
||||
return diag.Errorf("%v", serr)
|
||||
}
|
||||
|
||||
if isPrimary {
|
||||
amrr.GetResponse().Map[authmethodIsPrimaryForScopeKey] = true
|
||||
}
|
||||
|
||||
if err := setFromAuthMethodResponseMap(d, amrr.GetResponse().Map); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
@@ -225,13 +256,44 @@ func resourceAuthMethodUpdate(ctx context.Context, d *schema.ResourceData, meta
|
||||
}
|
||||
}
|
||||
|
||||
opts = append(opts, authmethods.WithAutomaticVersioning(true))
|
||||
amu, err := amClient.Update(ctx, d.Id(), 0, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error updating auth method: %v", err)
|
||||
if d.HasChange(authmethodIsPrimaryForScopeKey) {
|
||||
amrr, err := amClient.Read(ctx, d.Id())
|
||||
if err != nil {
|
||||
return diag.Errorf("error updating auth method: %v", err)
|
||||
}
|
||||
if amrr == nil {
|
||||
return diag.Errorf("error updating auth method: nil resource")
|
||||
}
|
||||
scopeId := amrr.GetResponse().Map["scope_id"].(string)
|
||||
authMethodId := amrr.GetResponse().Map["id"].(string)
|
||||
|
||||
isPrimary := d.Get(authmethodIsPrimaryForScopeKey).(bool)
|
||||
|
||||
if isPrimary {
|
||||
if err := updateScopeWithPrimaryAuthMethodId(ctx, scopeId, authMethodId, meta); err != nil {
|
||||
return diag.Errorf("%v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setFromAuthMethodResponseMap(d, amu.GetResponse().Map)
|
||||
if len(opts) > 0 {
|
||||
opts = append(opts, authmethods.WithAutomaticVersioning(true))
|
||||
amu, err := amClient.Update(ctx, d.Id(), 0, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error updating auth method: %v", err)
|
||||
}
|
||||
|
||||
if d.HasChange(authmethodIsPrimaryForScopeKey) {
|
||||
amu.GetResponse().Map[authmethodIsPrimaryForScopeKey] = d.Get(authmethodIsPrimaryForScopeKey).(bool)
|
||||
}
|
||||
|
||||
setFromAuthMethodResponseMap(d, amu.GetResponse().Map)
|
||||
}
|
||||
|
||||
// If only is_primary_for_scope changed
|
||||
if d.HasChange(authmethodIsPrimaryForScopeKey) {
|
||||
return resourceAuthMethodPasswordRead(ctx, d, meta)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ const (
|
||||
authmethodTypePassword = "password"
|
||||
authmethodMinLoginNameLengthKey = "min_login_name_length"
|
||||
authmethodMinPasswordLengthKey = "min_password_length"
|
||||
authmethodIsPrimaryForScopeKey = "is_primary_for_scope"
|
||||
)
|
||||
|
||||
func resourceAuthMethodPassword() *schema.Resource {
|
||||
@@ -72,6 +73,11 @@ func resourceAuthMethodPassword() *schema.Resource {
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
authmethodIsPrimaryForScopeKey: {
|
||||
Description: "When true, makes this auth method the primary auth method for the scope in which it resides.",
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -82,6 +88,10 @@ func setFromPasswordAuthMethodResponseMap(d *schema.ResourceData, raw map[string
|
||||
d.Set(ScopeIdKey, raw[ScopeIdKey])
|
||||
d.Set(TypeKey, raw[TypeKey])
|
||||
|
||||
if p, ok := raw[authmethodIsPrimaryForScopeKey]; ok {
|
||||
d.Set(authmethodIsPrimaryForScopeKey, p.(bool))
|
||||
}
|
||||
|
||||
if attrsVal, ok := raw["attributes"]; ok {
|
||||
attrs := attrsVal.(map[string]interface{})
|
||||
|
||||
@@ -158,6 +168,19 @@ func resourceAuthMethodPasswordCreate(ctx context.Context, d *schema.ResourceDat
|
||||
return diag.Errorf("nil auth method after create")
|
||||
}
|
||||
|
||||
amid := amcr.GetResponse().Map["id"].(string)
|
||||
|
||||
// update scope when set to primary
|
||||
if p, ok := d.GetOk(authmethodIsPrimaryForScopeKey); ok {
|
||||
if p.(bool) {
|
||||
if err := updateScopeWithPrimaryAuthMethodId(ctx, scopeId, amid, meta); err != nil {
|
||||
return diag.Errorf("%v", err)
|
||||
}
|
||||
|
||||
amcr.GetResponse().Map[authmethodIsPrimaryForScopeKey] = true
|
||||
}
|
||||
}
|
||||
|
||||
return setFromPasswordAuthMethodResponseMap(d, amcr.GetResponse().Map)
|
||||
}
|
||||
|
||||
@@ -177,6 +200,15 @@ func resourceAuthMethodPasswordRead(ctx context.Context, d *schema.ResourceData,
|
||||
return diag.Errorf("auth method nil after read")
|
||||
}
|
||||
|
||||
serr, isPrimary := readScopeIsPrimaryAuthMethodId(ctx, amrr.GetResponse().Map["scope_id"].(string), amrr.GetResponse().Map["id"].(string), meta)
|
||||
if serr != nil {
|
||||
return diag.Errorf("%v", serr)
|
||||
}
|
||||
|
||||
if isPrimary {
|
||||
amrr.GetResponse().Map[authmethodIsPrimaryForScopeKey] = true
|
||||
}
|
||||
|
||||
return setFromPasswordAuthMethodResponseMap(d, amrr.GetResponse().Map)
|
||||
}
|
||||
|
||||
@@ -218,6 +250,24 @@ func resourceAuthMethodPasswordUpdate(ctx context.Context, d *schema.ResourceDat
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(authmethodIsPrimaryForScopeKey) {
|
||||
amrr, err := amClient.Read(ctx, d.Id())
|
||||
if err != nil {
|
||||
return diag.Errorf("error updating auth method: %v", err)
|
||||
}
|
||||
if amrr == nil {
|
||||
return diag.Errorf("error updating auth method: nil resource")
|
||||
}
|
||||
scopeId := amrr.GetResponse().Map["scope_id"].(string)
|
||||
authMethodId := amrr.GetResponse().Map["id"].(string)
|
||||
|
||||
if d.Get(authmethodIsPrimaryForScopeKey).(bool) {
|
||||
if err := updateScopeWithPrimaryAuthMethodId(ctx, scopeId, authMethodId, meta); err != nil {
|
||||
return diag.Errorf("%v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts) > 0 {
|
||||
opts = append(opts, authmethods.WithAutomaticVersioning(true))
|
||||
amur, err := amClient.Update(ctx, d.Id(), 0, opts...)
|
||||
@@ -225,8 +275,18 @@ func resourceAuthMethodPasswordUpdate(ctx context.Context, d *schema.ResourceDat
|
||||
return diag.Errorf("error updating auth method: %v", err)
|
||||
}
|
||||
|
||||
if d.HasChange(authmethodIsPrimaryForScopeKey) {
|
||||
amur.GetResponse().Map[authmethodIsPrimaryForScopeKey] = d.Get(authmethodIsPrimaryForScopeKey).(bool)
|
||||
}
|
||||
|
||||
return setFromPasswordAuthMethodResponseMap(d, amur.GetResponse().Map)
|
||||
}
|
||||
|
||||
// If only is_primary_for_scope changed
|
||||
if d.HasChange(authmethodIsPrimaryForScopeKey) {
|
||||
return resourceAuthMethodPasswordRead(ctx, d, meta)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,16 @@ resource "boundary_auth_method_password" "foo" {
|
||||
scope_id = boundary_scope.org1.id
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
}`, fooAuthMethodDescUpdate)
|
||||
|
||||
fooAuthMethodIsPrimaryUpdate = fmt.Sprintf(`
|
||||
resource "boundary_auth_method_password" "foo" {
|
||||
name = "test"
|
||||
description = "%s"
|
||||
type = "password"
|
||||
scope_id = boundary_scope.org1.id
|
||||
is_primary_for_scope = true
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
}`, fooAuthMethodDesc)
|
||||
)
|
||||
|
||||
func TestAccAuthMethodPassword(t *testing.T) {
|
||||
@@ -55,6 +65,7 @@ func TestAccAuthMethodPassword(t *testing.T) {
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "name", "test"),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "type", "password"),
|
||||
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method_password.foo"),
|
||||
testAccIsPrimaryForScope(provider, "boundary_auth_method_password.foo", false),
|
||||
),
|
||||
},
|
||||
importStep("boundary_auth_method_password.foo"),
|
||||
@@ -66,9 +77,47 @@ func TestAccAuthMethodPassword(t *testing.T) {
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "name", "test"),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "type", "password"),
|
||||
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method_password.foo"),
|
||||
testAccIsPrimaryForScope(provider, "boundary_auth_method_password.foo", false),
|
||||
),
|
||||
},
|
||||
importStep("boundary_auth_method_password.foo"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAuthMethodPasswordIsPrimary(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckAuthMethodResourceDestroy(t, provider, passwordAuthMethodType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, fooAuthMethod),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "description", fooAuthMethodDesc),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "name", "test"),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "type", "password"),
|
||||
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method_password.foo"),
|
||||
testAccIsPrimaryForScope(provider, "boundary_auth_method_password.foo", false),
|
||||
),
|
||||
},
|
||||
importStep("boundary_auth_method_password.foo"),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, fooAuthMethodIsPrimaryUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "description", fooAuthMethodDesc),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "name", "test"),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "type", "password"),
|
||||
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method_password.foo"),
|
||||
testAccIsPrimaryForScope(provider, "boundary_auth_method_password.foo", true),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -42,6 +42,16 @@ resource "boundary_auth_method" "foo" {
|
||||
scope_id = boundary_scope.org1.id
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
}`, fooBaseAuthMethodDescUpdate)
|
||||
|
||||
fooBaseAuthMethodIsPrimaryUpdate = fmt.Sprintf(`
|
||||
resource "boundary_auth_method" "foo" {
|
||||
name = "test"
|
||||
description = "%s"
|
||||
type = "password"
|
||||
scope_id = boundary_scope.org1.id
|
||||
is_primary_for_scope = true
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
}`, fooAuthMethodDesc)
|
||||
)
|
||||
|
||||
func TestAccBaseAuthMethodPassword(t *testing.T) {
|
||||
@@ -81,6 +91,43 @@ func TestAccBaseAuthMethodPassword(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccBaseAuthMethodPasswordIsPrimary(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckAuthMethodResourceDestroy(t, provider, passwordAuthMethodType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, fooBaseAuthMethod),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "description", fooBaseAuthMethodDesc),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "name", "test"),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "type", "password"),
|
||||
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method.foo"),
|
||||
testAccIsPrimaryForScope(provider, "boundary_auth_method.foo", false),
|
||||
),
|
||||
},
|
||||
importStep("boundary_auth_method.foo"),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, fooBaseAuthMethodIsPrimaryUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "description", fooBaseAuthMethodDesc),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "name", "test"),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "type", "password"),
|
||||
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method.foo"),
|
||||
testAccIsPrimaryForScope(provider, "boundary_auth_method.foo", true),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckAuthMethodResourceExists(testProvider *schema.Provider, name string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
|
||||
@@ -140,9 +140,11 @@ func testAccCheckCredentialResourceExists(testProvider *schema.Provider, name st
|
||||
type credentialType string
|
||||
|
||||
const (
|
||||
jsonCredentialType credentialType = "boundary_credential_json"
|
||||
sshPrivateKeyCredentialType credentialType = "boundary_credential_ssh_private_key"
|
||||
usernamePasswordCredentialType credentialType = "boundary_credential_username_password"
|
||||
jsonCredentialType credentialType = "boundary_credential_json"
|
||||
sshPrivateKeyCredentialType credentialType = "boundary_credential_ssh_private_key"
|
||||
usernamePasswordCredentialType credentialType = "boundary_credential_username_password"
|
||||
usernamePasswordDomainCredentialType credentialType = "boundary_credential_username_password_domain"
|
||||
passwordCredentialType credentialType = "boundary_credential_password"
|
||||
)
|
||||
|
||||
func testAccCheckCredentialResourceDestroy(t *testing.T, testProvider *schema.Provider, typ credentialType) resource.TestCheckFunc {
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentiallibraries"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
credentialLibraryVaultLdapType = "vault-ldap"
|
||||
credentialLibraryVaultLdapPathKey = "path"
|
||||
)
|
||||
|
||||
var libraryVaultLdapAttrs = []string{
|
||||
credentialLibraryVaultLdapPathKey,
|
||||
}
|
||||
|
||||
func resourceCredentialLibraryVaultLdap() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Description: "The credential library for Vault LDAP resource allows you to configure a Boundary credential library for Vault LDAP.",
|
||||
|
||||
CreateContext: resourceCredentialLibraryCreateVaultLdap,
|
||||
ReadContext: resourceCredentialLibraryReadVaultLdap,
|
||||
UpdateContext: resourceCredentialLibraryUpdateVaultLdap,
|
||||
DeleteContext: resourceCredentialLibraryDeleteVaultLdap,
|
||||
Importer: &schema.ResourceImporter{
|
||||
StateContext: schema.ImportStatePassthroughContext,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
IDKey: {
|
||||
Description: "The ID of the Vault LDAP credential library.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
NameKey: {
|
||||
Description: "The Vault LDAP credential library name. Defaults to the resource name.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
DescriptionKey: {
|
||||
Description: "The Vault LDAP credential library description.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
credentialStoreIdKey: {
|
||||
Description: "The ID of the credential store that this library belongs to.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
credentialLibraryVaultLdapPathKey: {
|
||||
Description: "The path in Vault to request credentials from.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func setFromVaultLdapCredentialLibraryResponseMap(d *schema.ResourceData, raw map[string]interface{}) error {
|
||||
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(credentialStoreIdKey, raw[credentialStoreIdKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if attrsVal, ok := raw["attributes"]; ok {
|
||||
attrs := attrsVal.(map[string]interface{})
|
||||
for _, v := range libraryVaultLdapAttrs {
|
||||
if err := d.Set(v, attrs[v]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.SetId(raw["id"].(string))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialLibraryCreateVaultLdap(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
|
||||
var opts []credentiallibraries.Option
|
||||
if v, ok := d.GetOk(NameKey); ok {
|
||||
opts = append(opts, credentiallibraries.WithName(v.(string)))
|
||||
}
|
||||
if v, ok := d.GetOk(DescriptionKey); ok {
|
||||
opts = append(opts, credentiallibraries.WithDescription(v.(string)))
|
||||
}
|
||||
if v, ok := d.GetOk(credentialLibraryVaultLdapPathKey); ok {
|
||||
opts = append(opts, credentiallibraries.WithVaultLdapCredentialLibraryPath(v.(string)))
|
||||
}
|
||||
|
||||
var credentialStoreId string
|
||||
cid, ok := d.GetOk(credentialStoreIdKey)
|
||||
if ok {
|
||||
credentialStoreId = cid.(string)
|
||||
} else {
|
||||
return diag.Errorf("no credential store ID is set")
|
||||
}
|
||||
|
||||
client := credentiallibraries.NewClient(md.client)
|
||||
cr, err := client.Create(ctx, credentialLibraryVaultLdapType, credentialStoreId, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error creating credential library: %v", err)
|
||||
}
|
||||
if cr == nil {
|
||||
return diag.Errorf("nil credential library after create")
|
||||
}
|
||||
|
||||
if err := setFromVaultLdapCredentialLibraryResponseMap(d, cr.GetResponse().Map); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialLibraryReadVaultLdap(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentiallibraries.NewClient(md.client)
|
||||
|
||||
cr, err := client.Read(ctx, d.Id())
|
||||
if err != nil {
|
||||
if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return diag.Errorf("error reading credential library: %v", err)
|
||||
}
|
||||
if cr == nil {
|
||||
return diag.Errorf("credential library nil after read")
|
||||
}
|
||||
|
||||
if err := setFromVaultLdapCredentialLibraryResponseMap(d, cr.GetResponse().Map); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialLibraryUpdateVaultLdap(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentiallibraries.NewClient(md.client)
|
||||
|
||||
var opts []credentiallibraries.Option
|
||||
if d.HasChange(NameKey) {
|
||||
opts = append(opts, credentiallibraries.DefaultName())
|
||||
nameVal, ok := d.GetOk(NameKey)
|
||||
if ok {
|
||||
opts = append(opts, credentiallibraries.WithName(nameVal.(string)))
|
||||
}
|
||||
}
|
||||
if d.HasChange(DescriptionKey) {
|
||||
opts = append(opts, credentiallibraries.DefaultDescription())
|
||||
descVal, ok := d.GetOk(DescriptionKey)
|
||||
if ok {
|
||||
opts = append(opts, credentiallibraries.WithDescription(descVal.(string)))
|
||||
}
|
||||
}
|
||||
if d.HasChange(credentialLibraryVaultLdapPathKey) {
|
||||
v, ok := d.GetOk(credentialLibraryVaultLdapPathKey)
|
||||
if ok {
|
||||
opts = append(opts, credentiallibraries.WithVaultLdapCredentialLibraryPath(v.(string)))
|
||||
}
|
||||
}
|
||||
if len(opts) > 0 {
|
||||
opts = append(opts, credentiallibraries.WithAutomaticVersioning(true))
|
||||
aur, err := client.Update(ctx, d.Id(), 0, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error updating credential library: %v", err)
|
||||
}
|
||||
|
||||
if err := setFromVaultLdapCredentialLibraryResponseMap(d, aur.GetResponse().Map); err != nil {
|
||||
return diag.Errorf("error setting credential library from response: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialLibraryDeleteVaultLdap(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentiallibraries.NewClient(md.client)
|
||||
|
||||
_, err := client.Delete(ctx, d.Id())
|
||||
if err != nil {
|
||||
return diag.Errorf("error deleting credential library: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/testing/controller"
|
||||
"github.com/hashicorp/boundary/testing/vault"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
vaultLdapCredResc = "boundary_credential_library_vault_ldap.example"
|
||||
vaultLdapCredLibName = "foo"
|
||||
vaultLdapCredLibDesc = "the foo"
|
||||
vaultLdapCredLibPath = "/ldap/static-cred/foo"
|
||||
vaultLdapCredLibStringUpdate = "_random"
|
||||
)
|
||||
|
||||
var vaultLdapCredLibResource = fmt.Sprintf(`
|
||||
resource "boundary_credential_library_vault_ldap" "example" {
|
||||
name = "%s"
|
||||
description = "%s"
|
||||
credential_store_id = boundary_credential_store_vault.example.id
|
||||
path = "%s"
|
||||
}`, vaultLdapCredLibName,
|
||||
vaultLdapCredLibDesc,
|
||||
vaultLdapCredLibPath)
|
||||
|
||||
var vaultLdapCredLibResourceUpdate = fmt.Sprintf(`
|
||||
resource "boundary_credential_library_vault_ldap" "example" {
|
||||
name = "%s"
|
||||
description = "%s"
|
||||
credential_store_id = boundary_credential_store_vault.example.id
|
||||
path = "%s"
|
||||
}`, vaultLdapCredLibName+vaultLdapCredLibStringUpdate,
|
||||
vaultLdapCredLibDesc+vaultLdapCredLibStringUpdate,
|
||||
vaultLdapCredLibPath+vaultLdapCredLibStringUpdate)
|
||||
|
||||
func TestAccCredentialLibraryVaultLdap(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
vc := vault.NewTestVaultServer(t)
|
||||
_, token := vc.CreateToken(t)
|
||||
credStoreRes := vaultCredStoreResource(vc,
|
||||
vaultCredStoreName,
|
||||
vaultCredStoreDesc,
|
||||
vaultCredStoreNamespace,
|
||||
"www.original.com",
|
||||
token,
|
||||
true)
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
IsUnitTest: true,
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckCredentialLibraryVaultResourceDestroy(t, provider, ldapVaultCredentialLibraryType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, credStoreRes, vaultLdapCredLibResource),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(vaultLdapCredResc, NameKey, vaultLdapCredLibName),
|
||||
resource.TestCheckResourceAttr(vaultLdapCredResc, DescriptionKey, vaultLdapCredLibDesc),
|
||||
resource.TestCheckResourceAttr(vaultLdapCredResc, credentialLibraryVaultLdapPathKey, vaultLdapCredLibPath),
|
||||
|
||||
testAccCheckCredentialLibraryResourceExists(provider, vaultLdapCredResc),
|
||||
),
|
||||
},
|
||||
importStep(vaultLdapCredResc),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, credStoreRes, vaultLdapCredLibResourceUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(vaultLdapCredResc, NameKey, vaultLdapCredLibName+vaultLdapCredLibStringUpdate),
|
||||
resource.TestCheckResourceAttr(vaultLdapCredResc, DescriptionKey, vaultLdapCredLibDesc+vaultLdapCredLibStringUpdate),
|
||||
resource.TestCheckResourceAttr(vaultLdapCredResc, credentialLibraryVaultLdapPathKey, vaultLdapCredLibPath+vaultLdapCredLibStringUpdate),
|
||||
testAccCheckCredentialLibraryResourceExists(provider, vaultLdapCredResc),
|
||||
),
|
||||
},
|
||||
importStep(vaultLdapCredResc),
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -302,6 +302,7 @@ type vaultCredentialLibraryType string
|
||||
const (
|
||||
baseVaultCredentialLibraryType vaultCredentialLibraryType = "boundary_credential_library_vault"
|
||||
sshCertVaultCredentialLibraryType vaultCredentialLibraryType = "boundary_credential_library_vault_ssh_certificate"
|
||||
ldapVaultCredentialLibraryType vaultCredentialLibraryType = "boundary_credential_library_vault_ldap"
|
||||
)
|
||||
|
||||
func testAccCheckCredentialLibraryVaultResourceDestroy(t *testing.T, testProvider *schema.Provider, typ vaultCredentialLibraryType) resource.TestCheckFunc {
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
credentialPasswordKey = "password"
|
||||
credentialPasswordHmacKey = "password_hmac"
|
||||
credentialPasswordCredentialType = "password"
|
||||
)
|
||||
|
||||
func resourceCredentialPassword() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Description: "The password credential resource allows you to configure a credential using a password.",
|
||||
|
||||
CreateContext: resourceCredentialPasswordCreate,
|
||||
ReadContext: resourceCredentialPasswordRead,
|
||||
UpdateContext: resourceCredentialPasswordUpdate,
|
||||
DeleteContext: resourceCredentialPasswordDelete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
StateContext: schema.ImportStatePassthroughContext,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
IDKey: {
|
||||
Description: "The ID of this password credential.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
NameKey: {
|
||||
Description: "The name of this password credential. Defaults to the resource name.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
DescriptionKey: {
|
||||
Description: "The description of this password credential.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
credentialStoreIdKey: {
|
||||
Description: "The credential store in which to save this password credential.",
|
||||
Type: schema.TypeString,
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
},
|
||||
credentialPasswordKey: {
|
||||
Description: "The password of this password credential.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
credentialPasswordHmacKey: {
|
||||
Description: "The password hmac.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func setFromCredentialPasswordResponseMap(d *schema.ResourceData, raw map[string]interface{}, fromRead bool) error {
|
||||
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(credentialStoreIdKey, raw[credentialStoreIdKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if attrsVal, ok := raw["attributes"]; ok {
|
||||
attrs := attrsVal.(map[string]interface{})
|
||||
|
||||
statePasswordHmac := d.Get(credentialPasswordHmacKey)
|
||||
boundaryPasswordHmac := attrs[credentialPasswordHmacKey].(string)
|
||||
if statePasswordHmac.(string) != boundaryPasswordHmac && fromRead {
|
||||
// PasswordHmac has changed in Boundary, therefore the password has changed.
|
||||
// Update password value to force tf to attempt update.
|
||||
if err := d.Set(credentialPasswordKey, "(changed in Boundary)"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := d.Set(credentialPasswordHmacKey, boundaryPasswordHmac); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.SetId(raw["id"].(string))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialPasswordCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
|
||||
var opts []credentials.Option
|
||||
if v, ok := d.GetOk(NameKey); ok {
|
||||
opts = append(opts, credentials.WithName(v.(string)))
|
||||
}
|
||||
if v, ok := d.GetOk(DescriptionKey); ok {
|
||||
opts = append(opts, credentials.WithDescription(v.(string)))
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk(credentialPasswordKey); ok {
|
||||
opts = append(opts, credentials.WithPasswordCredentialPassword(v.(string)))
|
||||
}
|
||||
|
||||
var credentialStoreId string
|
||||
retrievedStoreId, ok := d.GetOk(credentialStoreIdKey)
|
||||
if ok {
|
||||
credentialStoreId = retrievedStoreId.(string)
|
||||
} else {
|
||||
return diag.Errorf("credential store id is unset")
|
||||
}
|
||||
|
||||
client := credentials.NewClient(md.client)
|
||||
cr, err := client.Create(ctx, credentialPasswordCredentialType, credentialStoreId, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error creating credential: %v", err)
|
||||
}
|
||||
if cr == nil {
|
||||
return diag.Errorf("nil credential after create")
|
||||
}
|
||||
|
||||
if err := setFromCredentialPasswordResponseMap(d, cr.GetResponse().Map, false); err != nil {
|
||||
return diag.Errorf("error generating credential from response map: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialPasswordRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentials.NewClient(md.client)
|
||||
|
||||
cr, err := client.Read(ctx, d.Id())
|
||||
if err != nil {
|
||||
if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return diag.Errorf("error reading credential: %v", err)
|
||||
}
|
||||
if cr == nil {
|
||||
return diag.Errorf("credential nil after read")
|
||||
}
|
||||
|
||||
if err := setFromCredentialPasswordResponseMap(d, cr.GetResponse().Map, true); err != nil {
|
||||
return diag.Errorf("error generating credential from response map: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialPasswordUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentials.NewClient(md.client)
|
||||
|
||||
var opts []credentials.Option
|
||||
if d.HasChange(NameKey) {
|
||||
opts = append(opts, credentials.DefaultName())
|
||||
nameVal, ok := d.GetOk(NameKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithName(nameVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(DescriptionKey) {
|
||||
opts = append(opts, credentials.DefaultDescription())
|
||||
descVal, ok := d.GetOk(DescriptionKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithDescription(descVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(credentialPasswordKey) {
|
||||
passwordVal, ok := d.GetOk(credentialPasswordKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithPasswordCredentialPassword(passwordVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts) > 0 {
|
||||
opts = append(opts, credentials.WithAutomaticVersioning(true))
|
||||
crUpdate, err := client.Update(ctx, d.Id(), 0, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error updating credential: %v", err)
|
||||
}
|
||||
if crUpdate == nil {
|
||||
return diag.Errorf("credential nil after update")
|
||||
}
|
||||
|
||||
if err = setFromCredentialPasswordResponseMap(d, crUpdate.GetResponse().Map, false); err != nil {
|
||||
return diag.Errorf("error generating credential from response map: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialPasswordDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentials.NewClient(md.client)
|
||||
|
||||
_, err := client.Delete(ctx, d.Id())
|
||||
if err != nil {
|
||||
return diag.Errorf("error deleting credential: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/boundary/testing/controller"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
||||
)
|
||||
|
||||
const (
|
||||
passwordCredResc = "boundary_credential_password.example"
|
||||
passwordCredName = "foo"
|
||||
passwordCredDesc = "the foo"
|
||||
passwordCredPassword = "default_password"
|
||||
passwordCredUpdate = "_random"
|
||||
)
|
||||
|
||||
func passwordCredResource(name, description, password string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "boundary_credential_store_static" "example" {
|
||||
name = "static store name"
|
||||
description = "static store description"
|
||||
scope_id = boundary_scope.proj1.id
|
||||
depends_on = [boundary_role.proj1_admin]
|
||||
}
|
||||
|
||||
resource "boundary_credential_password" "example" {
|
||||
name = "%s"
|
||||
description = "%s"
|
||||
credential_store_id = boundary_credential_store_static.example.id
|
||||
password = "%s"
|
||||
}`, name,
|
||||
description,
|
||||
password)
|
||||
}
|
||||
|
||||
func TestAccCredentialPassword(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
res := passwordCredResource(
|
||||
passwordCredName,
|
||||
passwordCredDesc,
|
||||
passwordCredPassword,
|
||||
)
|
||||
|
||||
resUpdate := passwordCredResource(
|
||||
passwordCredName,
|
||||
passwordCredDesc,
|
||||
passwordCredPassword+passwordCredUpdate,
|
||||
)
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckCredentialResourceDestroy(t, provider, passwordCredentialType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, res),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(passwordCredResc, NameKey, passwordCredName),
|
||||
resource.TestCheckResourceAttr(passwordCredResc, DescriptionKey, passwordCredDesc),
|
||||
resource.TestCheckResourceAttr(passwordCredResc, credentialPasswordKey, passwordCredPassword),
|
||||
|
||||
testAccCheckCredentialPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, passwordCredResc),
|
||||
),
|
||||
},
|
||||
importStep(passwordCredResc, credentialPasswordKey),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(passwordCredResc, NameKey, passwordCredName),
|
||||
resource.TestCheckResourceAttr(passwordCredResc, DescriptionKey, passwordCredDesc),
|
||||
resource.TestCheckResourceAttr(passwordCredResc, credentialPasswordKey, passwordCredPassword+passwordCredUpdate),
|
||||
|
||||
testAccCheckCredentialPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, passwordCredResc),
|
||||
),
|
||||
},
|
||||
importStep(passwordCredResc, credentialPasswordKey),
|
||||
{
|
||||
// Run a plan only update and verify no changes
|
||||
PlanOnly: true,
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
},
|
||||
importStep(passwordCredResc, credentialPasswordKey),
|
||||
{
|
||||
// update again but apply a preConfig to externally update resource
|
||||
PreConfig: func() { passwordCredExternalUpdate(t, provider) },
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
},
|
||||
importStep(passwordCredResc, credentialPasswordKey),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func passwordCredExternalUpdate(t *testing.T, testProvider *schema.Provider) {
|
||||
if storeId == "" {
|
||||
t.Fatal("storeId must be set before testing an external update")
|
||||
}
|
||||
|
||||
md := testProvider.Meta().(*metaData)
|
||||
c := credentials.NewClient(md.client)
|
||||
cr, err := c.Read(context.Background(), storeId)
|
||||
if err != nil {
|
||||
t.Fatal(fmt.Errorf("got an error reading %q: %w", storeId, err))
|
||||
}
|
||||
|
||||
// update credential options
|
||||
var opts []credentials.Option
|
||||
opts = append(opts, credentials.WithDescription("this is an updated description, my guy"))
|
||||
|
||||
_, err = c.Update(context.Background(), cr.Item.Id, cr.Item.Version, opts...)
|
||||
if err != nil {
|
||||
t.Fatal(fmt.Errorf("got an error updating %q: %w", cr.Item.Id, err))
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckCredentialPasswordHmac() resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[passwordCredResc]
|
||||
if !ok {
|
||||
return fmt.Errorf("not found: %s", passwordCredResc)
|
||||
}
|
||||
|
||||
computed := rs.Primary.Attributes["password_hmac"]
|
||||
if len(computed) != 43 {
|
||||
return fmt.Errorf("Computed password hmac not the expected length of 43 characters. hmac: %q", computed)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
credentialUsernamePasswordDomainUsernameKey = "username"
|
||||
credentialUsernamePasswordDomainPasswordKey = "password"
|
||||
credentialUsernamePasswordDomainPasswordHmacKey = "password_hmac"
|
||||
credentialUsernamePasswordDomainDomainKey = "domain"
|
||||
credentialUsernamePasswordDomainCredentialType = "username_password_domain"
|
||||
)
|
||||
|
||||
func resourceCredentialUsernamePasswordDomain() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Description: "The username-password-domain credential resource allows you to configure a credential using a username, password and domain.",
|
||||
|
||||
CreateContext: resourceCredentialUsernamePasswordDomainCreate,
|
||||
ReadContext: resourceCredentialUsernamePasswordDomainRead,
|
||||
UpdateContext: resourceCredentialUsernamePasswordDomainUpdate,
|
||||
DeleteContext: resourceCredentialUsernamePasswordDomainDelete,
|
||||
CustomizeDiff: resourceCredentialUsernamePasswordDomainCustomizeDiff,
|
||||
Importer: &schema.ResourceImporter{
|
||||
StateContext: schema.ImportStatePassthroughContext,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
IDKey: {
|
||||
Description: "The ID of this username-password-domain credential.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
NameKey: {
|
||||
Description: "The name of this username-password-domain credential. Defaults to the resource name.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
DescriptionKey: {
|
||||
Description: "The description of this username-password-domain credential.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
credentialStoreIdKey: {
|
||||
Description: "The credential store in which to save this username-password-domain credential.",
|
||||
Type: schema.TypeString,
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
},
|
||||
credentialUsernamePasswordDomainUsernameKey: {
|
||||
Description: "This field is required even though it is marked as optional. The username of this username-password-domain credential. Can also contain a domain if provided as username@domain or domain\\username",
|
||||
Type: schema.TypeString,
|
||||
Optional: true, // Explicitly set as optional so that Terraform doesn't interpret this field as read-only.
|
||||
Computed: true, // Required and Computed are mutually exclusive.
|
||||
},
|
||||
credentialUsernamePasswordDomainPasswordKey: {
|
||||
Description: "The password of this username-password-domain credential.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
credentialUsernamePasswordDomainPasswordHmacKey: {
|
||||
Description: "The password hmac.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
credentialUsernamePasswordDomainDomainKey: {
|
||||
Description: "The domain of this username-password-domain credential. This field is required unless provided as part of the username field instead (see username field description).",
|
||||
Type: schema.TypeString,
|
||||
Optional: true, // Explicitly set as optional so that Terraform doesn't interpret this field as read-only.
|
||||
Computed: true, // Required and Computed are mutually exclusive.
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func setFromCredentialUsernamePasswordDomainResponseMap(d *schema.ResourceData, raw map[string]interface{}, fromRead bool) error {
|
||||
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(credentialStoreIdKey, raw[credentialStoreIdKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if attrsVal, ok := raw["attributes"]; ok {
|
||||
attrs := attrsVal.(map[string]interface{})
|
||||
if err := d.Set(credentialUsernamePasswordDomainUsernameKey, attrs[credentialUsernamePasswordDomainUsernameKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
statePasswordHmac := d.Get(credentialUsernamePasswordDomainPasswordHmacKey)
|
||||
boundaryPasswordHmac := attrs[credentialUsernamePasswordDomainPasswordHmacKey].(string)
|
||||
if statePasswordHmac.(string) != boundaryPasswordHmac && fromRead {
|
||||
// PasswordHmac has changed in Boundary, therefore the password has changed.
|
||||
// Update password value to force tf to attempt update.
|
||||
if err := d.Set(credentialUsernamePasswordDomainPasswordKey, "(changed in Boundary)"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := d.Set(credentialUsernamePasswordDomainPasswordHmacKey, boundaryPasswordHmac); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.Set(credentialUsernamePasswordDomainDomainKey, attrs[credentialUsernamePasswordDomainDomainKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.SetId(raw["id"].(string))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialUsernamePasswordDomainCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
|
||||
var opts []credentials.Option
|
||||
if v, ok := d.GetOk(NameKey); ok {
|
||||
opts = append(opts, credentials.WithName(v.(string)))
|
||||
}
|
||||
if v, ok := d.GetOk(DescriptionKey); ok {
|
||||
opts = append(opts, credentials.WithDescription(v.(string)))
|
||||
}
|
||||
|
||||
// Username and Domain can be set separately, but can also be set together
|
||||
// in the form of "username@domain" or "domain\\username".
|
||||
// We need to parse them out in order to set them correctly.
|
||||
usernameKey, domainKey := "", ""
|
||||
if v, ok := d.GetOk(credentialUsernamePasswordDomainUsernameKey); ok {
|
||||
usernameKey = v.(string)
|
||||
}
|
||||
if v, ok := d.GetOk(credentialUsernamePasswordDomainDomainKey); ok {
|
||||
domainKey = v.(string)
|
||||
}
|
||||
|
||||
username, domain, err := credentials.ParseUsernameDomain(usernameKey, domainKey)
|
||||
if err != nil {
|
||||
return diag.Errorf("error parsing username and domain: %v", err)
|
||||
}
|
||||
|
||||
switch username {
|
||||
case "":
|
||||
default:
|
||||
opts = append(opts, credentials.WithUsernamePasswordDomainCredentialUsername(username))
|
||||
}
|
||||
switch domain {
|
||||
case "":
|
||||
default:
|
||||
opts = append(opts, credentials.WithUsernamePasswordDomainCredentialDomain(domain))
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk(credentialUsernamePasswordDomainPasswordKey); ok {
|
||||
opts = append(opts, credentials.WithUsernamePasswordDomainCredentialPassword(v.(string)))
|
||||
}
|
||||
|
||||
var credentialStoreId string
|
||||
retrievedStoreId, ok := d.GetOk(credentialStoreIdKey)
|
||||
if ok {
|
||||
credentialStoreId = retrievedStoreId.(string)
|
||||
} else {
|
||||
return diag.Errorf("credential store id is unset")
|
||||
}
|
||||
|
||||
client := credentials.NewClient(md.client)
|
||||
cr, err := client.Create(ctx, credentialUsernamePasswordDomainCredentialType, credentialStoreId, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error creating credential: %v", err)
|
||||
}
|
||||
if cr == nil {
|
||||
return diag.Errorf("nil credential after create")
|
||||
}
|
||||
|
||||
if err := setFromCredentialUsernamePasswordDomainResponseMap(d, cr.GetResponse().Map, false); err != nil {
|
||||
return diag.Errorf("error generating credential from response map: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialUsernamePasswordDomainRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentials.NewClient(md.client)
|
||||
|
||||
cr, err := client.Read(ctx, d.Id())
|
||||
if err != nil {
|
||||
if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return diag.Errorf("error reading credential: %v", err)
|
||||
}
|
||||
if cr == nil {
|
||||
return diag.Errorf("credential nil after read")
|
||||
}
|
||||
|
||||
if err := setFromCredentialUsernamePasswordDomainResponseMap(d, cr.GetResponse().Map, true); err != nil {
|
||||
return diag.Errorf("error generating credential from response map: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialUsernamePasswordDomainUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentials.NewClient(md.client)
|
||||
|
||||
var opts []credentials.Option
|
||||
if d.HasChange(NameKey) {
|
||||
opts = append(opts, credentials.DefaultName())
|
||||
nameVal, ok := d.GetOk(NameKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithName(nameVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(DescriptionKey) {
|
||||
opts = append(opts, credentials.DefaultDescription())
|
||||
descVal, ok := d.GetOk(DescriptionKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithDescription(descVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
// Username and Domain can be set separately, but can also be set together
|
||||
// in the form of "username@domain" or "domain\\username".
|
||||
// Since we do not know if they were originally set together or separately,
|
||||
// we need to check if either of them has changed.
|
||||
if d.HasChange(credentialUsernamePasswordDomainUsernameKey) || d.HasChange(credentialUsernamePasswordDomainDomainKey) {
|
||||
usernameKey, domainKey := "", ""
|
||||
if v, ok := d.GetOk(credentialUsernamePasswordDomainUsernameKey); ok {
|
||||
usernameKey = v.(string)
|
||||
}
|
||||
if v, ok := d.GetOk(credentialUsernamePasswordDomainDomainKey); ok {
|
||||
domainKey = v.(string)
|
||||
}
|
||||
|
||||
username, domain, err := credentials.ParseUsernameDomain(usernameKey, domainKey)
|
||||
if err != nil {
|
||||
return diag.Errorf("error parsing username and domain: %v", err)
|
||||
}
|
||||
|
||||
switch username {
|
||||
case "":
|
||||
default:
|
||||
opts = append(opts, credentials.WithUsernamePasswordDomainCredentialUsername(username))
|
||||
}
|
||||
switch domain {
|
||||
case "":
|
||||
default:
|
||||
opts = append(opts, credentials.WithUsernamePasswordDomainCredentialDomain(domain))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(credentialUsernamePasswordDomainPasswordKey) {
|
||||
passwordVal, ok := d.GetOk(credentialUsernamePasswordDomainPasswordKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithUsernamePasswordDomainCredentialPassword(passwordVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts) > 0 {
|
||||
opts = append(opts, credentials.WithAutomaticVersioning(true))
|
||||
crUpdate, err := client.Update(ctx, d.Id(), 0, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error updating credential: %v", err)
|
||||
}
|
||||
if crUpdate == nil {
|
||||
return diag.Errorf("credential nil after update")
|
||||
}
|
||||
|
||||
if err = setFromCredentialUsernamePasswordDomainResponseMap(d, crUpdate.GetResponse().Map, false); err != nil {
|
||||
return diag.Errorf("error generating credential from response map: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialUsernamePasswordDomainDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentials.NewClient(md.client)
|
||||
|
||||
_, err := client.Delete(ctx, d.Id())
|
||||
if err != nil {
|
||||
return diag.Errorf("error deleting credential: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialUsernamePasswordDomainCustomizeDiff(ctx context.Context, rd *schema.ResourceDiff, _ interface{}) error {
|
||||
usernameRaw := rd.Get(credentialUsernamePasswordDomainUsernameKey).(string)
|
||||
domainRaw := rd.Get(credentialUsernamePasswordDomainDomainKey).(string)
|
||||
|
||||
if usernameRaw != "" && domainRaw != "" {
|
||||
if strings.Contains(usernameRaw, "@") || strings.Contains(usernameRaw, "\\") {
|
||||
// This is an error condition for ParseUsernameDomain, so handle it
|
||||
// here by blanking the domain input. We've already asserted that
|
||||
// the username appears to contain a domain, so we'll extract it
|
||||
// below.
|
||||
domainRaw = ""
|
||||
}
|
||||
}
|
||||
|
||||
username, domain, err := credentials.ParseUsernameDomain(usernameRaw, domainRaw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing username and domain: %w", err)
|
||||
}
|
||||
// We can't set the fields as Required in the config (because we
|
||||
// have to set Computed), so enforce it here.
|
||||
if username == "" {
|
||||
return fmt.Errorf("username field is required")
|
||||
}
|
||||
if domain == "" {
|
||||
return fmt.Errorf("domain field is required")
|
||||
}
|
||||
|
||||
err = rd.Clear(credentialUsernamePasswordDomainUsernameKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to clear username field: %w", err)
|
||||
}
|
||||
err = rd.SetNew(credentialUsernamePasswordDomainUsernameKey, username)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set new username: %w", err)
|
||||
}
|
||||
|
||||
err = rd.Clear(credentialUsernamePasswordDomainDomainKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to clear domain field: %w", err)
|
||||
}
|
||||
err = rd.SetNew(credentialUsernamePasswordDomainDomainKey, domain)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set new domain: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,640 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/boundary/testing/controller"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
||||
)
|
||||
|
||||
const (
|
||||
usernamePasswordDomainCredResc = "boundary_credential_username_password_domain.example"
|
||||
usernamePasswordDomainCredName = "foo"
|
||||
usernamePasswordDomainCredDesc = "the foo"
|
||||
usernamePasswordDomainCredUsername = "default_username"
|
||||
usernamePasswordDomainCredUsernameAt = "default_username@default_domain"
|
||||
usernamePasswordDomainCredUsernameSlash = `default_domain\\default_username`
|
||||
usernamePasswordDomainCredPassword = "default_password"
|
||||
usernamePasswordDomainCredDomain = "default_domain"
|
||||
usernamePasswordDomainCredUpdate = "_random"
|
||||
)
|
||||
|
||||
func usernamePasswordDomainCredResourceWithoutDomain(name, description, username, password string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "boundary_credential_store_static" "example" {
|
||||
name = "static store name"
|
||||
description = "static store description"
|
||||
scope_id = boundary_scope.proj1.id
|
||||
depends_on = [boundary_role.proj1_admin]
|
||||
}
|
||||
|
||||
resource "boundary_credential_username_password_domain" "example" {
|
||||
name = "%s"
|
||||
description = "%s"
|
||||
credential_store_id = boundary_credential_store_static.example.id
|
||||
username = "%s"
|
||||
password = "%s"
|
||||
}`, name,
|
||||
description,
|
||||
username,
|
||||
password)
|
||||
}
|
||||
|
||||
func usernamePasswordDomainCredResourceWithDomain(name, description, username, password, domain string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "boundary_credential_store_static" "example" {
|
||||
name = "static store name"
|
||||
description = "static store description"
|
||||
scope_id = boundary_scope.proj1.id
|
||||
depends_on = [boundary_role.proj1_admin]
|
||||
}
|
||||
|
||||
resource "boundary_credential_username_password_domain" "example" {
|
||||
name = "%s"
|
||||
description = "%s"
|
||||
credential_store_id = boundary_credential_store_static.example.id
|
||||
username = "%s"
|
||||
password = "%s"
|
||||
domain = "%s"
|
||||
}`, name,
|
||||
description,
|
||||
username,
|
||||
password,
|
||||
domain)
|
||||
}
|
||||
|
||||
func TestAccCredentialUsernamePasswordDomain(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
res := usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
usernamePasswordDomainCredUsername,
|
||||
usernamePasswordDomainCredPassword,
|
||||
usernamePasswordDomainCredDomain,
|
||||
)
|
||||
|
||||
resUpdate := usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate,
|
||||
usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate,
|
||||
usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate,
|
||||
)
|
||||
|
||||
resUpdateAt := usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf("%s@%s", usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate),
|
||||
usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate,
|
||||
)
|
||||
|
||||
resUpdateSlash := usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf(`%s\\%s`, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate, usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate),
|
||||
usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate,
|
||||
)
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckCredentialResourceDestroy(t, provider, usernamePasswordDomainCredentialType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, res),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// run a plan only update and verify no changes
|
||||
PlanOnly: true,
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update again but apply a preConfig to externally update resource
|
||||
PreConfig: func() { usernamePasswordDomainCredExternalUpdate(t, provider) },
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
},
|
||||
})
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckCredentialResourceDestroy(t, provider, usernamePasswordDomainCredentialType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, res),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update from 3 distinct fields to username@domain.
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdateAt),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
},
|
||||
})
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckCredentialResourceDestroy(t, provider, usernamePasswordDomainCredentialType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, res),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update from 3 distinct fields to domain\username.
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdateSlash),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccCredentialUsernamePasswordDomain_DomainInUsernameFieldUsingAt(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
res := usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
usernamePasswordDomainCredUsernameAt,
|
||||
usernamePasswordDomainCredPassword,
|
||||
)
|
||||
|
||||
resUpdate := usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf("%s@%s", usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate),
|
||||
usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate,
|
||||
)
|
||||
|
||||
resUpdateSeparateFields := usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
usernamePasswordCredUsername+usernamePasswordCredUpdate+usernamePasswordCredUpdate,
|
||||
usernamePasswordDomainCredPassword+usernamePasswordCredUpdate+usernamePasswordCredUpdate,
|
||||
usernamePasswordDomainCredDomain+usernamePasswordCredUpdate+usernamePasswordCredUpdate,
|
||||
)
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckCredentialResourceDestroy(t, provider, usernamePasswordDomainCredentialType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, res),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// Run a plan only update and verify no changes
|
||||
PlanOnly: true,
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update again but apply a preConfig to externally update resource
|
||||
PreConfig: func() { usernamePasswordDomainCredExternalUpdate(t, provider) },
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update from username@domain to use all 3 fields separately.
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdateSeparateFields),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate+usernamePasswordDomainCredUpdate),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccCredentialUsernamePasswordDomain_DomainInUsernameFieldUsingSlash(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
res := usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
usernamePasswordDomainCredUsernameSlash,
|
||||
usernamePasswordDomainCredPassword,
|
||||
)
|
||||
|
||||
resUpdate := usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf(`%s\\%s`, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate, usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate),
|
||||
usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate,
|
||||
)
|
||||
|
||||
resUpdateSeparateFields := usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
usernamePasswordCredUsername+usernamePasswordCredUpdate+usernamePasswordCredUpdate,
|
||||
usernamePasswordDomainCredPassword+usernamePasswordCredUpdate+usernamePasswordCredUpdate,
|
||||
usernamePasswordDomainCredDomain+usernamePasswordCredUpdate+usernamePasswordCredUpdate,
|
||||
)
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckCredentialResourceDestroy(t, provider, usernamePasswordDomainCredentialType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, res),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// Run a plan only update and verify no changes
|
||||
PlanOnly: true,
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update again but apply a preConfig to externally update resource
|
||||
PreConfig: func() { usernamePasswordDomainCredExternalUpdate(t, provider) },
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// update from domain\username to use all 3 fields separately.
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdateSeparateFields),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername+usernamePasswordDomainCredUpdate+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword+usernamePasswordDomainCredUpdate+usernamePasswordDomainCredUpdate),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain+usernamePasswordDomainCredUpdate+usernamePasswordDomainCredUpdate),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// TestResourceCredentialUsernamePasswordDomainCustomizeDiff tests the diff
|
||||
// customization function by testing the diff equivalency of different
|
||||
// combinations of inputs.
|
||||
func TestResourceCredentialUsernamePasswordDomainCustomizeDiff(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
createResource string
|
||||
planOnlyUpdates []string
|
||||
}{
|
||||
{
|
||||
name: "usernamePasswordDomainFormatToOtherFormats",
|
||||
createResource: usernamePasswordDomainCredResourceWithDomain( // Start w/ username, password, domain.
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
usernamePasswordDomainCredUsername,
|
||||
usernamePasswordDomainCredPassword,
|
||||
usernamePasswordDomainCredDomain,
|
||||
),
|
||||
planOnlyUpdates: []string{
|
||||
// Plan an update to username@domain (with domain field still filled).
|
||||
usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf("%s@%s", usernamePasswordDomainCredUsername, usernamePasswordDomainCredDomain),
|
||||
usernamePasswordDomainCredPassword,
|
||||
usernamePasswordDomainCredDomain,
|
||||
),
|
||||
// Plan an update to username@domain and empty out domain.
|
||||
usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf("%s@%s", usernamePasswordDomainCredUsername, usernamePasswordDomainCredDomain),
|
||||
usernamePasswordDomainCredPassword,
|
||||
"",
|
||||
),
|
||||
// Plan an update to username@domain and nil out domain.
|
||||
usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf("%s@%s", usernamePasswordDomainCredUsername, usernamePasswordDomainCredDomain),
|
||||
usernamePasswordDomainCredPassword,
|
||||
),
|
||||
// Plan an update to domain\username (with domain field still filled).
|
||||
usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf(`%s\\%s`, usernamePasswordDomainCredDomain, usernamePasswordDomainCredUsername),
|
||||
usernamePasswordDomainCredPassword,
|
||||
usernamePasswordDomainCredDomain,
|
||||
),
|
||||
// Plan an update to domain\username and empty out domain.
|
||||
usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf(`%s\\%s`, usernamePasswordDomainCredDomain, usernamePasswordDomainCredUsername),
|
||||
usernamePasswordDomainCredPassword,
|
||||
"",
|
||||
),
|
||||
// Plan an update to domain\username and nil out domain.
|
||||
usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf(`%s\\%s`, usernamePasswordDomainCredDomain, usernamePasswordDomainCredUsername),
|
||||
usernamePasswordDomainCredPassword,
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "usernameAtpasswordFormatToOtherFormats",
|
||||
createResource: usernamePasswordDomainCredResourceWithoutDomain( // Start w/ username@domain and password.
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf("%s@%s", usernamePasswordDomainCredUsername, usernamePasswordDomainCredDomain),
|
||||
usernamePasswordDomainCredPassword,
|
||||
),
|
||||
planOnlyUpdates: []string{
|
||||
// Plan an update to domain\username.
|
||||
usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf(`%s\\%s`, usernamePasswordDomainCredDomain, usernamePasswordDomainCredUsername),
|
||||
usernamePasswordDomainCredPassword,
|
||||
),
|
||||
// Plan an update to add the same domain in the domain field.
|
||||
usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf("%s@%s", usernamePasswordDomainCredUsername, usernamePasswordDomainCredDomain),
|
||||
usernamePasswordDomainCredPassword,
|
||||
usernamePasswordDomainCredDomain,
|
||||
),
|
||||
// Plan an update to add the same username in the username field.
|
||||
usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
usernamePasswordDomainCredUsername,
|
||||
usernamePasswordDomainCredPassword,
|
||||
usernamePasswordDomainCredDomain,
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "domainSlashUsernameFormatToOtherFormats",
|
||||
createResource: usernamePasswordDomainCredResourceWithoutDomain( // Start w/ domain\username and password.
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf(`%s\\%s`, usernamePasswordDomainCredDomain, usernamePasswordDomainCredUsername),
|
||||
usernamePasswordDomainCredPassword,
|
||||
),
|
||||
planOnlyUpdates: []string{
|
||||
// Plan an update to username@domain.
|
||||
usernamePasswordDomainCredResourceWithoutDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf("%s@%s", usernamePasswordDomainCredUsername, usernamePasswordDomainCredDomain),
|
||||
usernamePasswordDomainCredPassword,
|
||||
),
|
||||
// Plan an update to add the same domain in the domain field.
|
||||
usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
fmt.Sprintf("%s@%s", usernamePasswordDomainCredUsername, usernamePasswordDomainCredDomain),
|
||||
usernamePasswordDomainCredPassword,
|
||||
usernamePasswordDomainCredDomain,
|
||||
),
|
||||
// Plan an update to add the same username in the username field.
|
||||
usernamePasswordDomainCredResourceWithDomain(
|
||||
usernamePasswordDomainCredName,
|
||||
usernamePasswordDomainCredDesc,
|
||||
usernamePasswordDomainCredUsername,
|
||||
usernamePasswordDomainCredPassword,
|
||||
usernamePasswordDomainCredDomain,
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var provider *schema.Provider
|
||||
tc := resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckCredentialResourceDestroy(t, provider, usernamePasswordDomainCredentialType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// Create resource.
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, tt.createResource),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, NameKey, usernamePasswordDomainCredName),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, DescriptionKey, usernamePasswordDomainCredDesc),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainUsernameKey, usernamePasswordDomainCredUsername),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey, usernamePasswordDomainCredPassword),
|
||||
resource.TestCheckResourceAttr(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainDomainKey, usernamePasswordDomainCredDomain),
|
||||
|
||||
testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac(),
|
||||
testAccCheckCredentialResourceExists(provider, usernamePasswordDomainCredResc),
|
||||
),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
{
|
||||
// Run a plan-only update on itself and verify no changes.
|
||||
PlanOnly: true,
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, tt.createResource),
|
||||
},
|
||||
importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey),
|
||||
},
|
||||
}
|
||||
|
||||
for _, resUpdate := range tt.planOnlyUpdates {
|
||||
tc.Steps = append(tc.Steps, resource.TestStep{
|
||||
PlanOnly: true,
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||
}, importStep(usernamePasswordDomainCredResc, credentialUsernamePasswordDomainPasswordKey))
|
||||
}
|
||||
|
||||
resource.Test(t, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func usernamePasswordDomainCredExternalUpdate(t *testing.T, testProvider *schema.Provider) {
|
||||
if storeId == "" {
|
||||
t.Fatal("storeId must be set before testing an external update")
|
||||
}
|
||||
|
||||
md := testProvider.Meta().(*metaData)
|
||||
c := credentials.NewClient(md.client)
|
||||
cr, err := c.Read(context.Background(), storeId)
|
||||
if err != nil {
|
||||
t.Fatal(fmt.Errorf("got an error reading %q: %w", storeId, err))
|
||||
}
|
||||
|
||||
// update credential options
|
||||
var opts []credentials.Option
|
||||
opts = append(opts, credentials.WithDescription("this is an updated description, my guy"))
|
||||
|
||||
_, err = c.Update(context.Background(), cr.Item.Id, cr.Item.Version, opts...)
|
||||
if err != nil {
|
||||
t.Fatal(fmt.Errorf("got an error updating %q: %w", cr.Item.Id, err))
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckCredentialStoreUsernamePasswordDomainPasswordHmac() resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[usernamePasswordDomainCredResc]
|
||||
if !ok {
|
||||
return fmt.Errorf("not found: %s", usernamePasswordDomainCredResc)
|
||||
}
|
||||
|
||||
computed := rs.Primary.Attributes["password_hmac"]
|
||||
if len(computed) != 43 {
|
||||
return fmt.Errorf("Computed password hmac not the expected length of 43 characters. hmac: %q", computed)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -118,6 +118,11 @@ func resourceHostCatalogPlugin() *schema.Resource {
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
WorkerFilterKey: {
|
||||
Description: "HCP Only. A filter used to control which PKI workers can handle dynamic host catalog requests.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
internalSecretsConfigHmacKey: {
|
||||
Description: "Internal only. HMAC of (serverSecretsHmac + config secrets). Used for proper secrets handling.",
|
||||
Type: schema.TypeString,
|
||||
@@ -294,6 +299,9 @@ func setFromHostCatalogPluginResponseMap(d *schema.ResourceData, raw map[string]
|
||||
if err := d.Set(ScopeIdKey, raw[ScopeIdKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(WorkerFilterKey, raw[WorkerFilterKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
// Plugin stuff
|
||||
{
|
||||
if err := d.Set(PluginIdKey, raw[PluginIdKey]); err != nil {
|
||||
@@ -399,6 +407,12 @@ func resourceHostCatalogPluginCreate(ctx context.Context, d *schema.ResourceData
|
||||
opts = append(opts, hostcatalogs.WithDescription(descStr))
|
||||
}
|
||||
|
||||
workerFilterVal, ok := d.GetOk(WorkerFilterKey)
|
||||
if ok {
|
||||
workerFilterStr := workerFilterVal.(string)
|
||||
opts = append(opts, hostcatalogs.WithWorkerFilter(workerFilterStr))
|
||||
}
|
||||
|
||||
attrsVal, ok := d.GetOk(AttributesJsonKey)
|
||||
if ok {
|
||||
attrsStr, err := parseutil.ParsePath(attrsVal.(string))
|
||||
@@ -556,6 +570,15 @@ func resourceHostCatalogPluginUpdate(ctx context.Context, d *schema.ResourceData
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(WorkerFilterKey) {
|
||||
opts = append(opts, hostcatalogs.DefaultWorkerFilter())
|
||||
workerFilterVal, ok := d.GetOk(WorkerFilterKey)
|
||||
if ok {
|
||||
workerFilterStr := workerFilterVal.(string)
|
||||
opts = append(opts, hostcatalogs.WithWorkerFilter(workerFilterStr))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(AttributesJsonKey) {
|
||||
attrsVal, ok := d.GetOk(AttributesJsonKey)
|
||||
if ok {
|
||||
|
||||
@@ -22,6 +22,9 @@ const (
|
||||
testPluginHostCatalogDescription = "bar"
|
||||
testPluginHostCatalogDescriptionUpdate = "bar foo"
|
||||
testPluginHostCatalogDescriptionUpdate2 = "bar foo foo"
|
||||
|
||||
testPluginHostCatalogWorkerFilterUpdate = "\"dev\" in \"/tags/type\""
|
||||
testPluginHostCatalogWorkerFilterUpdate2 = "\"pki\" in \"/tags/type\""
|
||||
)
|
||||
|
||||
// expectedAttributesState is used here and in plugin host sets to control how
|
||||
@@ -244,6 +247,212 @@ func TestAccPluginHostCatalog(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccPluginHostCatalogWithWorkerFilter(t *testing.T) {
|
||||
t.Skip("Skipping test until Boundary Terraform Provider can unit tests for Boundary Enterprise only features")
|
||||
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
resName := "boundary_host_catalog_plugin.foo"
|
||||
initialValuesStr := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zap"
|
||||
})
|
||||
secrets_json = jsonencode({
|
||||
hush = "puppies"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescription,
|
||||
)
|
||||
|
||||
// Changed description, secrets and added worker filter.
|
||||
valuesStrUpdate1 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = %q
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zoop"
|
||||
})
|
||||
secrets_json = jsonencode({
|
||||
flush = "fluppies"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate,
|
||||
testPluginHostCatalogWorkerFilterUpdate,
|
||||
)
|
||||
|
||||
// Changed description, no secrets update, nullify worker filter.
|
||||
valuesStrUpdate2 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = null
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zoop"
|
||||
})
|
||||
secrets_json = jsonencode({
|
||||
flush = "fluppies"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
)
|
||||
|
||||
// Same description and set a worker filter again, now empty secrets.
|
||||
valuesStrUpdate3 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = %q
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zoop"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
testPluginHostCatalogWorkerFilterUpdate2,
|
||||
)
|
||||
|
||||
// Same description, now explicitly unset secrets and blankify attrs and
|
||||
// worker filter.
|
||||
valuesStrUpdate4 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
secrets_json = "null"
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
)
|
||||
|
||||
// Set values again
|
||||
valuesStrUpdate5 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = %q
|
||||
attributes_json = jsonencode({
|
||||
foo = "bar"
|
||||
zip = "zoop"
|
||||
})
|
||||
secrets_json = jsonencode({
|
||||
flush = "fluppies"
|
||||
})
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
testPluginHostCatalogWorkerFilterUpdate2,
|
||||
)
|
||||
|
||||
// Explicitly set both secrets and attributes to null
|
||||
valuesStrUpdate6 := fmt.Sprintf(`
|
||||
description = "%s"
|
||||
worker_filter = %q
|
||||
attributes_json = "null"
|
||||
secrets_json = "null"
|
||||
`,
|
||||
testPluginHostCatalogDescriptionUpdate2,
|
||||
testPluginHostCatalogWorkerFilterUpdate2,
|
||||
)
|
||||
|
||||
initialHcl := fmt.Sprintf(projPluginHostCatalogBase, initialValuesStr)
|
||||
update1Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate1)
|
||||
update2Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate2)
|
||||
update3Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate3)
|
||||
update4Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate4)
|
||||
update5Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate5)
|
||||
update6Hcl := fmt.Sprintf(projPluginHostCatalogBase, valuesStrUpdate6)
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckHostCatalogResourceDestroy(t, provider, baseHostCatalogType),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// test create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, initialHcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.org1"),
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.proj1"),
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslyEmptyNowSet),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescription),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update1Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetButChanged),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate),
|
||||
resource.TestCheckResourceAttr(resName, WorkerFilterKey, testPluginHostCatalogWorkerFilterUpdate),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update2Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNoChange),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// this runs the same HCL; mostly used in some manual checking
|
||||
// to ensure update is still called even when nothing has
|
||||
// changed (as we need for secrets)
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update2Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNoChange),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update3Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNoChange),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
resource.TestCheckResourceAttr(resName, WorkerFilterKey, testPluginHostCatalogWorkerFilterUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update4Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNowEmpty),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update5Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslyEmptyNowSet),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
resource.TestCheckResourceAttr(resName, WorkerFilterKey, testPluginHostCatalogWorkerFilterUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
{
|
||||
// test update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, update6Hcl),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckPluginHostCatalogResourceExists(provider, resName, expectedAttributesStatePreviouslySetNowEmpty),
|
||||
resource.TestCheckResourceAttr(resName, DescriptionKey, testPluginHostCatalogDescriptionUpdate2),
|
||||
resource.TestCheckResourceAttr(resName, WorkerFilterKey, testPluginHostCatalogWorkerFilterUpdate2),
|
||||
),
|
||||
ExpectNonEmptyPlan: true,
|
||||
},
|
||||
importStep(resName, SecretsJsonKey, internalHmacUsedForSecretsConfigHmacKey, internalForceUpdateKey, internalSecretsConfigHmacKey),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckPluginHostCatalogResourceExists(testProvider *schema.Provider, name string, expAttrState expectedAttributesState) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
roleGrantScopeIdKey = "grant_scope_id"
|
||||
roleGrantScopeIdsKey = "grant_scope_ids"
|
||||
rolePrincipalIdsKey = "principal_ids"
|
||||
roleGrantStringsKey = "grant_strings"
|
||||
@@ -71,13 +70,6 @@ func resourceRole() *schema.Resource {
|
||||
Optional: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
roleGrantScopeIdKey: {
|
||||
Description: "For Boundary 0.15+, use `grant_scope_ids` instead. The scope for which the grants in the role should apply.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Deprecated: "In Boundary 0.15+, please use `grant_scope_ids` instead. This field will be removed in a future release.",
|
||||
},
|
||||
roleGrantScopeIdsKey: {
|
||||
Description: `A list of scopes for which the grants in this role should apply, which can include the special values "this", "children", or "descendants"`,
|
||||
Type: schema.TypeSet,
|
||||
@@ -108,9 +100,6 @@ func setFromRoleResponseMap(d *schema.ResourceData, raw map[string]interface{})
|
||||
if err := d.Set(roleGrantScopeIdsKey, raw["grant_scope_ids"]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(roleGrantScopeIdKey, raw["grant_scope_id"]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(raw["id"].(string))
|
||||
return nil
|
||||
@@ -140,11 +129,6 @@ func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, meta interf
|
||||
opts = append(opts, roles.WithDescription(descStr))
|
||||
}
|
||||
|
||||
grantScopeIdVal := d.Get(roleGrantScopeIdKey)
|
||||
if grantScopeIdVal != "" {
|
||||
grantScopeIdStr := grantScopeIdVal.(string)
|
||||
opts = append(opts, roles.WithGrantScopeId(grantScopeIdStr))
|
||||
}
|
||||
var grantScopeIds []string
|
||||
if grantScopeIdsVal, ok := d.GetOk(roleGrantScopeIdsKey); ok {
|
||||
list := grantScopeIdsVal.(*schema.Set).List()
|
||||
@@ -288,22 +272,6 @@ func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, meta interf
|
||||
}
|
||||
}
|
||||
|
||||
var grantScopeId *string
|
||||
if d.HasChange(roleGrantScopeIdKey) {
|
||||
// If it is an update to use the multi-value grant_scope_ids, and this
|
||||
// has changed to "", then don't set it on the API. Instead let it fall
|
||||
// through and below it'll be updated to be "".
|
||||
if !d.HasChange(roleGrantScopeIdsKey) {
|
||||
opts = append(opts, roles.DefaultGrantScopeId())
|
||||
grantScopeIdVal, ok := d.GetOk(roleGrantScopeIdKey)
|
||||
if ok {
|
||||
grantScopeIdStr := grantScopeIdVal.(string)
|
||||
grantScopeId = &grantScopeIdStr
|
||||
opts = append(opts, roles.WithGrantScopeId(grantScopeIdStr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts) > 0 {
|
||||
opts = append(opts, roles.WithAutomaticVersioning(true))
|
||||
_, err := rc.Update(ctx, d.Id(), 0, opts...)
|
||||
@@ -322,11 +290,6 @@ func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, meta interf
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
}
|
||||
if d.HasChange(roleGrantScopeIdKey) {
|
||||
if err := d.Set(roleGrantScopeIdKey, grantScopeId); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
var diags diag.Diagnostics
|
||||
if d.HasChange(roleGrantStringsKey) {
|
||||
|
||||
@@ -24,7 +24,7 @@ var (
|
||||
principal_ids = [boundary_user.foo.id]
|
||||
scope_id = boundary_scope.org1.id
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
grant_scope_ids = ["this", "children", boundary_scope.proj1.id]
|
||||
grant_scope_ids = ["this", boundary_scope.proj1.id]
|
||||
}`
|
||||
|
||||
orgRoleWithGrantScopesUpdate = `
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
principal_ids = [boundary_user.foo.id]
|
||||
scope_id = boundary_scope.org1.id
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
grant_scope_ids = ["this"]
|
||||
grant_scope_ids = ["this", "children"]
|
||||
}`
|
||||
|
||||
orgRoleWithInvalidGrantScopesUpdate = `
|
||||
@@ -46,38 +46,6 @@ var (
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
grant_scope_ids = ["this", "children", "p_foobar1234"]
|
||||
}`
|
||||
|
||||
conversionOrgRoleWithGrantScopeId = `
|
||||
resource "boundary_role" "with_grant_scope_id" {
|
||||
name = "grant scope id role"
|
||||
scope_id = boundary_scope.org1.id
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
grant_scope_id = boundary_scope.org1.id
|
||||
}`
|
||||
|
||||
conversionOrgRoleWithGrantScopeIdUpdate = `
|
||||
resource "boundary_role" "with_grant_scope_id" {
|
||||
name = "grant scope id role"
|
||||
scope_id = boundary_scope.org1.id
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
grant_scope_id = boundary_scope.proj1.id
|
||||
}`
|
||||
|
||||
conversionOrgRoleWithGrantScopeIdsConversion = `
|
||||
resource "boundary_role" "with_grant_scope_id" {
|
||||
name = "grant scope id role"
|
||||
scope_id = boundary_scope.org1.id
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
grant_scope_ids = ["this", boundary_scope.proj1.id]
|
||||
}`
|
||||
|
||||
conversionOrgRoleWithGrantScopeIdsUpdate = `
|
||||
resource "boundary_role" "with_grant_scope_id" {
|
||||
name = "grant scope id role"
|
||||
scope_id = boundary_scope.org1.id
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
grant_scope_ids = ["this", "children"]
|
||||
}`
|
||||
)
|
||||
|
||||
// TestAccRoleWithGrantScopes exercises creation and update with valid and
|
||||
@@ -100,7 +68,7 @@ func TestAccRoleWithGrantScopes(t *testing.T) {
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.proj1"),
|
||||
testAccCheckRoleResourceExists(provider, "boundary_role.with_grant_scopes"),
|
||||
testAccCheckUserResourceExists(provider, "boundary_user.foo"),
|
||||
testAccCheckRoleResourceGrantScopesSet(provider, "boundary_role.with_grant_scopes", []string{"this", "children", "boundary_scope.proj1"}),
|
||||
testAccCheckRoleResourceGrantScopesSet(provider, "boundary_role.with_grant_scopes", []string{"this", "boundary_scope.proj1"}),
|
||||
resource.TestCheckResourceAttr("boundary_role.with_grant_scopes", DescriptionKey, "with grant scopes"),
|
||||
resource.TestCheckResourceAttr("boundary_role.with_grant_scopes", NameKey, "with_grant_scopes"),
|
||||
),
|
||||
@@ -122,7 +90,7 @@ func TestAccRoleWithGrantScopes(t *testing.T) {
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, fooUser, orgRoleWithGrantScopesUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckRoleResourceExists(provider, "boundary_role.with_grant_scopes"),
|
||||
testAccCheckRoleResourceGrantScopesSet(provider, "boundary_role.with_grant_scopes", []string{"this"}),
|
||||
testAccCheckRoleResourceGrantScopesSet(provider, "boundary_role.with_grant_scopes", []string{"this", "children"}),
|
||||
resource.TestCheckResourceAttr("boundary_role.with_grant_scopes", DescriptionKey, "with grant scopes update"),
|
||||
resource.TestCheckResourceAttr("boundary_role.with_grant_scopes", NameKey, "with_grant_scopes_update"),
|
||||
),
|
||||
@@ -132,106 +100,6 @@ func TestAccRoleWithGrantScopes(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// TestAccRoleGrantScopeUpgrade exercises some specific upgrade scenarios around
|
||||
// grant_scope_id -> grant_scope_ids
|
||||
func TestAccRoleWithGrantScopesUpdate(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
t.Cleanup(tc.Shutdown)
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
IsUnitTest: true,
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckRoleResourceDestroy(t, provider),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// Create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, fooUser, conversionOrgRoleWithGrantScopeId),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.org1"),
|
||||
testAccCheckRoleResourceExists(provider, "boundary_role.with_grant_scope_id"),
|
||||
testAccCheckUserResourceExists(provider, "boundary_user.foo"),
|
||||
testAccCheckRoleResourceGrantScopesSet(provider, "boundary_role.with_grant_scope_id", []string{"boundary_scope.org1"}),
|
||||
testAccCheckRoleResourceGrantScopeSet(provider, "boundary_role.with_grant_scope_id", "boundary_scope.org1"),
|
||||
),
|
||||
},
|
||||
importStep("boundary_role.with_grant_scope_id"),
|
||||
{
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, fooUser, conversionOrgRoleWithGrantScopeIdUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.org1"),
|
||||
testAccCheckRoleResourceExists(provider, "boundary_role.with_grant_scope_id"),
|
||||
testAccCheckUserResourceExists(provider, "boundary_user.foo"),
|
||||
testAccCheckRoleResourceGrantScopesSet(provider, "boundary_role.with_grant_scope_id", []string{"boundary_scope.proj1"}),
|
||||
testAccCheckRoleResourceGrantScopeSet(provider, "boundary_role.with_grant_scope_id", "boundary_scope.proj1"),
|
||||
),
|
||||
},
|
||||
importStep("boundary_role.with_grant_scope_id"),
|
||||
{
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, fooUser, conversionOrgRoleWithGrantScopeIdsConversion),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.org1"),
|
||||
testAccCheckRoleResourceExists(provider, "boundary_role.with_grant_scope_id"),
|
||||
testAccCheckUserResourceExists(provider, "boundary_user.foo"),
|
||||
testAccCheckRoleResourceGrantScopesSet(provider, "boundary_role.with_grant_scope_id", []string{"this", "boundary_scope.proj1"}),
|
||||
testAccCheckRoleResourceGrantScopeSet(provider, "boundary_role.with_grant_scope_id", ""),
|
||||
),
|
||||
},
|
||||
importStep("boundary_role.with_grant_scope_id"),
|
||||
{
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, fooUser, conversionOrgRoleWithGrantScopeIdsUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckScopeResourceExists(provider, "boundary_scope.org1"),
|
||||
testAccCheckRoleResourceExists(provider, "boundary_role.with_grant_scope_id"),
|
||||
testAccCheckUserResourceExists(provider, "boundary_user.foo"),
|
||||
testAccCheckRoleResourceGrantScopesSet(provider, "boundary_role.with_grant_scope_id", []string{"this", "children"}),
|
||||
testAccCheckRoleResourceGrantScopeSet(provider, "boundary_role.with_grant_scope_id", ""),
|
||||
),
|
||||
},
|
||||
importStep("boundary_role.with_grant_scope_id"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckRoleResourceGrantScopeSet(testProvider *schema.Provider, name string, grantScope string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("role resource not found: %s", name)
|
||||
}
|
||||
|
||||
roleId := rs.Primary.ID
|
||||
|
||||
scopeId := grantScope
|
||||
if grantScope != "children" && grantScope != "this" && grantScope != "descendants" && grantScope != "" {
|
||||
scope, ok := s.RootModule().Resources[grantScope]
|
||||
if !ok {
|
||||
return fmt.Errorf("scope resource not found: %s", grantScope)
|
||||
}
|
||||
|
||||
scopeId = scope.Primary.ID
|
||||
if scopeId == "" {
|
||||
return fmt.Errorf("role resource ID is not set")
|
||||
}
|
||||
}
|
||||
|
||||
md := testProvider.Meta().(*metaData)
|
||||
rolesClient := roles.NewClient(md.client)
|
||||
|
||||
rr, err := rolesClient.Read(context.Background(), roleId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Got an error when reading role %q: %v", roleId, err)
|
||||
}
|
||||
|
||||
if rr.Item.GrantScopeId != scopeId {
|
||||
return fmt.Errorf("grant scope id in state is %s but in boundary is %s", scopeId, rr.Item.GrantScopeId)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckRoleResourceGrantScopesSet(testProvider *schema.Provider, name string, grantScopeIds []string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
|
||||
@@ -32,6 +32,7 @@ const (
|
||||
|
||||
targetTypeTcp = "tcp"
|
||||
targetTypeSsh = "ssh"
|
||||
targetTypeRdp = "rdp"
|
||||
)
|
||||
|
||||
func resourceTarget() *schema.Resource {
|
||||
@@ -193,7 +194,7 @@ func setFromTargetResponseMap(d *schema.ResourceData, raw map[string]interface{}
|
||||
typeStr := raw["type"].(string)
|
||||
|
||||
switch typeStr {
|
||||
case targetTypeTcp, targetTypeSsh:
|
||||
case targetTypeTcp, targetTypeSsh, targetTypeRdp:
|
||||
if attrsVal, ok := raw["attributes"]; ok {
|
||||
attrs := attrsVal.(map[string]interface{})
|
||||
if defPort, ok := attrs[targetDefaultPortKey].(json.Number); ok {
|
||||
@@ -246,7 +247,7 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
|
||||
return diag.Errorf("no type provided")
|
||||
}
|
||||
switch typeStr {
|
||||
case targetTypeTcp, targetTypeSsh:
|
||||
case targetTypeTcp, targetTypeSsh, targetTypeRdp:
|
||||
default:
|
||||
return diag.Errorf("invalid type provided")
|
||||
}
|
||||
@@ -275,6 +276,8 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
|
||||
opts = append(opts, targets.WithTcpTargetDefaultPort(uint32(defaultPortInt)))
|
||||
case targetTypeSsh:
|
||||
opts = append(opts, targets.WithSshTargetDefaultPort(uint32(defaultPortInt)))
|
||||
case targetTypeRdp:
|
||||
opts = append(opts, targets.WithRdpTargetDefaultPort(uint32(defaultPortInt)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,19 +292,27 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
|
||||
opts = append(opts, targets.WithTcpTargetDefaultClientPort(uint32(defaultClientPortInt)))
|
||||
case targetTypeSsh:
|
||||
opts = append(opts, targets.WithSshTargetDefaultClientPort(uint32(defaultClientPortInt)))
|
||||
case targetTypeRdp:
|
||||
opts = append(opts, targets.WithRdpTargetDefaultClientPort(uint32(defaultClientPortInt)))
|
||||
}
|
||||
}
|
||||
|
||||
enableSessionRecordingVal, ok := d.GetOk(targetEnableSessionRecordingKey)
|
||||
if ok {
|
||||
enableSessionRecordingBool := enableSessionRecordingVal.(bool)
|
||||
opts = append(opts, targets.WithSshTargetEnableSessionRecording(enableSessionRecordingBool))
|
||||
switch typeStr {
|
||||
case targetTypeSsh:
|
||||
opts = append(opts, targets.WithSshTargetEnableSessionRecording(enableSessionRecordingBool))
|
||||
}
|
||||
}
|
||||
|
||||
storageBucketIdVal, ok := d.GetOk(targetStorageBucketIdKey)
|
||||
if ok {
|
||||
storageBucketIdStr := storageBucketIdVal.(string)
|
||||
opts = append(opts, targets.WithSshTargetStorageBucketId(storageBucketIdStr))
|
||||
switch typeStr {
|
||||
case targetTypeSsh:
|
||||
opts = append(opts, targets.WithSshTargetStorageBucketId(storageBucketIdStr))
|
||||
}
|
||||
}
|
||||
|
||||
sessionMaxSecondsVal, ok := d.GetOk(targetSessionMaxSecondsKey)
|
||||
@@ -456,7 +467,7 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
|
||||
typeStr = typeVal.(string)
|
||||
}
|
||||
switch typeStr {
|
||||
case targetTypeTcp, targetTypeSsh:
|
||||
case targetTypeTcp, targetTypeSsh, targetTypeRdp:
|
||||
default:
|
||||
return diag.Errorf("invalid type provided")
|
||||
}
|
||||
@@ -537,6 +548,18 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
|
||||
defaultPort = &defaultPortInt
|
||||
opts = append(opts, targets.WithSshTargetDefaultPort(uint32(defaultPortInt)))
|
||||
}
|
||||
|
||||
case targetTypeRdp:
|
||||
opts = append(opts, targets.DefaultRdpTargetDefaultPort())
|
||||
defaultPortVal, ok := d.GetOk(targetDefaultPortKey)
|
||||
if ok {
|
||||
defaultPortInt := defaultPortVal.(int)
|
||||
if defaultPortInt <= 0 || defaultPortInt > math.MaxUint16 {
|
||||
return diag.Errorf(`"default_port" must be a valid tcp port`)
|
||||
}
|
||||
defaultPort = &defaultPortInt
|
||||
opts = append(opts, targets.WithRdpTargetDefaultPort(uint32(defaultPortInt)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,6 +589,18 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
|
||||
defaultClientPort = &defaultClientPortInt
|
||||
opts = append(opts, targets.WithSshTargetDefaultClientPort(uint32(defaultClientPortInt)))
|
||||
}
|
||||
|
||||
case targetTypeRdp:
|
||||
opts = append(opts, targets.DefaultRdpTargetDefaultClientPort())
|
||||
defaultClientPortVal, ok := d.GetOk(targetDefaultClientPortKey)
|
||||
if ok {
|
||||
defaultClientPortInt := defaultClientPortVal.(int)
|
||||
if defaultClientPortInt <= 0 || defaultClientPortInt > math.MaxUint16 {
|
||||
return diag.Errorf(`"default_client_port" must be a valid tcp port`)
|
||||
}
|
||||
defaultClientPort = &defaultClientPortInt
|
||||
opts = append(opts, targets.WithRdpTargetDefaultClientPort(uint32(defaultClientPortInt)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,45 @@
|
||||
module github.com/hashicorp/boundary/plugins/kms/mains/alicloudkms
|
||||
|
||||
go 1.17
|
||||
go 1.23.9
|
||||
|
||||
require (
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/alicloudkms/v2 v2.0.1
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.8
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/alicloudkms/v2 v2.0.4
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1499 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fatih/color v1.7.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/hashicorp/go-hclog v1.1.0 // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.3 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
|
||||
github.com/hashicorp/go-hclog v1.5.0 // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.19 // indirect
|
||||
github.com/hashicorp/go-plugin v1.5.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.6 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.9 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/oklog/run v1.0.0 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.8.1 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||
google.golang.org/grpc v1.56.3 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect
|
||||
google.golang.org/grpc v1.61.0 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,40 +1,46 @@
|
||||
module github.com/hashicorp/boundary/plugins/kms/mains/awskms
|
||||
|
||||
go 1.20
|
||||
go 1.23.9
|
||||
|
||||
require (
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2 v2.0.0
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.8
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2 v2.0.11
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go v1.43.8 // indirect
|
||||
github.com/aws/aws-sdk-go v1.55.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fatih/color v1.7.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.1.0 // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0 // indirect
|
||||
github.com/hashicorp/go-hclog v1.5.0 // indirect
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.19 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-plugin v1.4.3 // indirect
|
||||
github.com/hashicorp/go-plugin v1.5.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
||||
github.com/hashicorp/go-sockaddr v1.0.6 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||
github.com/oklog/run v1.0.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.8.1 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||
google.golang.org/grpc v1.56.3 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.11.1 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect
|
||||
google.golang.org/grpc v1.61.0 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
@@ -1,58 +1,58 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.43.8 h1:8a/M9C4l5CxFNM6IuNx4F1p+ITJEX12VxWxUQo61cbc=
|
||||
github.com/aws/aws-sdk-go v1.43.8/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
|
||||
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
|
||||
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw=
|
||||
github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0 h1:8qUXiUcayCr1RxMzS/D0DK1TPFTlpP8z3cWSR3BUf8E=
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0/go.mod h1:bmYifnHykiAB5yR+FK9fNjvE0GzE1Ev2F4eMTVourcA=
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0 h1:hKWzjzqfUi1HtpBEJ9tLKlRya1u6kRQGZAW9OFR+ia8=
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0/go.mod h1:H+TfVXu/Eyi6Ccs4EoT8pa3gR5lRh12sw4AOq6XkXCg=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2 v2.0.0 h1:RnTa2yQXHPP7CocgTAciNXcn5OG4wsqqENlMuUTXl74=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2 v2.0.0/go.mod h1:3D5UB9fjot4oUTYGQ5gGmhLJKreyLZeI0XB+NxcLTKs=
|
||||
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
|
||||
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.8 h1:/GIUjn9GkFXMk/8/irRdbdtmx8CcyeyWdVy/E5LvzyA=
|
||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.8/go.mod h1:JDc9UOD4EVRDIwPVethJcT5Ibi/Nas6eQDPtA60iwP0=
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.19 h1:FX7HrkfkYomf4SlMrwzOP32FXuFltq34Qy/gXk1Tp5Y=
|
||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.19/go.mod h1:wpZygQlPUUGt4Klgg+RlCaq/KRe8XinEzqTf7QmvrNo=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2 v2.0.11 h1:J9zGa9SlcOHT3SQTj0Vv3shHo0anWbs58weURGCgChI=
|
||||
github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2 v2.0.11/go.mod h1:iAOCu7/lG5eugg8+k7NVvQt0IpWT8s2Q9wnMtC/guM4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-plugin v1.4.3 h1:DXmvivbWD5qdiBts9TpBC7BYL1Aia5sxbRgQB+v6UZM=
|
||||
github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
|
||||
github.com/hashicorp/go-plugin v1.5.2 h1:aWv8eimFqWlsEiMrYZdPYl+FdHaBJSN4AWwGWfT1G2Y=
|
||||
github.com/hashicorp/go-plugin v1.5.2/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
|
||||
github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 h1:W9WN8p6moV1fjKLkeqEgkAMu5rauy9QeYDAmIaPuuiA=
|
||||
github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6/go.mod h1:MpCPSPGLDILGb4JMm94/mMi3YysIqsXzGCzkEZjcjXg=
|
||||
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
|
||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2 h1:ET4pqyjiGmY09R5y+rSd70J2w45CtbWDNvGqWp/R3Ng=
|
||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.2/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM=
|
||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0=
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=
|
||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
|
||||
github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I=
|
||||
github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
|
||||
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
|
||||
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
@@ -66,98 +66,75 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
|
||||
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
|
||||
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
|
||||
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
Loaded 100 of 113 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user