mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-28 04:10:44 -04:00
Merge branch 'opensource-master' into add-elasticsearch-auth
This commit is contained in:
commit
4ebfba2c2b
106 changed files with 4154 additions and 1689 deletions
1
.circleci/.gitattributes
vendored
Normal file
1
.circleci/.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
config.yml linguist-generated
|
||||
1
.circleci/.gitignore
vendored
Normal file
1
.circleci/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.tmp/
|
||||
47
.circleci/Makefile
Normal file
47
.circleci/Makefile
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
.PHONY: default
|
||||
default: ci-config
|
||||
|
||||
.PHONY: check-circleci-installed
|
||||
check-circleci-installed:
|
||||
@command -v circleci > /dev/null 2>&1 || { \
|
||||
echo "Please install circleci-cli, see https://circleci.com/docs/2.0/local-cli/#installation"; \
|
||||
exit 1; }
|
||||
|
||||
.PHONY: ci-config
|
||||
# ci-config is just an alias for config.yml for now
|
||||
ci-config: config.yml
|
||||
|
||||
CONFIG_SOURCE_DIR := config/
|
||||
CONFIG_SOURCE := $(shell find config/) Makefile
|
||||
OUT := config.yml
|
||||
TMP := .tmp/config.yml.tmp
|
||||
CONFIG_21 := .tmp/config.2.1.tmp
|
||||
|
||||
# Ensure the .tmp dir exists.
|
||||
$(shell [ -d .tmp ] || mkdir .tmp)
|
||||
|
||||
define GEN_CONFIG
|
||||
@circleci config pack $(CONFIG_SOURCE_DIR) > $(CONFIG_21)
|
||||
@echo "### Generated by 'make ci-config' do not manually edit this file." > $@
|
||||
@circleci config process $(CONFIG_21) >> $@
|
||||
endef
|
||||
|
||||
$(OUT): $(CONFIG_SOURCE) check-circleci-installed
|
||||
$(GEN_CONFIG)
|
||||
@echo "$@ updated"
|
||||
|
||||
$(TMP): $(CONFIG_SOURCE) check-circleci-installed
|
||||
$(GEN_CONFIG)
|
||||
|
||||
.PHONY: config-up-to-date
|
||||
config-up-to-date: $(TMP) # Note this must not depend on $(OUT)!
|
||||
@if diff config.yml $<; then \
|
||||
echo "Generated $(OUT) is up to date!"; \
|
||||
else \
|
||||
echo "Generated $(OUT) is out of date, run make ci-config to update."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: ci-verify
|
||||
ci-verify: config-up-to-date
|
||||
@circleci config validate config.yml
|
||||
117
.circleci/README.md
Normal file
117
.circleci/README.md
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# CircleCI config
|
||||
|
||||
This directory contains both the source code (under `./config/`)
|
||||
and the generated single-file `config.yml`
|
||||
which defines the CircleCI workflows for this project.
|
||||
|
||||
The Makefile in this directory generates the `./config.yml`
|
||||
in CircleCI 2.0 syntax,
|
||||
from the tree rooted at `./config/`,
|
||||
which contains files in CircleCI 2.1 syntax.
|
||||
CircleCI supports [generating a single config file from many],
|
||||
using the `$ circleci config pack` command.
|
||||
It also supports [expanding 2.1 syntax to 2.0 syntax]
|
||||
using the `$ circleci config process` command.
|
||||
|
||||
[generating a single config file from many]: https://circleci.com/docs/2.0/local-cli/#packing-a-config
|
||||
[expanding 2.1 syntax to 2.0 syntax]: https://circleci.com/docs/2.0/local-cli/#processing-a-config
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You will need the [CircleCI CLI tool] installed and working,
|
||||
at least version `0.1.5607`.
|
||||
|
||||
```
|
||||
$ circleci version
|
||||
0.1.5607+f705856
|
||||
```
|
||||
|
||||
NOTE: It is recommended to [download this tool directly from GitHub Releases].
|
||||
Do not install it using Homebrew, as this version cannot be easily updated.
|
||||
It is also not recommended to pipe curl to bash (which CircleCI recommend) for security reasons!
|
||||
|
||||
[CircleCI CLI tool]: https://circleci.com/docs/2.0/local-cli/
|
||||
[download this tool directly from GitHub Releases]: https://github.com/CircleCI-Public/circleci-cli/releases
|
||||
|
||||
## How to make changes
|
||||
|
||||
Before making changes, be sure to understand the layout
|
||||
of the `./config/` file tree, as well as circleci 2.1 syntax.
|
||||
See the [Syntax and layout] section below.
|
||||
|
||||
To update the config, you should edit, add or remove files
|
||||
in the `./config/` directory,
|
||||
and then run `make ci-config`.
|
||||
If that's successful,
|
||||
you should then commit every `*.yml` file in the tree rooted in this directory.
|
||||
That is: you should commit both the source under `./config/`
|
||||
and the generated file `./config.yml` at the same time, in the same commit.
|
||||
Do not edit the `./config.yml` file directly, as you will lose your changes
|
||||
next time `make ci-config` is run.
|
||||
|
||||
[Syntax and layout]: #syntax-and-layout
|
||||
|
||||
### Verifying `./config.yml`
|
||||
|
||||
To check whether or not the current `./config.yml` is up to date with the source,
|
||||
and whether it is valid, run `$ make ci-verify`.
|
||||
Note that `$ make ci-verify` should be run in CI,
|
||||
as well as by a local git commit hook,
|
||||
to ensure we never commit files that are invalid or out of date.
|
||||
|
||||
#### Example shell session
|
||||
|
||||
```sh
|
||||
$ make ci-config
|
||||
config.yml updated
|
||||
$ git add -A . # The -A makes sure to include deletions/renames etc.
|
||||
$ git commit -m "ci: blah blah blah"
|
||||
Changes detected in .circleci/, running 'make -C .circleci ci-verify'
|
||||
--> Generated config.yml is up to date!
|
||||
--> Config file at config.yml is valid.
|
||||
```
|
||||
|
||||
### Syntax and layout
|
||||
|
||||
It is important to understand the layout of the config directory.
|
||||
Read the documentation on [packing a config] for a full understanding
|
||||
of how multiple YAML files are merged by the circleci CLI tool.
|
||||
|
||||
[packing a config]: https://circleci.com/docs/2.0/local-cli/#packing-a-config
|
||||
|
||||
Here is an example file tree (with comments added afterwards):
|
||||
|
||||
```sh
|
||||
$ tree .
|
||||
.
|
||||
├── Makefile
|
||||
├── README.md # This file.
|
||||
├── config # The source code for config.yml is rooted here.
|
||||
│ ├── @config.yml # Files beginning with @ are treated specially by `circleci config pack`
|
||||
│ ├── commands # Subdirectories of config become top-level keys.
|
||||
│ │ └── go_test.yml # Filenames (minus .yml) become top-level keys under their parent (in this case "commands").
|
||||
│ │ # The contents of go_test.yml therefore are placed at: .commands.go_test:
|
||||
│ └── jobs # jobs also becomes a top-level key under config...
|
||||
│ ├── build-go-dev.yml # ...and likewise filenames become keys under their parent.
|
||||
│ ├── go-mod-download.yml
|
||||
│ ├── install-ui-dependencies.yml
|
||||
│ ├── test-go-race.yml
|
||||
│ ├── test-go.yml
|
||||
│ └── test-ui.yml
|
||||
└── config.yml # The generated file in 2.0 syntax.
|
||||
```
|
||||
|
||||
About those `@` files... Preceding a filename with `@`
|
||||
indicates to `$ circleci config pack` that the contents of this YAML file
|
||||
should be at the top-level, rather than underneath a key named after their filename.
|
||||
This naming convention is unfortunate as it breaks autocompletion in bash,
|
||||
but there we go.
|
||||
|
||||
### Why not just use YAML references?
|
||||
|
||||
YAML references only work within a single file,
|
||||
this is because `circleci config pack` is not a text-level packer,
|
||||
but rather stitches together the structures defined in each YAML
|
||||
file according to certain rules.
|
||||
Therefore it must parse each file separately,
|
||||
and YAML references are handled by the parser.
|
||||
661
.circleci/config.yml
generated
661
.circleci/config.yml
generated
|
|
@ -1,228 +1,511 @@
|
|||
### Generated by 'make ci-config' do not manually edit this file.
|
||||
version: 2
|
||||
|
||||
references:
|
||||
images:
|
||||
go: &GOLANG_IMAGE golang:1.12.4-stretch # Pin Go to patch version (ex: 1.2.3)
|
||||
node: &NODE_IMAGE node:10-stretch # Pin Node.js to major version (ex: 10)
|
||||
|
||||
environment: &ENVIRONMENT
|
||||
CIRCLECI_CLI_VERSION: 0.1.5546 # Pin CircleCI CLI to patch version (ex: 1.2.3)
|
||||
GO_VERSION: 1.12.4 # Pin Go to patch version (ex: 1.2.3)
|
||||
GOTESTSUM_VERSION: 0.3.3 # Pin gotestsum to patch version (ex: 1.2.3)
|
||||
|
||||
cache:
|
||||
go-sum: &GO_SUM_CACHE_KEY go-sum-v1-{{ checksum "go.sum" }}
|
||||
yarn-lock: &YARN_LOCK_CACHE_KEY yarn-lock-v1-{{ checksum "ui/yarn.lock" }}
|
||||
|
||||
jobs:
|
||||
install-ui-dependencies:
|
||||
docker:
|
||||
- image: *NODE_IMAGE
|
||||
- image: node:10-stretch
|
||||
working_directory: /src
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: *YARN_LOCK_CACHE_KEY
|
||||
- run:
|
||||
name: Install UI dependencies
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
cd ui
|
||||
yarn install --ignore-optional
|
||||
npm rebuild node-sass
|
||||
- save_cache:
|
||||
key: *YARN_LOCK_CACHE_KEY
|
||||
paths:
|
||||
- ui/node_modules
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: yarn-lock-v1-{{ checksum "ui/yarn.lock" }}
|
||||
- run:
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
cd ui
|
||||
yarn install --ignore-optional
|
||||
npm rebuild node-sass
|
||||
name: Install UI dependencies
|
||||
- save_cache:
|
||||
key: yarn-lock-v1-{{ checksum "ui/yarn.lock" }}
|
||||
paths:
|
||||
- ui/node_modules
|
||||
go-mod-download:
|
||||
docker:
|
||||
- image: *GOLANG_IMAGE
|
||||
- image: golang:1.12.4-stretch
|
||||
working_directory: /src
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: *GO_SUM_CACHE_KEY
|
||||
- run:
|
||||
name: Download Go modules
|
||||
command: go mod download
|
||||
- run:
|
||||
name: Verify checksums of Go modules
|
||||
command: go mod verify
|
||||
- save_cache:
|
||||
key: *GO_SUM_CACHE_KEY
|
||||
paths:
|
||||
- /go/pkg/mod
|
||||
|
||||
- add_ssh_keys:
|
||||
fingerprints:
|
||||
- c6:96:98:82:dc:04:6c:39:dd:ac:83:05:e3:15:1c:98
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: go-sum-v1-{{ checksum "go.sum" }}
|
||||
- run:
|
||||
command: go mod download
|
||||
name: Download Go modules
|
||||
- run:
|
||||
command: go mod verify
|
||||
name: Verify checksums of Go modules
|
||||
- save_cache:
|
||||
key: go-sum-v1-{{ checksum "go.sum" }}
|
||||
paths:
|
||||
- /go/pkg/mod
|
||||
build-go-dev:
|
||||
docker:
|
||||
- image: *GOLANG_IMAGE
|
||||
- image: golang:1.12.4-stretch
|
||||
working_directory: /src
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: *GO_SUM_CACHE_KEY
|
||||
- run:
|
||||
name: Build dev binary
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: go-sum-v1-{{ checksum "go.sum" }}
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
# Move dev UI assets to expected location
|
||||
rm -rf ./pkg
|
||||
mkdir ./pkg
|
||||
|
||||
# Build dev binary
|
||||
make bootstrap dev
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- bin
|
||||
# Move dev UI assets to expected location
|
||||
rm -rf ./pkg
|
||||
mkdir ./pkg
|
||||
|
||||
# Build dev binary
|
||||
make bootstrap dev
|
||||
name: Build dev binary
|
||||
- persist_to_workspace:
|
||||
paths:
|
||||
- bin
|
||||
root: .
|
||||
test-ui:
|
||||
docker:
|
||||
- image: *NODE_IMAGE
|
||||
- image: node:10-stretch
|
||||
working_directory: /src
|
||||
resource_class: medium+
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: *YARN_LOCK_CACHE_KEY
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Test UI
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: yarn-lock-v1-{{ checksum "ui/yarn.lock" }}
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
# Install Chrome
|
||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub \
|
||||
| apt-key add -
|
||||
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" \
|
||||
| tee /etc/apt/sources.list.d/google-chrome.list
|
||||
apt-get update
|
||||
apt-get -y install google-chrome-stable
|
||||
rm /etc/apt/sources.list.d/google-chrome.list
|
||||
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
# Install Chrome
|
||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub \
|
||||
| apt-key add -
|
||||
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" \
|
||||
| tee /etc/apt/sources.list.d/google-chrome.list
|
||||
apt-get update
|
||||
apt-get -y install google-chrome-stable
|
||||
rm /etc/apt/sources.list.d/google-chrome.list
|
||||
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
# Add ./bin to the PATH so vault binary can be run by Ember tests
|
||||
export PATH="${PWD}"/bin:${PATH}
|
||||
|
||||
# Run Ember tests
|
||||
cd ui
|
||||
mkdir -p test-results/qunit
|
||||
yarn run test-oss
|
||||
- store_artifacts:
|
||||
path: ui/test-results
|
||||
- store_test_results:
|
||||
path: ui/test-results
|
||||
|
||||
test-ui-browserstack:
|
||||
docker:
|
||||
- image: *NODE_IMAGE
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: *YARN_LOCK_CACHE_KEY
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Run BrowserStack tests
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
# Add ./bin to the PATH so vault binary can be run by Ember tests
|
||||
export PATH="${PWD}"/bin:${PATH}
|
||||
|
||||
make test-ui-browserstack
|
||||
# Add ./bin to the PATH so vault binary can be run by Ember tests
|
||||
export PATH="${PWD}/bin:${PATH}"
|
||||
|
||||
# Run Ember tests
|
||||
cd ui
|
||||
mkdir -p test-results/qunit
|
||||
yarn run test-oss
|
||||
name: Test UI
|
||||
- store_artifacts:
|
||||
path: ui/test-results
|
||||
- store_test_results:
|
||||
path: ui/test-results
|
||||
test-go:
|
||||
machine: true
|
||||
environment:
|
||||
<<: *ENVIRONMENT
|
||||
GO_TAGS:
|
||||
working_directory: ~/src
|
||||
parallelism: 2
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
sudo mkdir /go
|
||||
sudo chown -R circleci:circleci /go
|
||||
name: Allow circleci user to restore Go modules cache
|
||||
- restore_cache:
|
||||
key: go-sum-v1-{{ checksum "go.sum" }}
|
||||
- run:
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
# Install Go
|
||||
curl -sSLO "https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
sudo rm -rf /usr/local/go
|
||||
sudo tar -C /usr/local -xzf "go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
rm -f "go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
export GOPATH=/go
|
||||
export PATH="${PATH}:${GOPATH}/bin:/usr/local/go/bin"
|
||||
|
||||
# Install CircleCI CLI
|
||||
curl -sSL \
|
||||
"https://github.com/CircleCI-Public/circleci-cli/releases/download/v${CIRCLECI_CLI_VERSION}/circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64.tar.gz" \
|
||||
| sudo tar --overwrite -xz \
|
||||
-C /usr/local/bin \
|
||||
"circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64/circleci"
|
||||
|
||||
# Split Go tests by prior test times
|
||||
package_names=$(go list \
|
||||
-tags "${GO_TAGS}" \
|
||||
./... \
|
||||
| grep -v /integ \
|
||||
| grep -v /vendor/ \
|
||||
| sort \
|
||||
| circleci tests split --split-by=timings --timings-type=classname)
|
||||
|
||||
# Install gotestsum
|
||||
curl -sSL "https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_linux_amd64.tar.gz" \
|
||||
| sudo tar --overwrite -xz -C /usr/local/bin gotestsum
|
||||
|
||||
# Run tests
|
||||
make prep
|
||||
mkdir -p test-results/go-test
|
||||
CGO_ENABLED= \
|
||||
VAULT_ADDR= \
|
||||
VAULT_TOKEN= \
|
||||
VAULT_DEV_ROOT_TOKEN_ID= \
|
||||
VAULT_ACC= \
|
||||
gotestsum --format=short-verbose --junitfile test-results/go-test/results.xml -- \
|
||||
-tags "${GO_TAGS}" \
|
||||
-timeout=40m \
|
||||
-parallel=20 \
|
||||
\
|
||||
${package_names}
|
||||
name: Run Go tests
|
||||
no_output_timeout: 20m
|
||||
- store_artifacts:
|
||||
path: test-results
|
||||
- store_test_results:
|
||||
path: test-results
|
||||
environment:
|
||||
- CIRCLECI_CLI_VERSION: 0.1.5546
|
||||
- GO_TAGS: null
|
||||
- GO_VERSION: 1.12.4
|
||||
- GOTESTSUM_VERSION: 0.3.3
|
||||
test-go-race:
|
||||
machine: true
|
||||
working_directory: ~/src
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Allow circleci user to restore Go modules cache
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
sudo mkdir /go
|
||||
sudo chown -R circleci:circleci /go
|
||||
- restore_cache:
|
||||
key: *GO_SUM_CACHE_KEY
|
||||
- run:
|
||||
name: Run Go tests
|
||||
no_output_timeout: 20m
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
sudo mkdir /go
|
||||
sudo chown -R circleci:circleci /go
|
||||
name: Allow circleci user to restore Go modules cache
|
||||
- restore_cache:
|
||||
key: go-sum-v1-{{ checksum "go.sum" }}
|
||||
- run:
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
# Install Go
|
||||
curl -sSLO "https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
sudo rm -rf /usr/local/go
|
||||
sudo tar -C /usr/local -xzf "go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
rm -f "go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
export GOPATH=/go
|
||||
export PATH="${PATH}:${GOPATH}/bin:/usr/local/go/bin"
|
||||
# Install Go
|
||||
curl -sSLO "https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
sudo rm -rf /usr/local/go
|
||||
sudo tar -C /usr/local -xzf "go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
rm -f "go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
export GOPATH=/go
|
||||
export PATH="${PATH}:${GOPATH}/bin:/usr/local/go/bin"
|
||||
|
||||
# Install CircleCI CLI
|
||||
curl -sSL \
|
||||
"https://github.com/CircleCI-Public/circleci-cli/releases/download/v${CIRCLECI_CLI_VERSION}/circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64.tar.gz" \
|
||||
| sudo tar --overwrite -xz \
|
||||
-C /usr/local/bin \
|
||||
"circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64/circleci"
|
||||
# Install CircleCI CLI
|
||||
curl -sSL \
|
||||
"https://github.com/CircleCI-Public/circleci-cli/releases/download/v${CIRCLECI_CLI_VERSION}/circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64.tar.gz" \
|
||||
| sudo tar --overwrite -xz \
|
||||
-C /usr/local/bin \
|
||||
"circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64/circleci"
|
||||
|
||||
# Split Go tests by prior test times
|
||||
package_names=$(go list \
|
||||
-tags "${GO_TAGS}" \
|
||||
./... \
|
||||
| grep -v /vendor/ \
|
||||
| sort \
|
||||
| circleci tests split --split-by=timings --timings-type=classname)
|
||||
# Split Go tests by prior test times
|
||||
package_names=$(go list \
|
||||
-tags "${GO_TAGS}" \
|
||||
./... \
|
||||
| grep -v /integ \
|
||||
| grep -v /vendor/ \
|
||||
| sort \
|
||||
| circleci tests split --split-by=timings --timings-type=classname)
|
||||
|
||||
# Install gotestsum
|
||||
curl -sSL "https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_linux_amd64.tar.gz" \
|
||||
| sudo tar --overwrite -xz -C /usr/local/bin gotestsum
|
||||
|
||||
# Run tests
|
||||
make prep
|
||||
mkdir -p test-results/go-test
|
||||
CGO_ENABLED= \
|
||||
VAULT_ADDR= \
|
||||
VAULT_TOKEN= \
|
||||
VAULT_DEV_ROOT_TOKEN_ID= \
|
||||
VAULT_ACC= \
|
||||
gotestsum --format=short-verbose --junitfile test-results/go-test/results.xml -- \
|
||||
-tags "${GO_TAGS}" \
|
||||
-timeout=40m \
|
||||
-parallel=20 \
|
||||
${package_names}
|
||||
- store_artifacts:
|
||||
path: test-results
|
||||
- store_test_results:
|
||||
path: test-results
|
||||
# Install gotestsum
|
||||
curl -sSL "https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_linux_amd64.tar.gz" \
|
||||
| sudo tar --overwrite -xz -C /usr/local/bin gotestsum
|
||||
|
||||
# Run tests
|
||||
make prep
|
||||
mkdir -p test-results/go-test
|
||||
CGO_ENABLED= \
|
||||
VAULT_ADDR= \
|
||||
VAULT_TOKEN= \
|
||||
VAULT_DEV_ROOT_TOKEN_ID= \
|
||||
VAULT_ACC= \
|
||||
gotestsum --format=short-verbose --junitfile test-results/go-test/results.xml -- \
|
||||
-tags "${GO_TAGS}" \
|
||||
-timeout=40m \
|
||||
-parallel=20 \
|
||||
-race \
|
||||
${package_names}
|
||||
name: Run Go tests
|
||||
no_output_timeout: 20m
|
||||
- store_artifacts:
|
||||
path: test-results
|
||||
- store_test_results:
|
||||
path: test-results
|
||||
environment:
|
||||
- CIRCLECI_CLI_VERSION: 0.1.5546
|
||||
- GO_TAGS: null
|
||||
- GO_VERSION: 1.12.4
|
||||
- GOTESTSUM_VERSION: 0.3.3
|
||||
workflows:
|
||||
version: 2
|
||||
|
||||
ci:
|
||||
jobs:
|
||||
- install-ui-dependencies
|
||||
- go-mod-download
|
||||
- build-go-dev:
|
||||
requires:
|
||||
- go-mod-download
|
||||
- test-ui:
|
||||
requires:
|
||||
- install-ui-dependencies
|
||||
- build-go-dev
|
||||
- test-go:
|
||||
requires:
|
||||
- build-go-dev
|
||||
- test-ui-browserstack:
|
||||
requires:
|
||||
- install-ui-dependencies
|
||||
- build-go-dev
|
||||
- install-ui-dependencies
|
||||
- go-mod-download
|
||||
- build-go-dev:
|
||||
requires:
|
||||
- go-mod-download
|
||||
- test-ui:
|
||||
requires:
|
||||
- install-ui-dependencies
|
||||
- build-go-dev
|
||||
- test-go:
|
||||
requires:
|
||||
- build-go-dev
|
||||
- test-go-race:
|
||||
requires:
|
||||
- build-go-dev
|
||||
version: 2
|
||||
|
||||
# Original config.yml file:
|
||||
# commands:
|
||||
# go_test:
|
||||
# description: run go tests
|
||||
# parameters:
|
||||
# extra_flags:
|
||||
# default: \"\"
|
||||
# type: string
|
||||
# steps:
|
||||
# - run:
|
||||
# command: |
|
||||
# set -eux -o pipefail
|
||||
#
|
||||
# # Install Go
|
||||
# curl -sSLO \"https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz\"
|
||||
# sudo rm -rf /usr/local/go
|
||||
# sudo tar -C /usr/local -xzf \"go${GO_VERSION}.linux-amd64.tar.gz\"
|
||||
# rm -f \"go${GO_VERSION}.linux-amd64.tar.gz\"
|
||||
# export GOPATH=/go
|
||||
# export PATH=\"${PATH}:${GOPATH}/bin:/usr/local/go/bin\"
|
||||
#
|
||||
# # Install CircleCI CLI
|
||||
# curl -sSL \\
|
||||
# \"https://github.com/CircleCI-Public/circleci-cli/releases/download/v${CIRCLECI_CLI_VERSION}/circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64.tar.gz\" \\
|
||||
# | sudo tar --overwrite -xz \\
|
||||
# -C /usr/local/bin \\
|
||||
# \"circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64/circleci\"
|
||||
#
|
||||
# # Split Go tests by prior test times
|
||||
# package_names=$(go list \\
|
||||
# -tags \"${GO_TAGS}\" \\
|
||||
# ./... \\
|
||||
# | grep -v /integ \\
|
||||
# | grep -v /vendor/ \\
|
||||
# | sort \\
|
||||
# | circleci tests split --split-by=timings --timings-type=classname)
|
||||
#
|
||||
# # Install gotestsum
|
||||
# curl -sSL \"https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_linux_amd64.tar.gz\" \\
|
||||
# | sudo tar --overwrite -xz -C /usr/local/bin gotestsum
|
||||
#
|
||||
# # Run tests
|
||||
# make prep
|
||||
# mkdir -p test-results/go-test
|
||||
# CGO_ENABLED= \\
|
||||
# VAULT_ADDR= \\
|
||||
# VAULT_TOKEN= \\
|
||||
# VAULT_DEV_ROOT_TOKEN_ID= \\
|
||||
# VAULT_ACC= \\
|
||||
# gotestsum --format=short-verbose --junitfile test-results/go-test/results.xml -- \\
|
||||
# -tags \"${GO_TAGS}\" \\
|
||||
# -timeout=40m \\
|
||||
# -parallel=20 \\
|
||||
# << parameters.extra_flags >> \\
|
||||
# ${package_names}
|
||||
# name: Run Go tests
|
||||
# no_output_timeout: 20m
|
||||
# restore_go_cache:
|
||||
# steps:
|
||||
# - restore_cache:
|
||||
# key: go-sum-v1-{{ checksum \"go.sum\" }}
|
||||
# restore_yarn_cache:
|
||||
# steps:
|
||||
# - restore_cache:
|
||||
# key: yarn-lock-v1-{{ checksum \"ui/yarn.lock\" }}
|
||||
# save_go_cache:
|
||||
# steps:
|
||||
# - save_cache:
|
||||
# key: go-sum-v1-{{ checksum \"go.sum\" }}
|
||||
# paths:
|
||||
# - /go/pkg/mod
|
||||
# save_yarn_cache:
|
||||
# steps:
|
||||
# - save_cache:
|
||||
# key: yarn-lock-v1-{{ checksum \"ui/yarn.lock\" }}
|
||||
# paths:
|
||||
# - ui/node_modules
|
||||
# executors:
|
||||
# go:
|
||||
# docker:
|
||||
# - image: golang:1.12.4-stretch
|
||||
# working_directory: /src
|
||||
# go-machine:
|
||||
# environment:
|
||||
# CIRCLECI_CLI_VERSION: 0.1.5546
|
||||
# GO_TAGS: null
|
||||
# GO_VERSION: 1.12.4
|
||||
# GOTESTSUM_VERSION: 0.3.3
|
||||
# machine: true
|
||||
# working_directory: ~/src
|
||||
# node:
|
||||
# docker:
|
||||
# - image: node:10-stretch
|
||||
# working_directory: /src
|
||||
# jobs:
|
||||
# build-go-dev:
|
||||
# executor: go
|
||||
# steps:
|
||||
# - checkout
|
||||
# - restore_go_cache
|
||||
# - attach_workspace:
|
||||
# at: .
|
||||
# - run:
|
||||
# command: |
|
||||
# set -eux -o pipefail
|
||||
#
|
||||
# # Move dev UI assets to expected location
|
||||
# rm -rf ./pkg
|
||||
# mkdir ./pkg
|
||||
#
|
||||
# # Build dev binary
|
||||
# make bootstrap dev
|
||||
# name: Build dev binary
|
||||
# - persist_to_workspace:
|
||||
# paths:
|
||||
# - bin
|
||||
# root: .
|
||||
# go-mod-download:
|
||||
# executor: go
|
||||
# steps:
|
||||
# - add_ssh_keys:
|
||||
# fingerprints:
|
||||
# - c6:96:98:82:dc:04:6c:39:dd:ac:83:05:e3:15:1c:98
|
||||
# - checkout
|
||||
# - restore_go_cache
|
||||
# - run:
|
||||
# command: go mod download
|
||||
# name: Download Go modules
|
||||
# - run:
|
||||
# command: go mod verify
|
||||
# name: Verify checksums of Go modules
|
||||
# - save_go_cache
|
||||
# install-ui-dependencies:
|
||||
# executor: node
|
||||
# steps:
|
||||
# - checkout
|
||||
# - restore_yarn_cache
|
||||
# - run:
|
||||
# command: |
|
||||
# set -eux -o pipefail
|
||||
#
|
||||
# cd ui
|
||||
# yarn install --ignore-optional
|
||||
# npm rebuild node-sass
|
||||
# name: Install UI dependencies
|
||||
# - save_yarn_cache
|
||||
# test-go:
|
||||
# executor: go-machine
|
||||
# parallelism: 2
|
||||
# steps:
|
||||
# - checkout
|
||||
# - run:
|
||||
# command: |
|
||||
# set -eux -o pipefail
|
||||
#
|
||||
# sudo mkdir /go
|
||||
# sudo chown -R circleci:circleci /go
|
||||
# name: Allow circleci user to restore Go modules cache
|
||||
# - restore_go_cache
|
||||
# - go_test
|
||||
# - store_artifacts:
|
||||
# path: test-results
|
||||
# - store_test_results:
|
||||
# path: test-results
|
||||
# test-go-race:
|
||||
# executor: go-machine
|
||||
# steps:
|
||||
# - checkout
|
||||
# - run:
|
||||
# command: |
|
||||
# set -eux -o pipefail
|
||||
#
|
||||
# sudo mkdir /go
|
||||
# sudo chown -R circleci:circleci /go
|
||||
# name: Allow circleci user to restore Go modules cache
|
||||
# - restore_go_cache
|
||||
# - go_test:
|
||||
# extra_flags: -race
|
||||
# - store_artifacts:
|
||||
# path: test-results
|
||||
# - store_test_results:
|
||||
# path: test-results
|
||||
# test-ui:
|
||||
# executor: node
|
||||
# resource_class: medium+
|
||||
# steps:
|
||||
# - checkout
|
||||
# - restore_yarn_cache
|
||||
# - attach_workspace:
|
||||
# at: .
|
||||
# - run:
|
||||
# command: |
|
||||
# set -eux -o pipefail
|
||||
#
|
||||
# # Install Chrome
|
||||
# wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub \\
|
||||
# | apt-key add -
|
||||
# echo \"deb http://dl.google.com/linux/chrome/deb/ stable main\" \\
|
||||
# | tee /etc/apt/sources.list.d/google-chrome.list
|
||||
# apt-get update
|
||||
# apt-get -y install google-chrome-stable
|
||||
# rm /etc/apt/sources.list.d/google-chrome.list
|
||||
# rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
#
|
||||
# # Add ./bin to the PATH so vault binary can be run by Ember tests
|
||||
# export PATH=\"${PWD}/bin:${PATH}\"
|
||||
#
|
||||
# # Run Ember tests
|
||||
# cd ui
|
||||
# mkdir -p test-results/qunit
|
||||
# yarn run test-oss
|
||||
# name: Test UI
|
||||
# - store_artifacts:
|
||||
# path: ui/test-results
|
||||
# - store_test_results:
|
||||
# path: ui/test-results
|
||||
# references:
|
||||
# cache:
|
||||
# go-sum: go-sum-v1-{{ checksum \"go.sum\" }}
|
||||
# yarn-lock: yarn-lock-v1-{{ checksum \"ui/yarn.lock\" }}
|
||||
# images:
|
||||
# go: golang:1.12.4-stretch
|
||||
# node: node:10-stretch
|
||||
# version: 2.1
|
||||
# workflows:
|
||||
# ci:
|
||||
# jobs:
|
||||
# - install-ui-dependencies
|
||||
# - go-mod-download
|
||||
# - build-go-dev:
|
||||
# requires:
|
||||
# - go-mod-download
|
||||
# - test-ui:
|
||||
# requires:
|
||||
# - install-ui-dependencies
|
||||
# - build-go-dev
|
||||
# - test-go:
|
||||
# requires:
|
||||
# - build-go-dev
|
||||
# - test-go-race:
|
||||
# requires:
|
||||
# - build-go-dev
|
||||
53
.circleci/config/@config.yml
Normal file
53
.circleci/config/@config.yml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
version: 2.1
|
||||
|
||||
references:
|
||||
images:
|
||||
go: &GOLANG_IMAGE golang:1.12.4-stretch # Pin Go to patch version (ex: 1.2.3)
|
||||
node: &NODE_IMAGE node:10-stretch # Pin Node.js to major version (ex: 10)
|
||||
|
||||
cache:
|
||||
go-sum: &GO_SUM_CACHE_KEY go-sum-v1-{{ checksum "go.sum" }}
|
||||
yarn-lock: &YARN_LOCK_CACHE_KEY yarn-lock-v1-{{ checksum "ui/yarn.lock" }}
|
||||
|
||||
# more commands defined in commands/
|
||||
commands:
|
||||
restore_yarn_cache:
|
||||
steps:
|
||||
- restore_cache:
|
||||
key: *YARN_LOCK_CACHE_KEY
|
||||
save_yarn_cache:
|
||||
steps:
|
||||
- save_cache:
|
||||
key: *YARN_LOCK_CACHE_KEY
|
||||
paths:
|
||||
- ui/node_modules
|
||||
restore_go_cache:
|
||||
steps:
|
||||
- restore_cache:
|
||||
key: *GO_SUM_CACHE_KEY
|
||||
save_go_cache:
|
||||
steps:
|
||||
- save_cache:
|
||||
key: *GO_SUM_CACHE_KEY
|
||||
paths:
|
||||
- /go/pkg/mod
|
||||
|
||||
executors:
|
||||
go:
|
||||
docker:
|
||||
- image: *GOLANG_IMAGE
|
||||
working_directory: /src
|
||||
go-machine:
|
||||
machine: true
|
||||
environment:
|
||||
CIRCLECI_CLI_VERSION: 0.1.5546 # Pin CircleCI CLI to patch version (ex: 1.2.3)
|
||||
GO_VERSION: 1.12.4 # Pin Go to patch version (ex: 1.2.3)
|
||||
GOTESTSUM_VERSION: 0.3.3 # Pin gotestsum to patch version (ex: 1.2.3)
|
||||
GO_TAGS:
|
||||
working_directory: ~/src
|
||||
node:
|
||||
docker:
|
||||
- image: *NODE_IMAGE
|
||||
working_directory: /src
|
||||
|
||||
55
.circleci/config/commands/go_test.yml
Normal file
55
.circleci/config/commands/go_test.yml
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
description: run go tests
|
||||
parameters:
|
||||
extra_flags:
|
||||
type: string
|
||||
default: ""
|
||||
steps:
|
||||
- run:
|
||||
name: Run Go tests
|
||||
no_output_timeout: 20m
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
# Install Go
|
||||
curl -sSLO "https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
sudo rm -rf /usr/local/go
|
||||
sudo tar -C /usr/local -xzf "go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
rm -f "go${GO_VERSION}.linux-amd64.tar.gz"
|
||||
export GOPATH=/go
|
||||
export PATH="${PATH}:${GOPATH}/bin:/usr/local/go/bin"
|
||||
|
||||
# Install CircleCI CLI
|
||||
curl -sSL \
|
||||
"https://github.com/CircleCI-Public/circleci-cli/releases/download/v${CIRCLECI_CLI_VERSION}/circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64.tar.gz" \
|
||||
| sudo tar --overwrite -xz \
|
||||
-C /usr/local/bin \
|
||||
"circleci-cli_${CIRCLECI_CLI_VERSION}_linux_amd64/circleci"
|
||||
|
||||
# Split Go tests by prior test times
|
||||
package_names=$(go list \
|
||||
-tags "${GO_TAGS}" \
|
||||
./... \
|
||||
| grep -v /integ \
|
||||
| grep -v /vendor/ \
|
||||
| sort \
|
||||
| circleci tests split --split-by=timings --timings-type=classname)
|
||||
|
||||
# Install gotestsum
|
||||
curl -sSL "https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_linux_amd64.tar.gz" \
|
||||
| sudo tar --overwrite -xz -C /usr/local/bin gotestsum
|
||||
|
||||
# Run tests
|
||||
make prep
|
||||
mkdir -p test-results/go-test
|
||||
CGO_ENABLED= \
|
||||
VAULT_ADDR= \
|
||||
VAULT_TOKEN= \
|
||||
VAULT_DEV_ROOT_TOKEN_ID= \
|
||||
VAULT_ACC= \
|
||||
gotestsum --format=short-verbose --junitfile test-results/go-test/results.xml -- \
|
||||
-tags "${GO_TAGS}" \
|
||||
-timeout=40m \
|
||||
-parallel=20 \
|
||||
<< parameters.extra_flags >> \
|
||||
${package_names}
|
||||
|
||||
21
.circleci/config/jobs/build-go-dev.yml
Normal file
21
.circleci/config/jobs/build-go-dev.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
executor: go
|
||||
steps:
|
||||
- checkout
|
||||
- restore_go_cache
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Build dev binary
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
# Move dev UI assets to expected location
|
||||
rm -rf ./pkg
|
||||
mkdir ./pkg
|
||||
|
||||
# Build dev binary
|
||||
make bootstrap dev
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- bin
|
||||
15
.circleci/config/jobs/go-mod-download.yml
Normal file
15
.circleci/config/jobs/go-mod-download.yml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
executor: go
|
||||
steps:
|
||||
- add_ssh_keys:
|
||||
fingerprints:
|
||||
# "CircleCI SSH Checkout" SSH key associated with hashicorp-ci GitHub user
|
||||
- "c6:96:98:82:dc:04:6c:39:dd:ac:83:05:e3:15:1c:98"
|
||||
- checkout
|
||||
- restore_go_cache
|
||||
- run:
|
||||
name: Download Go modules
|
||||
command: go mod download
|
||||
- run:
|
||||
name: Verify checksums of Go modules
|
||||
command: go mod verify
|
||||
- save_go_cache
|
||||
13
.circleci/config/jobs/install-ui-dependencies.yml
Normal file
13
.circleci/config/jobs/install-ui-dependencies.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
executor: node
|
||||
steps:
|
||||
- checkout
|
||||
- restore_yarn_cache
|
||||
- run:
|
||||
name: Install UI dependencies
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
cd ui
|
||||
yarn install --ignore-optional
|
||||
npm rebuild node-sass
|
||||
- save_yarn_cache
|
||||
17
.circleci/config/jobs/test-go-race.yml
Normal file
17
.circleci/config/jobs/test-go-race.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
executor: go-machine
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Allow circleci user to restore Go modules cache
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
sudo mkdir /go
|
||||
sudo chown -R circleci:circleci /go
|
||||
- restore_go_cache
|
||||
- go_test:
|
||||
extra_flags: "-race"
|
||||
- store_artifacts:
|
||||
path: test-results
|
||||
- store_test_results:
|
||||
path: test-results
|
||||
17
.circleci/config/jobs/test-go.yml
Normal file
17
.circleci/config/jobs/test-go.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
executor: go-machine
|
||||
parallelism: 2
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Allow circleci user to restore Go modules cache
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
sudo mkdir /go
|
||||
sudo chown -R circleci:circleci /go
|
||||
- restore_go_cache
|
||||
- go_test
|
||||
- store_artifacts:
|
||||
path: test-results
|
||||
- store_test_results:
|
||||
path: test-results
|
||||
33
.circleci/config/jobs/test-ui.yml
Normal file
33
.circleci/config/jobs/test-ui.yml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
executor: node
|
||||
resource_class: medium+
|
||||
steps:
|
||||
- checkout
|
||||
- restore_yarn_cache
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Test UI
|
||||
command: |
|
||||
set -eux -o pipefail
|
||||
|
||||
# Install Chrome
|
||||
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub \
|
||||
| apt-key add -
|
||||
echo "deb http://dl.google.com/linux/chrome/deb/ stable main" \
|
||||
| tee /etc/apt/sources.list.d/google-chrome.list
|
||||
apt-get update
|
||||
apt-get -y install google-chrome-stable
|
||||
rm /etc/apt/sources.list.d/google-chrome.list
|
||||
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
# Add ./bin to the PATH so vault binary can be run by Ember tests
|
||||
export PATH="${PWD}/bin:${PATH}"
|
||||
|
||||
# Run Ember tests
|
||||
cd ui
|
||||
mkdir -p test-results/qunit
|
||||
yarn run test-oss
|
||||
- store_artifacts:
|
||||
path: ui/test-results
|
||||
- store_test_results:
|
||||
path: ui/test-results
|
||||
16
.circleci/config/workflows/ci.yml
Normal file
16
.circleci/config/workflows/ci.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
jobs:
|
||||
- install-ui-dependencies
|
||||
- go-mod-download
|
||||
- build-go-dev:
|
||||
requires:
|
||||
- go-mod-download
|
||||
- test-ui:
|
||||
requires:
|
||||
- install-ui-dependencies
|
||||
- build-go-dev
|
||||
- test-go:
|
||||
requires:
|
||||
- build-go-dev
|
||||
- test-go-race:
|
||||
requires:
|
||||
- build-go-dev
|
||||
104
.hooks/pre-commit
Executable file
104
.hooks/pre-commit
Executable file
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# READ THIS BEFORE MAKING CHANGES:
|
||||
#
|
||||
# If you want to add a new pre-commit check, here are the rules:
|
||||
#
|
||||
# 1. Create a bash function for your check (see e.g. ui_lint below).
|
||||
# NOTE: Each function will be called in a sub-shell so you can freely
|
||||
# change directory without worrying about interference.
|
||||
# 2. Add the name of the function to the CHECKS variable.
|
||||
# 3. If no changes relevant to your new check are staged, then
|
||||
# do not output anything at all - this would be annoying noise.
|
||||
# In this case, call 'return 0' from your check function to return
|
||||
# early without blocking the commit.
|
||||
# 4. If any non-trivial check-specific thing has to be invoked,
|
||||
# then output '==> [check description]' as the first line of
|
||||
# output. Each sub-check should output '--> [subcheck description]'
|
||||
# after it has run, indicating success or failure.
|
||||
# 5. Call 'block [reason]' to block the commit. This ensures the last
|
||||
# line of output calls out that the commit was blocked - which may not
|
||||
# be obvious from random error messages generated in 4.
|
||||
#
|
||||
# At the moment, there are no automated tests for this hook, so please run it
|
||||
# locally to check you have not broken anything - breaking this will interfere
|
||||
# with other peoples' workflows significantly, so be sure, check everything twice.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Call block to block the commit with a message.
|
||||
block() {
|
||||
echo "$@"
|
||||
echo "Commit blocked - see errors above."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Add all check functions to this space separated list.
|
||||
# They are executed in this order (see end of file).
|
||||
CHECKS="ui_lint circleci_verify"
|
||||
|
||||
# Run ui linter if changes in that dir detected.
|
||||
ui_lint() {
|
||||
local DIR=ui LINTER=node_modules/.bin/lint-staged
|
||||
|
||||
# Silently succeed if no changes staged for $DIR
|
||||
if git diff --name-only --cached --exit-code -- $DIR/; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Silently succeed if the linter has not been installed.
|
||||
# We assume that if you're doing UI dev, you will have installed the linter
|
||||
# by running yarn.
|
||||
if [ ! -x $DIR/$LINTER ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "==> Changes detected in $DIR/: Running linter..."
|
||||
|
||||
# Run the linter from the UI dir.
|
||||
cd $DIR
|
||||
$LINTER || block "UI lint failed"
|
||||
}
|
||||
|
||||
# Check .circleci/config.yml is up to date and valid, and that all changes are
|
||||
# included together in this commit.
|
||||
circleci_verify() {
|
||||
# Change to the root dir of the repo.
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
|
||||
# Fail early if we accidentally used '.yaml' instead of '.yml'
|
||||
if ! git diff --name-only --cached --exit-code -- '.circleci/***.yaml'; then
|
||||
# This is just for consistency, as I keep making this mistake - Sam.
|
||||
block "ERROR: File(s) with .yaml extension detected. Please rename them .yml instead."
|
||||
fi
|
||||
|
||||
# Succeed early if no changes to yml files in .circleci/ are currently staged.
|
||||
# make ci-verify is slow so we really don't want to run it unnecessarily.
|
||||
if git diff --name-only --cached --exit-code -- '.circleci/***.yml'; then
|
||||
return 0
|
||||
fi
|
||||
# Make sure to add no explicit output before this line, as it would just be noise
|
||||
# for those making non-circleci changes.
|
||||
echo "==> Verifying config changes in .circleci/"
|
||||
echo "--> OK: All files are .yml not .yaml"
|
||||
|
||||
# Ensure commit includes _all_ files in .circleci/
|
||||
# So not only are the files up to date, but we are also committing them in one go.
|
||||
if ! git diff --name-only --exit-code -- '.circleci/***.yml'; then
|
||||
echo "ERROR: Some .yml diffs in .circleci/ are staged, others not."
|
||||
block "Please commit the entire .circleci/ directory together, or omit it altogether."
|
||||
fi
|
||||
|
||||
echo "--> OK: All .yml files in .circleci are staged."
|
||||
|
||||
if ! make -C .circleci ci-verify; then
|
||||
block "ERROR: make ci-verify failed"
|
||||
fi
|
||||
|
||||
echo "--> OK: make ci-verify succeeded."
|
||||
}
|
||||
|
||||
for CHECK in $CHECKS; do
|
||||
# Force each check into a subshell to avoid crosstalk.
|
||||
( $CHECK ) || exit $?
|
||||
done
|
||||
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
CHANGES:
|
||||
|
||||
* auth/token: Token store roles use new, common token fields for the values
|
||||
that overlap with other auth backends. `period`, `explicit_max_ttl`, and
|
||||
`bound_cidrs` will continue to work, with priority being given to the
|
||||
`token_` prefixed versions of those parameters. They will also be returned
|
||||
when doing a read on the role if they were used to provide values initially;
|
||||
however, in Vault 1.4 if `period` or `explicit_max_ttl` is zero they will no
|
||||
longer be returned. (`explicit_max_ttl` was already not returned if empty.)
|
||||
* Due to underlying changes in Go version 1.12 and Go > 1.11.5, Vault is now
|
||||
stricter about what characters it will accept in path names. Whereas before
|
||||
it would filter out unprintable characters (and this could be turned off),
|
||||
|
|
@ -50,6 +57,9 @@ IMPROVEMENTS:
|
|||
|
||||
BUG FIXES:
|
||||
|
||||
* identity: Fix a case where modifying aliases of an entity could end up
|
||||
moving the entity into the wrong namespace
|
||||
|
||||
## 1.1.3 (June 5th, 2019)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
|
|
|||
7
Makefile
7
Makefile
|
|
@ -102,8 +102,15 @@ vet:
|
|||
prep: fmtcheck
|
||||
@sh -c "'$(CURDIR)/scripts/goversioncheck.sh' '$(GO_VERSION_MIN)'"
|
||||
@go generate $(go list ./... | grep -v /vendor/)
|
||||
@# Remove old (now broken) husky git hooks.
|
||||
@[ ! -d .git/hooks ] || grep -l '^# husky$$' .git/hooks/* | xargs rm -f
|
||||
@if [ -d .git/hooks ]; then cp .hooks/* .git/hooks/; fi
|
||||
|
||||
ci-config:
|
||||
@$(MAKE) -C .circleci
|
||||
ci-verify:
|
||||
@$(MAKE) -C .circleci ci-verify
|
||||
|
||||
# bootstrap the build by downloading additional tools
|
||||
bootstrap:
|
||||
@for tool in $(EXTERNAL_TOOLS) ; do \
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ require (
|
|||
github.com/hashicorp/go-retryablehttp v0.5.3
|
||||
github.com/hashicorp/go-rootcerts v1.0.0
|
||||
github.com/hashicorp/hcl v1.0.0
|
||||
github.com/hashicorp/vault/sdk v0.1.8
|
||||
github.com/hashicorp/vault/sdk v0.1.12-0.20190614165924-47d4e5b1f688
|
||||
github.com/mitchellh/mapstructure v1.1.2
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ func (c *Sys) RekeyRetrieveBackup() (*RekeyRetrieveResponse, error) {
|
|||
}
|
||||
|
||||
func (c *Sys) RekeyRetrieveRecoveryBackup() (*RekeyRetrieveResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey/recovery-backup")
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey/recovery-key-backup")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
|
@ -275,7 +275,7 @@ func (c *Sys) RekeyDeleteBackup() error {
|
|||
}
|
||||
|
||||
func (c *Sys) RekeyDeleteRecoveryBackup() error {
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey/recovery-backup")
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey/recovery-key-backup")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ func (f *AuditFormatter) FormatRequest(ctx context.Context, w io.Writer, config
|
|||
TokenPolicies: auth.TokenPolicies,
|
||||
IdentityPolicies: auth.IdentityPolicies,
|
||||
ExternalNamespacePolicies: auth.ExternalNamespacePolicies,
|
||||
NoDefaultPolicy: auth.NoDefaultPolicy,
|
||||
Metadata: auth.Metadata,
|
||||
EntityID: auth.EntityID,
|
||||
RemainingUses: req.ClientTokenRemainingUses,
|
||||
|
|
@ -352,6 +353,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
|
|||
TokenPolicies: resp.Auth.TokenPolicies,
|
||||
IdentityPolicies: resp.Auth.IdentityPolicies,
|
||||
ExternalNamespacePolicies: resp.Auth.ExternalNamespacePolicies,
|
||||
NoDefaultPolicy: resp.Auth.NoDefaultPolicy,
|
||||
Metadata: resp.Auth.Metadata,
|
||||
NumUses: resp.Auth.NumUses,
|
||||
EntityID: resp.Auth.EntityID,
|
||||
|
|
@ -397,6 +399,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
|
|||
TokenPolicies: auth.TokenPolicies,
|
||||
IdentityPolicies: auth.IdentityPolicies,
|
||||
ExternalNamespacePolicies: auth.ExternalNamespacePolicies,
|
||||
NoDefaultPolicy: auth.NoDefaultPolicy,
|
||||
Metadata: auth.Metadata,
|
||||
RemainingUses: req.ClientTokenRemainingUses,
|
||||
EntityID: auth.EntityID,
|
||||
|
|
@ -496,6 +499,7 @@ type AuditAuth struct {
|
|||
TokenPolicies []string `json:"token_policies,omitempty"`
|
||||
IdentityPolicies []string `json:"identity_policies,omitempty"`
|
||||
ExternalNamespacePolicies map[string][]string `json:"external_namespace_policies,omitempty"`
|
||||
NoDefaultPolicy bool `json:"no_default_policy,omitempty"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
NumUses int `json:"num_uses,omitempty"`
|
||||
RemainingUses int `json:"remaining_uses,omitempty"`
|
||||
|
|
|
|||
|
|
@ -38,12 +38,13 @@ func TestFormatJSON_formatRequest(t *testing.T) {
|
|||
}{
|
||||
"auth, request": {
|
||||
&logical.Auth{
|
||||
ClientToken: "foo",
|
||||
Accessor: "bar",
|
||||
EntityID: "foobarentity",
|
||||
DisplayName: "testtoken",
|
||||
Policies: []string{"root"},
|
||||
TokenType: logical.TokenTypeService,
|
||||
ClientToken: "foo",
|
||||
Accessor: "bar",
|
||||
DisplayName: "testtoken",
|
||||
EntityID: "foobarentity",
|
||||
NoDefaultPolicy: true,
|
||||
Policies: []string{"root"},
|
||||
TokenType: logical.TokenTypeService,
|
||||
},
|
||||
&logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
|
|
@ -64,12 +65,13 @@ func TestFormatJSON_formatRequest(t *testing.T) {
|
|||
},
|
||||
"auth, request with prefix": {
|
||||
&logical.Auth{
|
||||
ClientToken: "foo",
|
||||
Accessor: "bar",
|
||||
EntityID: "foobarentity",
|
||||
DisplayName: "testtoken",
|
||||
Policies: []string{"root"},
|
||||
TokenType: logical.TokenTypeService,
|
||||
ClientToken: "foo",
|
||||
Accessor: "bar",
|
||||
EntityID: "foobarentity",
|
||||
DisplayName: "testtoken",
|
||||
NoDefaultPolicy: true,
|
||||
Policies: []string{"root"},
|
||||
TokenType: logical.TokenTypeService,
|
||||
},
|
||||
&logical.Request{
|
||||
Operation: logical.UpdateOperation,
|
||||
|
|
@ -141,5 +143,5 @@ func TestFormatJSON_formatRequest(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
const testFormatJSONReqBasicStrFmt = `{"time":"2015-08-05T13:45:46Z","type":"request","auth":{"client_token":"%s","accessor":"bar","display_name":"testtoken","policies":["root"],"metadata":null,"entity_id":"foobarentity","token_type":"service"},"request":{"operation":"update","path":"/foo","data":null,"wrap_ttl":60,"remote_address":"127.0.0.1","headers":{"foo":["bar"]}},"error":"this is an error"}
|
||||
const testFormatJSONReqBasicStrFmt = `{"time":"2015-08-05T13:45:46Z","type":"request","auth":{"client_token":"%s","accessor":"bar","display_name":"testtoken","policies":["root"],"no_default_policy":true,"metadata":null,"entity_id":"foobarentity","token_type":"service"},"request":{"operation":"update","path":"/foo","data":null,"wrap_ttl":60,"remote_address":"127.0.0.1","headers":{"foo":["bar"]}},"error":"this is an error"}
|
||||
`
|
||||
|
|
|
|||
|
|
@ -37,12 +37,13 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
|
|||
}{
|
||||
"auth, request": {
|
||||
&logical.Auth{
|
||||
ClientToken: "foo",
|
||||
Accessor: "bar",
|
||||
EntityID: "foobarentity",
|
||||
DisplayName: "testtoken",
|
||||
Policies: []string{"root"},
|
||||
TokenType: logical.TokenTypeService,
|
||||
ClientToken: "foo",
|
||||
Accessor: "bar",
|
||||
DisplayName: "testtoken",
|
||||
EntityID: "foobarentity",
|
||||
NoDefaultPolicy: true,
|
||||
Policies: []string{"root"},
|
||||
TokenType: logical.TokenTypeService,
|
||||
},
|
||||
&logical.Request{
|
||||
ID: "request",
|
||||
|
|
@ -64,17 +65,18 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
|
|||
errors.New("this is an error"),
|
||||
"",
|
||||
"",
|
||||
fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id">foobarentity</json:string><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_type">service</json:string></json:object><json:string name="error">this is an error</json:string><json:object name="request"><json:string name="client_token">%s</json:string><json:string name="client_token_accessor">bar</json:string><json:object name="headers"><json:array name="foo"><json:string>bar</json:string></json:array></json:object><json:string name="id">request</json:string><json:object name="namespace"><json:string name="id">root</json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">true</json:boolean><json:string name="remote_address">127.0.0.1</json:string><json:number name="wrap_ttl">60</json:number></json:object><json:string name="type">request</json:string>`,
|
||||
fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id">foobarentity</json:string><json:boolean name="no_default_policy">true</json:boolean><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_type">service</json:string></json:object><json:string name="error">this is an error</json:string><json:object name="request"><json:string name="client_token">%s</json:string><json:string name="client_token_accessor">bar</json:string><json:object name="headers"><json:array name="foo"><json:string>bar</json:string></json:array></json:object><json:string name="id">request</json:string><json:object name="namespace"><json:string name="id">root</json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">true</json:boolean><json:string name="remote_address">127.0.0.1</json:string><json:number name="wrap_ttl">60</json:number></json:object><json:string name="type">request</json:string>`,
|
||||
fooSalted, fooSalted),
|
||||
},
|
||||
"auth, request with prefix": {
|
||||
&logical.Auth{
|
||||
ClientToken: "foo",
|
||||
Accessor: "bar",
|
||||
EntityID: "foobarentity",
|
||||
DisplayName: "testtoken",
|
||||
Policies: []string{"root"},
|
||||
TokenType: logical.TokenTypeService,
|
||||
ClientToken: "foo",
|
||||
Accessor: "bar",
|
||||
DisplayName: "testtoken",
|
||||
NoDefaultPolicy: true,
|
||||
EntityID: "foobarentity",
|
||||
Policies: []string{"root"},
|
||||
TokenType: logical.TokenTypeService,
|
||||
},
|
||||
&logical.Request{
|
||||
ID: "request",
|
||||
|
|
@ -96,7 +98,7 @@ func TestFormatJSONx_formatRequest(t *testing.T) {
|
|||
errors.New("this is an error"),
|
||||
"",
|
||||
"@cee: ",
|
||||
fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id">foobarentity</json:string><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_type">service</json:string></json:object><json:string name="error">this is an error</json:string><json:object name="request"><json:string name="client_token">%s</json:string><json:string name="client_token_accessor">bar</json:string><json:object name="headers"><json:array name="foo"><json:string>bar</json:string></json:array></json:object><json:string name="id">request</json:string><json:object name="namespace"><json:string name="id">root</json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">true</json:boolean><json:string name="remote_address">127.0.0.1</json:string><json:number name="wrap_ttl">60</json:number></json:object><json:string name="type">request</json:string>`,
|
||||
fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id">foobarentity</json:string><json:boolean name="no_default_policy">true</json:boolean><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_type">service</json:string></json:object><json:string name="error">this is an error</json:string><json:object name="request"><json:string name="client_token">%s</json:string><json:string name="client_token_accessor">bar</json:string><json:object name="headers"><json:array name="foo"><json:string>bar</json:string></json:array></json:object><json:string name="id">request</json:string><json:object name="namespace"><json:string name="id">root</json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">true</json:boolean><json:string name="remote_address">127.0.0.1</json:string><json:number name="wrap_ttl">60</json:number></json:object><json:string name="type">request</json:string>`,
|
||||
fooSalted, fooSalted),
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -685,12 +685,22 @@ func (c *OperatorRekeyCommand) printUnsealKeys(client *api.Client, status *api.R
|
|||
|
||||
if len(resp.PGPFingerprints) > 0 && resp.Backup {
|
||||
c.UI.Output("")
|
||||
c.UI.Output(wrapAtLength(fmt.Sprintf(
|
||||
"The encrypted unseal keys are backed up to \"core/unseal-keys-backup\"" +
|
||||
"in the storage backend. Remove these keys at any time using " +
|
||||
"\"vault operator rekey -backup-delete\". Vault does not automatically " +
|
||||
"remove these keys.",
|
||||
)))
|
||||
switch strings.ToLower(strings.TrimSpace(c.flagTarget)) {
|
||||
case "barrier":
|
||||
c.UI.Output(wrapAtLength(fmt.Sprintf(
|
||||
"The encrypted unseal keys are backed up to \"core/unseal-keys-backup\" " +
|
||||
"in the storage backend. Remove these keys at any time using " +
|
||||
"\"vault operator rekey -backup-delete\". Vault does not automatically " +
|
||||
"remove these keys.",
|
||||
)))
|
||||
case "recovery", "hsm":
|
||||
c.UI.Output(wrapAtLength(fmt.Sprintf(
|
||||
"The encrypted unseal keys are backed up to \"core/recovery-keys-backup\" " +
|
||||
"in the storage backend. Remove these keys at any time using " +
|
||||
"\"vault operator rekey -backup-delete -target=recovery\". Vault does not automatically " +
|
||||
"remove these keys.",
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
switch status.VerificationRequired {
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -81,8 +81,8 @@ require (
|
|||
github.com/hashicorp/vault-plugin-secrets-gcp v0.5.2
|
||||
github.com/hashicorp/vault-plugin-secrets-gcpkms v0.5.1
|
||||
github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20190416155133-fd495225dea0
|
||||
github.com/hashicorp/vault/api v1.0.1
|
||||
github.com/hashicorp/vault/sdk v0.1.11
|
||||
github.com/hashicorp/vault/api v1.0.3-0.20190614165924-47d4e5b1f688
|
||||
github.com/hashicorp/vault/sdk v0.1.12-0.20190614165924-47d4e5b1f688
|
||||
github.com/influxdata/influxdb v0.0.0-20190411212539-d24b7ba8c4c4
|
||||
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect
|
||||
github.com/jackc/pgx v3.3.0+incompatible // indirect
|
||||
|
|
|
|||
|
|
@ -265,10 +265,6 @@ func ConfClusterAndCore(t testing.T, conf *vault.CoreConfig, opts *vault.TestClu
|
|||
"approle": credAppRole.Factory,
|
||||
"userpass": credUserpass.Factory,
|
||||
}
|
||||
coreConfig.LogicalBackends = map[string]logical.Factory{
|
||||
"local-kv": PassthroughWithLocalPathsFactory,
|
||||
"leased-kv": vault.LeasedPassthroughBackendFactory,
|
||||
}
|
||||
vault.AddNoopAudit(&coreConfig)
|
||||
cluster := vault.NewTestCluster(t, &coreConfig, opts)
|
||||
cluster.Start()
|
||||
|
|
@ -281,13 +277,6 @@ func ConfClusterAndCore(t testing.T, conf *vault.CoreConfig, opts *vault.TestClu
|
|||
return cluster, core
|
||||
}
|
||||
|
||||
func GetClusterAndCore(t testing.T, logger log.Logger, handlerFunc func(*vault.HandlerProperties) http.Handler) (*vault.TestCluster, *vault.TestClusterCore) {
|
||||
return ConfClusterAndCore(t, &vault.CoreConfig{}, &vault.TestClusterOptions{
|
||||
Logger: logger,
|
||||
HandlerFunc: handlerFunc,
|
||||
})
|
||||
}
|
||||
|
||||
func GetPerfReplicatedClusters(t testing.T, conf *vault.CoreConfig, opts *vault.TestClusterOptions) *ReplicatedTestClusters {
|
||||
ret := &ReplicatedTestClusters{}
|
||||
|
||||
|
|
@ -305,13 +294,18 @@ func GetPerfReplicatedClusters(t testing.T, conf *vault.CoreConfig, opts *vault.
|
|||
// Set this lower so that state populates quickly to standby nodes
|
||||
cluster.HeartbeatInterval = 2 * time.Second
|
||||
|
||||
opts1 := *opts
|
||||
opts1.Logger = logger.Named("perf-pri")
|
||||
ret.PerfPrimaryCluster, _ = ConfClusterAndCore(t, conf, &opts1)
|
||||
numCores := opts.NumCores
|
||||
if numCores == 0 {
|
||||
numCores = vault.DefaultNumCores
|
||||
}
|
||||
|
||||
opts2 := *opts
|
||||
opts1.Logger = logger.Named("perf-sec")
|
||||
ret.PerfSecondaryCluster, _ = ConfClusterAndCore(t, conf, &opts2)
|
||||
localopts := *opts
|
||||
localopts.Logger = logger.Named("perf-pri")
|
||||
ret.PerfPrimaryCluster, _ = ConfClusterAndCore(t, conf, &localopts)
|
||||
|
||||
localopts.Logger = logger.Named("perf-sec")
|
||||
localopts.FirstCoreNumber += numCores
|
||||
ret.PerfSecondaryCluster, _ = ConfClusterAndCore(t, conf, &localopts)
|
||||
|
||||
SetupTwoClusterPerfReplication(t, ret.PerfPrimaryCluster, ret.PerfSecondaryCluster)
|
||||
|
||||
|
|
@ -319,6 +313,12 @@ func GetPerfReplicatedClusters(t testing.T, conf *vault.CoreConfig, opts *vault.
|
|||
}
|
||||
|
||||
func GetFourReplicatedClusters(t testing.T, handlerFunc func(*vault.HandlerProperties) http.Handler) *ReplicatedTestClusters {
|
||||
return GetFourReplicatedClustersWithConf(t, &vault.CoreConfig{}, &vault.TestClusterOptions{
|
||||
HandlerFunc: handlerFunc,
|
||||
})
|
||||
}
|
||||
|
||||
func GetFourReplicatedClustersWithConf(t testing.T, conf *vault.CoreConfig, opts *vault.TestClusterOptions) *ReplicatedTestClusters {
|
||||
ret := &ReplicatedTestClusters{}
|
||||
|
||||
logger := log.New(&log.LoggerOptions{
|
||||
|
|
@ -328,13 +328,26 @@ func GetFourReplicatedClusters(t testing.T, handlerFunc func(*vault.HandlerPrope
|
|||
// Set this lower so that state populates quickly to standby nodes
|
||||
cluster.HeartbeatInterval = 2 * time.Second
|
||||
|
||||
ret.PerfPrimaryCluster, _ = GetClusterAndCore(t, logger.Named("perf-pri"), handlerFunc)
|
||||
numCores := opts.NumCores
|
||||
if numCores == 0 {
|
||||
numCores = vault.DefaultNumCores
|
||||
}
|
||||
|
||||
ret.PerfSecondaryCluster, _ = GetClusterAndCore(t, logger.Named("perf-sec"), handlerFunc)
|
||||
localopts := *opts
|
||||
localopts.Logger = logger.Named("perf-pri")
|
||||
ret.PerfPrimaryCluster, _ = ConfClusterAndCore(t, conf, &localopts)
|
||||
|
||||
ret.PerfPrimaryDRCluster, _ = GetClusterAndCore(t, logger.Named("perf-pri-dr"), handlerFunc)
|
||||
localopts.Logger = logger.Named("perf-sec")
|
||||
localopts.FirstCoreNumber += numCores
|
||||
ret.PerfSecondaryCluster, _ = ConfClusterAndCore(t, conf, &localopts)
|
||||
|
||||
ret.PerfSecondaryDRCluster, _ = GetClusterAndCore(t, logger.Named("perf-sec-dr"), handlerFunc)
|
||||
localopts.Logger = logger.Named("perf-pri-dr")
|
||||
localopts.FirstCoreNumber += numCores
|
||||
ret.PerfPrimaryDRCluster, _ = ConfClusterAndCore(t, conf, &localopts)
|
||||
|
||||
localopts.Logger = logger.Named("perf-sec-dr")
|
||||
localopts.FirstCoreNumber += numCores
|
||||
ret.PerfSecondaryDRCluster, _ = ConfClusterAndCore(t, conf, &localopts)
|
||||
|
||||
builder := &ReplicatedTestClustersBuilder{clusters: ret}
|
||||
builder.setupFourClusterReplication(t)
|
||||
|
|
|
|||
|
|
@ -237,9 +237,7 @@ func NewConsulBackend(conf map[string]string, logger log.Logger) (physical.Backe
|
|||
logger.Debug("config address parsed", "scheme", parts[0])
|
||||
logger.Debug("config scheme parsed", "address", parts[1])
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("address should be host[:port], not URL")
|
||||
}
|
||||
} // allow "unix:" or whatever else consul supports in the future
|
||||
}
|
||||
}
|
||||
if scheme, ok := conf["scheme"]; ok {
|
||||
|
|
|
|||
|
|
@ -231,6 +231,24 @@ func TestConsul_newConsulBackend(t *testing.T) {
|
|||
max_parallel: 4,
|
||||
consistencyMode: "strong",
|
||||
},
|
||||
{
|
||||
name: "Unix socket",
|
||||
consulConfig: map[string]string{
|
||||
"address": "unix:///tmp/.consul.http.sock",
|
||||
},
|
||||
address: "/tmp/.consul.http.sock",
|
||||
scheme: "http", // Default, not overridden?
|
||||
|
||||
// Defaults
|
||||
checkTimeout: 5 * time.Second,
|
||||
redirectAddr: "http://127.0.0.1:8200",
|
||||
path: "vault/",
|
||||
service: "vault",
|
||||
token: "",
|
||||
max_parallel: 4,
|
||||
disableReg: false,
|
||||
consistencyMode: "default",
|
||||
},
|
||||
{
|
||||
name: "Scheme in address",
|
||||
consulConfig: map[string]string{
|
||||
|
|
|
|||
|
|
@ -107,103 +107,92 @@ func testPostgresSQLLockTTL(t *testing.T, ha physical.HABackend) {
|
|||
// Set much smaller lock times to speed up the test.
|
||||
lockTTL := 3
|
||||
renewInterval := time.Second * 1
|
||||
watchInterval := time.Second * 1
|
||||
retryInterval := time.Second * 1
|
||||
longRenewInterval := time.Duration(lockTTL*2) * time.Second
|
||||
lockkey := "postgresttl"
|
||||
|
||||
var leaderCh <-chan struct{}
|
||||
|
||||
// Get the lock
|
||||
origLock, err := ha.LockWith("dynamodbttl", "bar")
|
||||
origLock, err := ha.LockWith(lockkey, "bar")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
// set the first lock renew period to double the expected TTL.
|
||||
lock := origLock.(*PostgreSQLLock)
|
||||
lock.renewInterval = time.Duration(lockTTL*2) * time.Second
|
||||
lock.ttlSeconds = lockTTL
|
||||
// lock.retryInterval = watchInterval
|
||||
{
|
||||
// set the first lock renew period to double the expected TTL.
|
||||
lock := origLock.(*PostgreSQLLock)
|
||||
lock.renewInterval = longRenewInterval
|
||||
lock.ttlSeconds = lockTTL
|
||||
|
||||
// Attempt to lock
|
||||
leaderCh, err := lock.Lock(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if leaderCh == nil {
|
||||
t.Fatalf("failed to get leader ch")
|
||||
}
|
||||
// Attempt to lock
|
||||
leaderCh, err = lock.Lock(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if leaderCh == nil {
|
||||
t.Fatalf("failed to get leader ch")
|
||||
}
|
||||
|
||||
// Check the value
|
||||
held, val, err := lock.Value()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if !held {
|
||||
t.Fatalf("should be held")
|
||||
}
|
||||
if val != "bar" {
|
||||
t.Fatalf("bad value: %v", err)
|
||||
// Check the value
|
||||
held, val, err := lock.Value()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if !held {
|
||||
t.Fatalf("should be held")
|
||||
}
|
||||
if val != "bar" {
|
||||
t.Fatalf("bad value: %v", val)
|
||||
}
|
||||
}
|
||||
|
||||
// Second acquisition should succeed because the first lock should
|
||||
// not renew within the 3 sec TTL.
|
||||
origLock2, err := ha.LockWith("dynamodbttl", "baz")
|
||||
origLock2, err := ha.LockWith(lockkey, "baz")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
{
|
||||
lock2 := origLock2.(*PostgreSQLLock)
|
||||
lock2.renewInterval = renewInterval
|
||||
lock2.ttlSeconds = lockTTL
|
||||
lock2.retryInterval = retryInterval
|
||||
|
||||
lock2 := origLock2.(*PostgreSQLLock)
|
||||
lock2.renewInterval = renewInterval
|
||||
lock2.ttlSeconds = lockTTL
|
||||
// lock2.retryInterval = watchInterval
|
||||
// Cancel attempt in 6 sec so as not to block unit tests forever
|
||||
stopCh := make(chan struct{})
|
||||
time.AfterFunc(time.Duration(lockTTL*2)*time.Second, func() {
|
||||
close(stopCh)
|
||||
})
|
||||
|
||||
// Cancel attempt in 6 sec so as not to block unit tests forever
|
||||
stopCh := make(chan struct{})
|
||||
time.AfterFunc(time.Duration(lockTTL*2)*time.Second, func() {
|
||||
close(stopCh)
|
||||
})
|
||||
// Attempt to lock should work
|
||||
leaderCh2, err := lock2.Lock(stopCh)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if leaderCh2 == nil {
|
||||
t.Fatalf("should get leader ch")
|
||||
}
|
||||
defer lock2.Unlock()
|
||||
|
||||
// Attempt to lock should work
|
||||
leaderCh2, err := lock2.Lock(stopCh)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if leaderCh2 == nil {
|
||||
t.Fatalf("should get leader ch")
|
||||
}
|
||||
|
||||
// Check the value
|
||||
held, val, err = lock2.Value()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if !held {
|
||||
t.Fatalf("should be held")
|
||||
}
|
||||
if val != "baz" {
|
||||
t.Fatalf("bad value: %v", err)
|
||||
// Check the value
|
||||
held, val, err := lock2.Value()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
if !held {
|
||||
t.Fatalf("should be held")
|
||||
}
|
||||
if val != "baz" {
|
||||
t.Fatalf("bad value: %v", val)
|
||||
}
|
||||
}
|
||||
|
||||
// The first lock should have lost the leader channel
|
||||
leaderChClosed := false
|
||||
blocking := make(chan struct{})
|
||||
// Attempt to read from the leader or the blocking channel, which ever one
|
||||
// happens first.
|
||||
go func() {
|
||||
select {
|
||||
case <-time.After(watchInterval * 3):
|
||||
return
|
||||
case <-leaderCh:
|
||||
leaderChClosed = true
|
||||
close(blocking)
|
||||
case <-blocking:
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
<-blocking
|
||||
if !leaderChClosed {
|
||||
select {
|
||||
case <-time.After(longRenewInterval * 2):
|
||||
t.Fatalf("original lock did not have its leader channel closed.")
|
||||
case <-leaderCh:
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
lock2.Unlock()
|
||||
}
|
||||
|
||||
// Verify that once Unlock is called, we don't keep trying to renew the original
|
||||
|
|
@ -237,7 +226,7 @@ func testPostgresSQLLockRenewal(t *testing.T, ha physical.HABackend) {
|
|||
t.Fatalf("should be held")
|
||||
}
|
||||
if val != "bar" {
|
||||
t.Fatalf("bad value: %v", err)
|
||||
t.Fatalf("bad value: %v", val)
|
||||
}
|
||||
|
||||
// Release the lock, which will delete the stored item
|
||||
|
|
@ -280,7 +269,7 @@ func testPostgresSQLLockRenewal(t *testing.T, ha physical.HABackend) {
|
|||
t.Fatalf("should be held")
|
||||
}
|
||||
if val != "baz" {
|
||||
t.Fatalf("bad value: %v", err)
|
||||
t.Fatalf("bad value: %v", val)
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ RUN apt-get update -y && apt-get install -y -q nodejs yarn=1.12.1-1
|
|||
RUN rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
ENV GOVERSION 1.12.4
|
||||
ENV GOVERSION 1.12.6
|
||||
RUN mkdir /goroot && mkdir /gopath
|
||||
RUN curl https://storage.googleapis.com/golang/go${GOVERSION}.linux-amd64.tar.gz \
|
||||
| tar xvzf - -C /goroot --strip-components=1
|
||||
|
|
|
|||
233
sdk/helper/tokenutil/tokenutil.go
Normal file
233
sdk/helper/tokenutil/tokenutil.go
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
package tokenutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
sockaddr "github.com/hashicorp/go-sockaddr"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/helper/parseutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
// TokenParams contains a set of common parameters that auth plugins can use
|
||||
// for setting token behavior
|
||||
type TokenParams struct {
|
||||
// The set of CIDRs that tokens generated using this role will be bound to
|
||||
TokenBoundCIDRs []*sockaddr.SockAddrMarshaler `json:"token_bound_cidrs"`
|
||||
|
||||
// If set, the token entry will have an explicit maximum TTL set, rather
|
||||
// than deferring to role/mount values
|
||||
TokenExplicitMaxTTL time.Duration `json:"token_explicit_max_ttl" mapstructure:"token_explicit_max_ttl"`
|
||||
|
||||
// The max TTL to use for the token
|
||||
TokenMaxTTL time.Duration `json:"token_max_ttl" mapstructure:"token_max_ttl"`
|
||||
|
||||
// If set, core will not automatically add default to the policy list
|
||||
TokenNoDefaultPolicy bool `json:"token_no_default_policy" mapstructure:"token_no_default_policy"`
|
||||
|
||||
// The maximum number of times a token issued from this role may be used.
|
||||
TokenNumUses int `json:"token_num_uses" mapstructure:"token_num_uses"`
|
||||
|
||||
// If non-zero, tokens created using this role will be able to be renewed
|
||||
// forever, but will have a fixed renewal period of this value
|
||||
TokenPeriod time.Duration `json:"token_period" mapstructure:"token_period"`
|
||||
|
||||
// The policies to set
|
||||
TokenPolicies []string `json:"token_policies" mapstructure:"token_policies"`
|
||||
|
||||
// The type of token this role should issue
|
||||
TokenType logical.TokenType `json:"token_type" mapstructure:"token_type"`
|
||||
|
||||
// The TTL to user for the token
|
||||
TokenTTL time.Duration `json:"token_ttl" mapstructure:"token_ttl"`
|
||||
}
|
||||
|
||||
// AddTokenFields adds fields to an existing role. It panics if it would
|
||||
// overwrite an existing field.
|
||||
func AddTokenFields(m map[string]*framework.FieldSchema) {
|
||||
AddTokenFieldsWithAllowList(m, nil)
|
||||
}
|
||||
|
||||
// AddTokenFields adds fields to an existing role. It panics if it would
|
||||
// overwrite an existing field. Allowed can be use to restrict the set, e.g. if
|
||||
// there would be conflicts.
|
||||
func AddTokenFieldsWithAllowList(m map[string]*framework.FieldSchema, allowed []string) {
|
||||
r := TokenFields()
|
||||
for k, v := range r {
|
||||
if len(allowed) > 0 && !strutil.StrListContains(allowed, k) {
|
||||
continue
|
||||
}
|
||||
if _, has := m[k]; has {
|
||||
panic(fmt.Sprintf("adding role field %s would overwrite existing field", k))
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// TokenFields provides a set of field schemas for the parameters
|
||||
func TokenFields() map[string]*framework.FieldSchema {
|
||||
return map[string]*framework.FieldSchema{
|
||||
"token_bound_cidrs": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `Comma separated string or JSON list of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.`,
|
||||
},
|
||||
|
||||
"token_explicit_max_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: tokenExplicitMaxTTLHelp,
|
||||
},
|
||||
|
||||
"token_max_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: "The maximum lifetime of the generated token",
|
||||
},
|
||||
|
||||
"token_no_default_policy": &framework.FieldSchema{
|
||||
Type: framework.TypeBool,
|
||||
Description: "If true, the 'default' policy will not automatically be added to generated tokens",
|
||||
},
|
||||
|
||||
"token_period": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: tokenPeriodHelp,
|
||||
},
|
||||
|
||||
"token_policies": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: "Comma-separated list of policies",
|
||||
},
|
||||
|
||||
"token_type": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Default: "default-service",
|
||||
Description: "The type of token to generate, service or batch",
|
||||
},
|
||||
|
||||
"token_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: "The initial ttl of the token to generate",
|
||||
},
|
||||
|
||||
"token_num_uses": &framework.FieldSchema{
|
||||
Type: framework.TypeInt,
|
||||
Description: "The maximum number of times a token may be used, a value of zero means unlimited",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ParseTokenFields provides common field parsing functionality into a TokenFields struct
|
||||
func (t *TokenParams) ParseTokenFields(req *logical.Request, d *framework.FieldData) error {
|
||||
if boundCIDRsRaw, ok := d.GetOk("token_bound_cidrs"); ok {
|
||||
boundCIDRs, err := parseutil.ParseAddrs(boundCIDRsRaw.([]string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.TokenBoundCIDRs = boundCIDRs
|
||||
}
|
||||
|
||||
if explicitMaxTTLRaw, ok := d.GetOk("token_explicit_max_ttl"); ok {
|
||||
t.TokenExplicitMaxTTL = time.Duration(explicitMaxTTLRaw.(int)) * time.Second
|
||||
}
|
||||
|
||||
if maxTTLRaw, ok := d.GetOk("token_max_ttl"); ok {
|
||||
t.TokenMaxTTL = time.Duration(maxTTLRaw.(int)) * time.Second
|
||||
}
|
||||
if t.TokenMaxTTL < 0 {
|
||||
return errors.New("'token_max_ttl' cannot be negative")
|
||||
}
|
||||
|
||||
if noDefaultRaw, ok := d.GetOk("token_no_default_policy"); ok {
|
||||
t.TokenNoDefaultPolicy = noDefaultRaw.(bool)
|
||||
}
|
||||
|
||||
if periodRaw, ok := d.GetOk("token_period"); ok {
|
||||
t.TokenPeriod = time.Duration(periodRaw.(int)) * time.Second
|
||||
}
|
||||
if t.TokenPeriod < 0 {
|
||||
return errors.New("'token_period' cannot be negative")
|
||||
}
|
||||
|
||||
if policiesRaw, ok := d.GetOk("token_policies"); ok {
|
||||
t.TokenPolicies = policiesRaw.([]string)
|
||||
}
|
||||
|
||||
if tokenTypeRaw, ok := d.GetOk("token_type"); ok {
|
||||
var tokenType logical.TokenType
|
||||
tokenTypeStr := tokenTypeRaw.(string)
|
||||
switch tokenTypeStr {
|
||||
case "service":
|
||||
tokenType = logical.TokenTypeService
|
||||
case "batch":
|
||||
tokenType = logical.TokenTypeBatch
|
||||
case "", "default", "default-service":
|
||||
tokenType = logical.TokenTypeDefaultService
|
||||
case "default-batch":
|
||||
tokenType = logical.TokenTypeDefaultBatch
|
||||
default:
|
||||
return fmt.Errorf("invalid 'token_type' value %q", tokenTypeStr)
|
||||
}
|
||||
t.TokenType = tokenType
|
||||
}
|
||||
|
||||
if ttlRaw, ok := d.GetOk("token_ttl"); ok {
|
||||
t.TokenTTL = time.Duration(ttlRaw.(int)) * time.Second
|
||||
}
|
||||
if t.TokenTTL < 0 {
|
||||
return errors.New("'token_ttl' cannot be negative")
|
||||
}
|
||||
if t.TokenTTL > 0 && t.TokenMaxTTL > 0 && t.TokenTTL > t.TokenMaxTTL {
|
||||
return errors.New("'token_ttl' cannot be greater than 'token_max_ttl'")
|
||||
}
|
||||
|
||||
if tokenNumUses, ok := d.GetOk("token_num_uses"); ok {
|
||||
t.TokenNumUses = tokenNumUses.(int)
|
||||
}
|
||||
if t.TokenNumUses < 0 {
|
||||
return errors.New("'token_num_uses' cannot be negative")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PopulateTokenData adds information from TokenParams into the map
|
||||
func (t *TokenParams) PopulateTokenData(m map[string]interface{}) {
|
||||
m["token_bound_cidrs"] = t.TokenBoundCIDRs
|
||||
m["token_explicit_max_ttl"] = t.TokenExplicitMaxTTL.Seconds()
|
||||
m["token_max_ttl"] = t.TokenMaxTTL.Seconds()
|
||||
m["token_no_default_policy"] = t.TokenNoDefaultPolicy
|
||||
m["token_period"] = t.TokenPeriod.Seconds()
|
||||
m["token_policies"] = t.TokenPolicies
|
||||
m["token_type"] = t.TokenType.String()
|
||||
m["token_ttl"] = t.TokenTTL.Seconds()
|
||||
m["token_num_uses"] = t.TokenNumUses
|
||||
}
|
||||
|
||||
// PopulateTokenAuth populates Auth with parameters
|
||||
func (t *TokenParams) PopulateTokenAuth(auth *logical.Auth) {
|
||||
auth.BoundCIDRs = t.TokenBoundCIDRs
|
||||
auth.ExplicitMaxTTL = t.TokenExplicitMaxTTL
|
||||
auth.MaxTTL = t.TokenMaxTTL
|
||||
auth.NoDefaultPolicy = t.TokenNoDefaultPolicy
|
||||
auth.Period = t.TokenPeriod
|
||||
auth.Policies = t.TokenPolicies
|
||||
auth.TokenType = t.TokenType
|
||||
auth.TTL = t.TokenTTL
|
||||
auth.NumUses = t.TokenNumUses
|
||||
}
|
||||
|
||||
const (
|
||||
tokenPeriodHelp = `If set, tokens created via this role
|
||||
will have no max lifetime; instead, their
|
||||
renewal period will be fixed to this value.
|
||||
This takes an integer number of seconds,
|
||||
or a string duration (e.g. "24h").`
|
||||
tokenExplicitMaxTTLHelp = `If set, tokens created via this role
|
||||
carry an explicit maximum TTL. During renewal,
|
||||
the current maximum TTL values of the role
|
||||
and the mount are not checked for changes,
|
||||
and any updates to these values will have
|
||||
no effect on the token being renewed.`
|
||||
)
|
||||
|
|
@ -38,6 +38,11 @@ type Auth struct {
|
|||
// different namespaces indexed by respective namespace identifiers
|
||||
ExternalNamespacePolicies map[string][]string `json:"external_namespace_policies" mapstructure:"external_namespace_policies" structs:"external_namespace_policies"`
|
||||
|
||||
// Indicates that the default policy should not be added by core when
|
||||
// creating a token. The default policy will still be added if it's
|
||||
// explicitly defined.
|
||||
NoDefaultPolicy bool `json:"no_default_policy" mapstructure:"no_default_policy" structs:"no_default_policy"`
|
||||
|
||||
// Metadata is used to attach arbitrary string-type metadata to
|
||||
// an authenticated user. This metadata will be outputted into the
|
||||
// audit log.
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ type SystemView interface {
|
|||
|
||||
type ExtendedSystemView interface {
|
||||
Auditor() Auditor
|
||||
ForwardGenericRequest(context.Context, *Request) (*Response, error)
|
||||
}
|
||||
|
||||
type StaticSystemView struct {
|
||||
|
|
@ -104,6 +105,10 @@ func (d StaticSystemView) Auditor() Auditor {
|
|||
return noopAuditor{}
|
||||
}
|
||||
|
||||
func (d StaticSystemView) ForwardGenericRequest(ctx context.Context, req *Request) (*Response, error) {
|
||||
return nil, errors.New("ForwardGenericRequest is not implemented in StaticSystemView")
|
||||
}
|
||||
|
||||
func (d StaticSystemView) DefaultLeaseTTL() time.Duration {
|
||||
return d.DefaultLeaseTTLVal
|
||||
}
|
||||
|
|
|
|||
|
|
@ -526,7 +526,9 @@ type Auth struct {
|
|||
// TTL is a hard limit and cannot be exceeded, also counts for periodic tokens.
|
||||
ExplicitMaxTTL int64 `sentinel:"" protobuf:"varint,16,opt,name=explicit_max_ttl,json=explicitMaxTtl,proto3" json:"explicit_max_ttl,omitempty"`
|
||||
// TokenType is the type of token being requested
|
||||
TokenType uint32 `sentinel:"" protobuf:"varint,17,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
|
||||
TokenType uint32 `sentinel:"" protobuf:"varint,17,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
|
||||
// Whether the default policy should be added automatically by core
|
||||
NoDefaultPolicy bool `sentinel:"" protobuf:"varint,18,opt,name=no_default_policy,json=noDefaultPolicy,proto3" json:"no_default_policy,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
|
@ -676,6 +678,13 @@ func (m *Auth) GetTokenType() uint32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (m *Auth) GetNoDefaultPolicy() bool {
|
||||
if m != nil {
|
||||
return m.NoDefaultPolicy
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type TokenEntry struct {
|
||||
ID string `sentinel:"" protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Accessor string `sentinel:"" protobuf:"bytes,2,opt,name=accessor,proto3" json:"accessor,omitempty"`
|
||||
|
|
@ -2713,164 +2722,165 @@ func init() {
|
|||
func init() { proto.RegisterFile("sdk/plugin/pb/backend.proto", fileDescriptor_4dbf1dfe0c11846b) }
|
||||
|
||||
var fileDescriptor_4dbf1dfe0c11846b = []byte{
|
||||
// 2499 bytes of a gzipped FileDescriptorProto
|
||||
// 2519 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x59, 0xdb, 0x72, 0x1b, 0xc7,
|
||||
0xd1, 0x2e, 0x00, 0xc4, 0xa9, 0x71, 0x22, 0x46, 0xb4, 0xfe, 0x15, 0x24, 0xff, 0x82, 0xd7, 0x91,
|
||||
0x0c, 0x2b, 0x36, 0x68, 0x51, 0x71, 0x2c, 0x27, 0x65, 0xa7, 0x68, 0x8a, 0x96, 0x19, 0x93, 0x36,
|
||||
0x6b, 0x09, 0xc5, 0x39, 0x55, 0xc1, 0x83, 0xdd, 0x21, 0xb8, 0xc5, 0xc5, 0xee, 0x66, 0x76, 0x96,
|
||||
0x22, 0xae, 0xf2, 0x16, 0x79, 0x8d, 0xdc, 0xa6, 0x72, 0x93, 0xbb, 0x94, 0x2b, 0xf7, 0x79, 0x8d,
|
||||
0x3c, 0x43, 0x6a, 0x7a, 0x66, 0x4f, 0x00, 0x68, 0xc9, 0x55, 0xce, 0xdd, 0x4c, 0x77, 0xcf, 0xa9,
|
||||
0xe7, 0xeb, 0xaf, 0x7b, 0x76, 0xe1, 0x6e, 0xe4, 0x5c, 0xee, 0x86, 0x5e, 0x3c, 0x77, 0xfd, 0xdd,
|
||||
0x70, 0xb6, 0x3b, 0xa3, 0xf6, 0x25, 0xf3, 0x9d, 0x71, 0xc8, 0x03, 0x11, 0x90, 0x72, 0x38, 0x1b,
|
||||
0xdc, 0x9f, 0x07, 0xc1, 0xdc, 0x63, 0xbb, 0x28, 0x99, 0xc5, 0xe7, 0xbb, 0xc2, 0x5d, 0xb0, 0x48,
|
||||
0xd0, 0x45, 0xa8, 0x8c, 0x06, 0x03, 0x39, 0x83, 0x17, 0xcc, 0x5d, 0x9b, 0x7a, 0xbb, 0xae, 0xc3,
|
||||
0x7c, 0xe1, 0x8a, 0xa5, 0xd6, 0x19, 0x79, 0x9d, 0x5a, 0x45, 0x69, 0xcc, 0x3a, 0x54, 0x0f, 0x17,
|
||||
0xa1, 0x58, 0x9a, 0x43, 0xa8, 0x7d, 0xc1, 0xa8, 0xc3, 0x38, 0xb9, 0x0d, 0xb5, 0x0b, 0x6c, 0x19,
|
||||
0xa5, 0x61, 0x65, 0xd4, 0xb4, 0x74, 0xcf, 0xfc, 0x03, 0xc0, 0xa9, 0x1c, 0x73, 0xc8, 0x79, 0xc0,
|
||||
0xc9, 0x1d, 0x68, 0x30, 0xce, 0xa7, 0x62, 0x19, 0x32, 0xa3, 0x34, 0x2c, 0x8d, 0x3a, 0x56, 0x9d,
|
||||
0x71, 0x3e, 0x59, 0x86, 0x8c, 0xfc, 0x1f, 0xc8, 0xe6, 0x74, 0x11, 0xcd, 0x8d, 0xf2, 0xb0, 0x24,
|
||||
0x67, 0x60, 0x9c, 0x9f, 0x44, 0xf3, 0x64, 0x8c, 0x1d, 0x38, 0xcc, 0xa8, 0x0c, 0x4b, 0xa3, 0x0a,
|
||||
0x8e, 0x39, 0x08, 0x1c, 0x66, 0xfe, 0xa5, 0x04, 0xd5, 0x53, 0x2a, 0x2e, 0x22, 0x42, 0x60, 0x8b,
|
||||
0x07, 0x81, 0xd0, 0x8b, 0x63, 0x9b, 0x8c, 0xa0, 0x17, 0xfb, 0x34, 0x16, 0x17, 0xf2, 0x54, 0x36,
|
||||
0x15, 0xcc, 0x31, 0xca, 0xa8, 0x5e, 0x15, 0x93, 0xb7, 0xa1, 0xe3, 0x05, 0x36, 0xf5, 0xa6, 0x91,
|
||||
0x08, 0x38, 0x9d, 0xcb, 0x75, 0xa4, 0x5d, 0x1b, 0x85, 0x67, 0x4a, 0x46, 0x1e, 0x41, 0x3f, 0x62,
|
||||
0xd4, 0x9b, 0xbe, 0xe4, 0x34, 0x4c, 0x0d, 0xb7, 0xd4, 0x84, 0x52, 0xf1, 0x0d, 0xa7, 0xa1, 0xb6,
|
||||
0x35, 0xff, 0x51, 0x83, 0xba, 0xc5, 0xfe, 0x14, 0xb3, 0x48, 0x90, 0x2e, 0x94, 0x5d, 0x07, 0x4f,
|
||||
0xdb, 0xb4, 0xca, 0xae, 0x43, 0xc6, 0x40, 0x2c, 0x16, 0x7a, 0x72, 0x69, 0x37, 0xf0, 0x0f, 0xbc,
|
||||
0x38, 0x12, 0x8c, 0xeb, 0x33, 0x6f, 0xd0, 0x90, 0x7b, 0xd0, 0x0c, 0x42, 0xc6, 0x51, 0x86, 0x0e,
|
||||
0x68, 0x5a, 0x99, 0x40, 0x1e, 0x3c, 0xa4, 0xe2, 0xc2, 0xd8, 0x42, 0x05, 0xb6, 0xa5, 0xcc, 0xa1,
|
||||
0x82, 0x1a, 0x55, 0x25, 0x93, 0x6d, 0x62, 0x42, 0x2d, 0x62, 0x36, 0x67, 0xc2, 0xa8, 0x0d, 0x4b,
|
||||
0xa3, 0xd6, 0x1e, 0x8c, 0xc3, 0xd9, 0xf8, 0x0c, 0x25, 0x96, 0xd6, 0x90, 0x7b, 0xb0, 0x25, 0xfd,
|
||||
0x62, 0xd4, 0xd1, 0xa2, 0x21, 0x2d, 0xf6, 0x63, 0x71, 0x61, 0xa1, 0x94, 0xec, 0x41, 0x5d, 0xdd,
|
||||
0x69, 0x64, 0x34, 0x86, 0x95, 0x51, 0x6b, 0xcf, 0x90, 0x06, 0xfa, 0x94, 0x63, 0x05, 0x83, 0xe8,
|
||||
0xd0, 0x17, 0x7c, 0x69, 0x25, 0x86, 0xe4, 0x2d, 0x68, 0xdb, 0x9e, 0xcb, 0x7c, 0x31, 0x15, 0xc1,
|
||||
0x25, 0xf3, 0x8d, 0x26, 0xee, 0xa8, 0xa5, 0x64, 0x13, 0x29, 0x22, 0x7b, 0xf0, 0x46, 0xde, 0x64,
|
||||
0x4a, 0x6d, 0x9b, 0x45, 0x51, 0xc0, 0x0d, 0x40, 0xdb, 0x5b, 0x39, 0xdb, 0x7d, 0xad, 0x92, 0xd3,
|
||||
0x3a, 0x6e, 0x14, 0x7a, 0x74, 0x39, 0xf5, 0xe9, 0x82, 0x19, 0x2d, 0x35, 0xad, 0x96, 0x7d, 0x45,
|
||||
0x17, 0x8c, 0xdc, 0x87, 0xd6, 0x22, 0x88, 0x7d, 0x31, 0x0d, 0x03, 0xd7, 0x17, 0x46, 0x1b, 0x2d,
|
||||
0x00, 0x45, 0xa7, 0x52, 0x42, 0xde, 0x04, 0xd5, 0x53, 0x60, 0xec, 0x28, 0xbf, 0xa2, 0x04, 0xe1,
|
||||
0xf8, 0x00, 0xba, 0x4a, 0x9d, 0xee, 0xa7, 0x8b, 0x26, 0x1d, 0x94, 0xa6, 0x3b, 0xf9, 0x00, 0x9a,
|
||||
0x88, 0x07, 0xd7, 0x3f, 0x0f, 0x8c, 0x1e, 0xfa, 0xed, 0x56, 0xce, 0x2d, 0x12, 0x13, 0x47, 0xfe,
|
||||
0x79, 0x60, 0x35, 0x5e, 0xea, 0x16, 0xf9, 0x04, 0xee, 0x16, 0xce, 0xcb, 0xd9, 0x82, 0xba, 0xbe,
|
||||
0xeb, 0xcf, 0xa7, 0x71, 0xc4, 0x22, 0x63, 0x1b, 0x11, 0x6e, 0xe4, 0x4e, 0x6d, 0x25, 0x06, 0x2f,
|
||||
0x22, 0x16, 0x91, 0xbb, 0xd0, 0x54, 0x41, 0x3a, 0x75, 0x1d, 0xa3, 0x8f, 0x5b, 0x6a, 0x28, 0xc1,
|
||||
0x91, 0x43, 0xde, 0x81, 0x5e, 0x18, 0x78, 0xae, 0xbd, 0x9c, 0x06, 0x57, 0x8c, 0x73, 0xd7, 0x61,
|
||||
0x06, 0x19, 0x96, 0x46, 0x0d, 0xab, 0xab, 0xc4, 0x5f, 0x6b, 0xe9, 0xa6, 0xd0, 0xb8, 0x85, 0x86,
|
||||
0x6b, 0xa1, 0x31, 0x06, 0xb0, 0x03, 0xdf, 0x67, 0x36, 0xc2, 0x6f, 0x07, 0x4f, 0xd8, 0x95, 0x27,
|
||||
0x3c, 0x48, 0xa5, 0x56, 0xce, 0x62, 0xf0, 0x39, 0xb4, 0xf3, 0x50, 0x20, 0xdb, 0x50, 0xb9, 0x64,
|
||||
0x4b, 0x0d, 0x7f, 0xd9, 0x24, 0x43, 0xa8, 0x5e, 0x51, 0x2f, 0x66, 0x08, 0x79, 0x0d, 0x44, 0x35,
|
||||
0xc4, 0x52, 0x8a, 0x5f, 0x94, 0x9f, 0x96, 0xcc, 0xbf, 0x57, 0x61, 0x4b, 0x82, 0x8f, 0x7c, 0x08,
|
||||
0x1d, 0x8f, 0xd1, 0x88, 0x4d, 0x83, 0x50, 0x2e, 0x10, 0xe1, 0x54, 0xad, 0xbd, 0x6d, 0x39, 0xec,
|
||||
0x58, 0x2a, 0xbe, 0x56, 0x72, 0xab, 0xed, 0xe5, 0x7a, 0x32, 0xa4, 0x5d, 0x5f, 0x30, 0xee, 0x53,
|
||||
0x6f, 0x8a, 0xc1, 0xa0, 0x02, 0xac, 0x9d, 0x08, 0x9f, 0xc9, 0xa0, 0x58, 0xc5, 0x51, 0x65, 0x1d,
|
||||
0x47, 0x03, 0x68, 0xa0, 0xef, 0x5c, 0x16, 0xe9, 0x60, 0x4f, 0xfb, 0x64, 0x0f, 0x1a, 0x0b, 0x26,
|
||||
0xa8, 0x8e, 0x35, 0x19, 0x12, 0xb7, 0x93, 0x98, 0x19, 0x9f, 0x68, 0x85, 0x0a, 0x88, 0xd4, 0x6e,
|
||||
0x2d, 0x22, 0x6a, 0xeb, 0x11, 0x31, 0x80, 0x46, 0x0a, 0xba, 0xba, 0xba, 0xe1, 0xa4, 0x2f, 0x69,
|
||||
0x36, 0x64, 0xdc, 0x0d, 0x1c, 0xa3, 0x81, 0x40, 0xd1, 0x3d, 0x49, 0x92, 0x7e, 0xbc, 0x50, 0x10,
|
||||
0x6a, 0x2a, 0x92, 0xf4, 0xe3, 0xc5, 0x3a, 0x62, 0x60, 0x05, 0x31, 0x3f, 0x81, 0x2a, 0xf5, 0x5c,
|
||||
0x1a, 0x61, 0x08, 0xc9, 0x9b, 0xd5, 0x7c, 0x3f, 0xde, 0x97, 0x52, 0x4b, 0x29, 0xc9, 0x13, 0xe8,
|
||||
0xcc, 0x79, 0x10, 0x87, 0x53, 0xec, 0xb2, 0xc8, 0x68, 0xe3, 0x69, 0x57, 0xad, 0xdb, 0x68, 0xb4,
|
||||
0xaf, 0x6c, 0x64, 0x04, 0xce, 0x82, 0xd8, 0x77, 0xa6, 0xb6, 0xeb, 0xf0, 0xc8, 0xe8, 0xa0, 0xf3,
|
||||
0x00, 0x45, 0x07, 0x52, 0x22, 0x43, 0x4c, 0x85, 0x40, 0xea, 0xe0, 0x2e, 0xda, 0x74, 0x50, 0x7a,
|
||||
0x9a, 0x78, 0xf9, 0xa7, 0xd0, 0x4f, 0x12, 0x53, 0x66, 0xd9, 0x43, 0xcb, 0xed, 0x44, 0x91, 0x1a,
|
||||
0x8f, 0x60, 0x9b, 0x5d, 0x4b, 0x0a, 0x75, 0xc5, 0x74, 0x41, 0xaf, 0xa7, 0x42, 0x78, 0x3a, 0xa4,
|
||||
0xba, 0x89, 0xfc, 0x84, 0x5e, 0x4f, 0x84, 0x27, 0xe3, 0x5f, 0xad, 0x8e, 0xf1, 0xdf, 0xc7, 0x64,
|
||||
0xd4, 0x44, 0x89, 0x8c, 0xff, 0xc1, 0x2f, 0xa1, 0x53, 0xb8, 0xc2, 0x0d, 0x40, 0xde, 0xc9, 0x03,
|
||||
0xb9, 0x99, 0x07, 0xef, 0xbf, 0xb6, 0x00, 0xf0, 0x2e, 0xd5, 0xd0, 0xd5, 0x0c, 0x90, 0xbf, 0xe0,
|
||||
0xf2, 0x86, 0x0b, 0xa6, 0x9c, 0xf9, 0x42, 0x83, 0x51, 0xf7, 0xbe, 0x17, 0x87, 0x49, 0x0e, 0xa8,
|
||||
0xe6, 0x72, 0xc0, 0x7b, 0xb0, 0x25, 0x31, 0x67, 0xd4, 0x32, 0xaa, 0xce, 0x76, 0x84, 0xe8, 0x54,
|
||||
0xc8, 0x44, 0xab, 0xb5, 0x40, 0xa8, 0xaf, 0x07, 0x42, 0x1e, 0x61, 0x8d, 0x22, 0xc2, 0xde, 0x86,
|
||||
0x8e, 0xcd, 0x19, 0xe6, 0xa3, 0xa9, 0x2c, 0x30, 0x34, 0x02, 0xdb, 0x89, 0x70, 0xe2, 0x2e, 0x98,
|
||||
0xf4, 0x9f, 0xbc, 0x0c, 0x40, 0x95, 0x6c, 0x6e, 0xbc, 0xab, 0xd6, 0xc6, 0xbb, 0xc2, 0xec, 0xee,
|
||||
0x31, 0xcd, 0xe2, 0xd8, 0xce, 0x45, 0x42, 0xa7, 0x10, 0x09, 0x05, 0xb8, 0x77, 0x57, 0xe0, 0xbe,
|
||||
0x82, 0xc9, 0xde, 0x1a, 0x26, 0xdf, 0x82, 0xb6, 0x74, 0x40, 0x14, 0x52, 0x9b, 0xc9, 0x09, 0xb6,
|
||||
0x95, 0x23, 0x52, 0xd9, 0x91, 0x83, 0x11, 0x1c, 0xcf, 0x66, 0xcb, 0x8b, 0xc0, 0x63, 0x19, 0x09,
|
||||
0xb7, 0x52, 0xd9, 0x91, 0x23, 0xf7, 0x8b, 0xa8, 0x22, 0x88, 0x2a, 0x6c, 0x0f, 0x3e, 0x82, 0x66,
|
||||
0xea, 0xf5, 0x1f, 0x04, 0xa6, 0xbf, 0x96, 0xa0, 0x9d, 0x27, 0x3a, 0x39, 0x78, 0x32, 0x39, 0xc6,
|
||||
0xc1, 0x15, 0x4b, 0x36, 0x65, 0x89, 0xc0, 0x99, 0xcf, 0x5e, 0xd2, 0x99, 0xa7, 0x26, 0x68, 0x58,
|
||||
0x99, 0x40, 0x6a, 0x5d, 0xdf, 0xe6, 0x6c, 0x91, 0xa0, 0xaa, 0x62, 0x65, 0x02, 0xf2, 0x31, 0x80,
|
||||
0x1b, 0x45, 0x31, 0x53, 0x37, 0xb7, 0x85, 0x34, 0x30, 0x18, 0xab, 0xba, 0x71, 0x9c, 0xd4, 0x8d,
|
||||
0xe3, 0x49, 0x52, 0x37, 0x5a, 0x4d, 0xb4, 0xc6, 0x2b, 0xbd, 0x0d, 0x35, 0x79, 0x41, 0x93, 0x63,
|
||||
0x44, 0x5e, 0xc5, 0xd2, 0x3d, 0xf3, 0xcf, 0x50, 0x53, 0x95, 0xc5, 0xff, 0x94, 0xbc, 0xef, 0x40,
|
||||
0x43, 0xcd, 0xed, 0x3a, 0x3a, 0x56, 0xea, 0xd8, 0x3f, 0x72, 0xcc, 0xef, 0xca, 0xd0, 0xb0, 0x58,
|
||||
0x14, 0x06, 0x7e, 0xc4, 0x72, 0x95, 0x4f, 0xe9, 0x95, 0x95, 0x4f, 0x79, 0x63, 0xe5, 0x93, 0xd4,
|
||||
0x53, 0x95, 0x5c, 0x3d, 0x35, 0x80, 0x06, 0x67, 0x8e, 0xcb, 0x99, 0x2d, 0x74, 0xed, 0x95, 0xf6,
|
||||
0xa5, 0xee, 0x25, 0xe5, 0x32, 0x65, 0x47, 0x98, 0x17, 0x9a, 0x56, 0xda, 0x27, 0x8f, 0xf3, 0x05,
|
||||
0x83, 0x2a, 0xc5, 0x76, 0x54, 0xc1, 0xa0, 0xb6, 0xbb, 0xa1, 0x62, 0x78, 0x92, 0x15, 0x5e, 0x75,
|
||||
0x8c, 0xe6, 0x3b, 0xf9, 0x01, 0x9b, 0x2b, 0xaf, 0x1f, 0x2d, 0x0f, 0x7f, 0x57, 0x86, 0xed, 0xd5,
|
||||
0xbd, 0x6d, 0x40, 0xe0, 0x0e, 0x54, 0x55, 0x3e, 0xd3, 0xf0, 0x15, 0x6b, 0x99, 0xac, 0xb2, 0x42,
|
||||
0x74, 0xbf, 0x5a, 0x25, 0x8d, 0x57, 0x43, 0xaf, 0x48, 0x28, 0xef, 0xc2, 0xb6, 0x74, 0x51, 0xc8,
|
||||
0x9c, 0xac, 0x46, 0x53, 0x0c, 0xd8, 0xd3, 0xf2, 0xb4, 0x4a, 0x7b, 0x04, 0xfd, 0xc4, 0x34, 0xe3,
|
||||
0x86, 0x5a, 0xc1, 0xf6, 0x30, 0xa1, 0x88, 0xdb, 0x50, 0x3b, 0x0f, 0xf8, 0x82, 0x0a, 0x4d, 0x82,
|
||||
0xba, 0x57, 0x20, 0x39, 0x64, 0xdb, 0x86, 0xc2, 0x64, 0x22, 0x94, 0xef, 0x10, 0x49, 0x3e, 0xe9,
|
||||
0x1b, 0x01, 0x59, 0xb0, 0x61, 0x35, 0x92, 0xb7, 0x81, 0xf9, 0x5b, 0xe8, 0xad, 0x94, 0x85, 0x1b,
|
||||
0x1c, 0x99, 0x2d, 0x5f, 0x2e, 0x2c, 0x5f, 0x98, 0xb9, 0xb2, 0x32, 0xf3, 0xef, 0xa0, 0xff, 0x05,
|
||||
0xf5, 0x1d, 0x8f, 0xe9, 0xf9, 0xf7, 0xf9, 0x3c, 0x92, 0x09, 0x4e, 0xbf, 0x52, 0xa6, 0x3a, 0xfb,
|
||||
0x74, 0xac, 0xa6, 0x96, 0x1c, 0x39, 0xe4, 0x01, 0xd4, 0xb9, 0xb2, 0xd6, 0x00, 0x68, 0xe5, 0xea,
|
||||
0x56, 0x2b, 0xd1, 0x99, 0xdf, 0x02, 0x29, 0x4c, 0x2d, 0x1f, 0x28, 0x4b, 0x32, 0x92, 0xe8, 0x57,
|
||||
0xa0, 0xd0, 0x51, 0xd5, 0xce, 0x63, 0xd2, 0x4a, 0xb5, 0x64, 0x08, 0x15, 0xc6, 0xb9, 0x5e, 0x02,
|
||||
0x0b, 0xc7, 0xec, 0x39, 0x68, 0x49, 0x95, 0xf9, 0x33, 0xe8, 0x9f, 0x85, 0xcc, 0x76, 0xa9, 0x87,
|
||||
0x4f, 0x39, 0xb5, 0xc0, 0x7d, 0xa8, 0x4a, 0x27, 0x27, 0x84, 0xd1, 0xc4, 0x81, 0xa8, 0x56, 0x72,
|
||||
0xf3, 0x5b, 0x30, 0xd4, 0xbe, 0x0e, 0xaf, 0xdd, 0x48, 0x30, 0xdf, 0x66, 0x07, 0x17, 0xcc, 0xbe,
|
||||
0xfc, 0x11, 0x4f, 0x7e, 0x05, 0x77, 0x36, 0xad, 0x90, 0xec, 0xaf, 0x65, 0xcb, 0xde, 0xf4, 0x5c,
|
||||
0xe6, 0x0e, 0x5c, 0xa3, 0x61, 0x01, 0x8a, 0x3e, 0x97, 0x12, 0x79, 0x8f, 0x4c, 0x8e, 0x8b, 0x34,
|
||||
0x1f, 0xeb, 0x5e, 0xe2, 0x8f, 0xca, 0xcd, 0xfe, 0xf8, 0x5b, 0x09, 0x9a, 0x67, 0x4c, 0xc4, 0x21,
|
||||
0x9e, 0xe5, 0x2e, 0x34, 0x67, 0x3c, 0xb8, 0x64, 0x3c, 0x3b, 0x4a, 0x43, 0x09, 0x8e, 0x1c, 0xf2,
|
||||
0x18, 0x6a, 0x07, 0x81, 0x7f, 0xee, 0xce, 0xf1, 0x61, 0xab, 0x89, 0x21, 0x1d, 0x3b, 0x56, 0x3a,
|
||||
0x45, 0x0c, 0xda, 0x90, 0x0c, 0xa1, 0xa5, 0x3f, 0x13, 0xbc, 0x78, 0x71, 0xf4, 0x2c, 0xa9, 0x78,
|
||||
0x73, 0xa2, 0xc1, 0xc7, 0xd0, 0xca, 0x0d, 0xfc, 0x41, 0xa9, 0xea, 0xff, 0x01, 0x70, 0x75, 0xe5,
|
||||
0xa3, 0x6d, 0x75, 0x54, 0x3d, 0x52, 0x1e, 0xed, 0x3e, 0x34, 0x65, 0x71, 0xa5, 0xd4, 0x49, 0x92,
|
||||
0x2c, 0x65, 0x49, 0xd2, 0x7c, 0x00, 0xfd, 0x23, 0xff, 0x8a, 0x7a, 0xae, 0x43, 0x05, 0xfb, 0x92,
|
||||
0x2d, 0xd1, 0x05, 0x6b, 0x3b, 0x30, 0xcf, 0xa0, 0xad, 0x5f, 0xda, 0xaf, 0xb5, 0xc7, 0xb6, 0xde,
|
||||
0xe3, 0xf7, 0x07, 0xd1, 0xbb, 0xd0, 0xd3, 0x93, 0x1e, 0xbb, 0x3a, 0x84, 0x64, 0x8d, 0xc1, 0xd9,
|
||||
0xb9, 0x7b, 0xad, 0xa7, 0xd6, 0x3d, 0xf3, 0x29, 0x6c, 0xe7, 0x4c, 0xd3, 0xe3, 0x5c, 0xb2, 0x65,
|
||||
0x94, 0x7c, 0x81, 0x90, 0xed, 0xc4, 0x03, 0xe5, 0xcc, 0x03, 0x26, 0x74, 0xf5, 0xc8, 0xe7, 0x4c,
|
||||
0xdc, 0x70, 0xba, 0x2f, 0xd3, 0x8d, 0x3c, 0x67, 0x7a, 0xf2, 0x87, 0x50, 0x65, 0xf2, 0xa4, 0xf9,
|
||||
0xfc, 0x99, 0xf7, 0x80, 0xa5, 0xd4, 0x1b, 0x16, 0x7c, 0x9a, 0x2e, 0x78, 0x1a, 0xab, 0x05, 0x5f,
|
||||
0x73, 0x2e, 0xf3, 0xed, 0x74, 0x1b, 0xa7, 0xb1, 0xb8, 0xe9, 0x46, 0x1f, 0x40, 0x5f, 0x1b, 0x3d,
|
||||
0x63, 0x1e, 0x13, 0xec, 0x86, 0x23, 0x3d, 0x04, 0x52, 0x30, 0xbb, 0x69, 0xba, 0x7b, 0xd0, 0x98,
|
||||
0x4c, 0x8e, 0x53, 0x6d, 0x91, 0x1b, 0xcd, 0x4f, 0xa0, 0x7f, 0x16, 0x3b, 0xc1, 0x29, 0x77, 0xaf,
|
||||
0x5c, 0x8f, 0xcd, 0xd5, 0x62, 0x49, 0xf1, 0x5b, 0xca, 0x15, 0xbf, 0x1b, 0xb3, 0x91, 0x39, 0x02,
|
||||
0x52, 0x18, 0x9e, 0xde, 0x5b, 0x14, 0x3b, 0x81, 0x0e, 0x61, 0x6c, 0x9b, 0x23, 0x68, 0x4f, 0xa8,
|
||||
0x2c, 0x36, 0x1c, 0x65, 0x63, 0x40, 0x5d, 0xa8, 0xbe, 0x36, 0x4b, 0xba, 0xe6, 0x1e, 0xec, 0x1c,
|
||||
0x50, 0xfb, 0xc2, 0xf5, 0xe7, 0xcf, 0xdc, 0x48, 0x56, 0x5b, 0x7a, 0xc4, 0x00, 0x1a, 0x8e, 0x16,
|
||||
0xe8, 0x21, 0x69, 0xdf, 0x7c, 0x1f, 0xde, 0xc8, 0x7d, 0xe6, 0x39, 0x13, 0x34, 0xf1, 0xc7, 0x0e,
|
||||
0x54, 0x23, 0xd9, 0xc3, 0x11, 0x55, 0x4b, 0x75, 0xcc, 0xaf, 0x60, 0x27, 0x9f, 0x80, 0x65, 0xed,
|
||||
0x93, 0x1c, 0x1c, 0xab, 0x92, 0x52, 0xae, 0x2a, 0xd1, 0x3e, 0x2b, 0x67, 0xf9, 0x64, 0x1b, 0x2a,
|
||||
0xbf, 0xfe, 0x66, 0xa2, 0xc1, 0x2e, 0x9b, 0xe6, 0x1f, 0xe5, 0xf2, 0xc5, 0xf9, 0xd4, 0xf2, 0x85,
|
||||
0xd2, 0xa4, 0xf4, 0x5a, 0xa5, 0xc9, 0x3a, 0xde, 0xde, 0x87, 0xfe, 0x89, 0x17, 0xd8, 0x97, 0x87,
|
||||
0x7e, 0xce, 0x1b, 0x06, 0xd4, 0x99, 0x9f, 0x77, 0x46, 0xd2, 0x35, 0xdf, 0x81, 0xde, 0x71, 0x60,
|
||||
0x53, 0xef, 0x24, 0x88, 0x7d, 0x91, 0x7a, 0x01, 0xbf, 0xbb, 0x69, 0x53, 0xd5, 0x31, 0xdf, 0x87,
|
||||
0xae, 0x4e, 0xd1, 0xfe, 0x79, 0x90, 0x30, 0x63, 0x96, 0xcc, 0x4b, 0xc5, 0x42, 0xdf, 0x3c, 0x86,
|
||||
0x5e, 0x66, 0xae, 0xe6, 0x7d, 0x07, 0x6a, 0x4a, 0xad, 0xcf, 0xd6, 0x4b, 0x5f, 0xaf, 0xca, 0xd2,
|
||||
0xd2, 0xea, 0x0d, 0x87, 0x5a, 0x40, 0xf7, 0x14, 0xbf, 0x7f, 0x1e, 0xfa, 0x57, 0x6a, 0xb2, 0x23,
|
||||
0x20, 0xea, 0x8b, 0xe8, 0x94, 0xf9, 0x57, 0x2e, 0x0f, 0x7c, 0x2c, 0xae, 0x4b, 0xba, 0x84, 0x49,
|
||||
0x26, 0x4e, 0x07, 0x25, 0x16, 0x56, 0x3f, 0x5c, 0x15, 0x6d, 0xf4, 0x21, 0x64, 0x5f, 0x57, 0x64,
|
||||
0xaa, 0xe1, 0x6c, 0x11, 0x08, 0x36, 0xa5, 0x8e, 0x93, 0x44, 0x0b, 0x28, 0xd1, 0xbe, 0xe3, 0xf0,
|
||||
0xbd, 0xff, 0x94, 0xa1, 0xfe, 0x99, 0x22, 0x70, 0xf2, 0x29, 0x74, 0x0a, 0xe9, 0x9a, 0xbc, 0x81,
|
||||
0x65, 0xdd, 0x6a, 0x71, 0x30, 0xb8, 0xbd, 0x26, 0x56, 0xe7, 0xfa, 0x00, 0xda, 0xf9, 0x64, 0x4c,
|
||||
0x30, 0xf1, 0xe2, 0xb7, 0xde, 0x01, 0xce, 0xb4, 0x9e, 0xa9, 0xcf, 0x60, 0x67, 0x53, 0x9a, 0x24,
|
||||
0xf7, 0xb2, 0x15, 0xd6, 0x53, 0xf4, 0xe0, 0xcd, 0x9b, 0xb4, 0x49, 0x7a, 0xad, 0x1f, 0x78, 0x8c,
|
||||
0xfa, 0x71, 0x98, 0xdf, 0x41, 0xd6, 0x24, 0x8f, 0xa1, 0x53, 0x48, 0x14, 0xea, 0x9c, 0x6b, 0xb9,
|
||||
0x23, 0x3f, 0xe4, 0x21, 0x54, 0x31, 0x39, 0x91, 0x4e, 0x21, 0x4b, 0x0e, 0xba, 0x69, 0x57, 0xad,
|
||||
0x3d, 0x84, 0x2d, 0xfc, 0x02, 0x98, 0x5b, 0x18, 0x47, 0xa4, 0x99, 0x6b, 0xef, 0xdf, 0x25, 0xa8,
|
||||
0x27, 0x5f, 0x85, 0x1f, 0xc3, 0x96, 0xcc, 0x01, 0xe4, 0x56, 0x8e, 0x46, 0x93, 0xfc, 0x31, 0xd8,
|
||||
0x59, 0x11, 0xaa, 0x05, 0xc6, 0x50, 0x79, 0xce, 0x04, 0x21, 0x39, 0xa5, 0x4e, 0x06, 0x83, 0x5b,
|
||||
0x45, 0x59, 0x6a, 0x7f, 0x1a, 0x17, 0xed, 0x35, 0x97, 0x17, 0xec, 0x53, 0x96, 0xfe, 0x08, 0x6a,
|
||||
0x8a, 0x65, 0x95, 0x53, 0xd6, 0xf8, 0x59, 0x5d, 0xfe, 0x3a, 0x1f, 0xef, 0xfd, 0x73, 0x0b, 0xe0,
|
||||
0x6c, 0x19, 0x09, 0xb6, 0xf8, 0x8d, 0xcb, 0x5e, 0x92, 0x47, 0xd0, 0x7b, 0xc6, 0xce, 0x69, 0xec,
|
||||
0x09, 0x7c, 0xaa, 0x49, 0x36, 0xc9, 0xf9, 0x04, 0x0b, 0xbe, 0x94, 0xac, 0x1f, 0x42, 0xeb, 0x84,
|
||||
0x5e, 0xbf, 0xda, 0xee, 0x53, 0xe8, 0x14, 0x38, 0x58, 0x6f, 0x71, 0x95, 0xd5, 0xf5, 0x16, 0xd7,
|
||||
0xd9, 0xfa, 0x21, 0xd4, 0x35, 0x33, 0xe7, 0xd7, 0xc0, 0x1c, 0x56, 0x60, 0xec, 0x9f, 0x43, 0x6f,
|
||||
0x85, 0x97, 0xf3, 0xf6, 0xf8, 0x39, 0x64, 0x23, 0x6f, 0x3f, 0x95, 0xaf, 0x9d, 0x22, 0x37, 0xe7,
|
||||
0x07, 0xea, 0x97, 0xd7, 0x26, 0xf2, 0x7e, 0x5e, 0x7c, 0x27, 0xe1, 0x13, 0xd5, 0x58, 0xa5, 0xcf,
|
||||
0x84, 0xbc, 0x07, 0x77, 0x36, 0x69, 0xd2, 0x10, 0xcc, 0x33, 0xe8, 0x5a, 0x08, 0xae, 0xd3, 0xeb,
|
||||
0x7b, 0x00, 0x19, 0x89, 0xe6, 0xed, 0x11, 0x1e, 0xab, 0xfc, 0xfa, 0x21, 0x40, 0x46, 0x8d, 0x0a,
|
||||
0x55, 0x45, 0x66, 0x55, 0xc3, 0x56, 0xe9, 0xf3, 0x11, 0x34, 0x53, 0x3a, 0xcb, 0xaf, 0x81, 0x13,
|
||||
0x14, 0xd9, 0xf1, 0xb3, 0x47, 0xbf, 0x1f, 0xcd, 0x5d, 0x71, 0x11, 0xcf, 0xc6, 0x76, 0xb0, 0xd8,
|
||||
0xbd, 0xa0, 0xd1, 0x85, 0x6b, 0x07, 0x3c, 0xdc, 0xbd, 0x92, 0x60, 0xda, 0x2d, 0xfc, 0xb4, 0x9a,
|
||||
0xd5, 0xf0, 0xa1, 0xf7, 0xe4, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5b, 0x0c, 0x01, 0xf3, 0xcc,
|
||||
0x1a, 0x00, 0x00,
|
||||
0x0c, 0x33, 0x36, 0x68, 0xd1, 0x71, 0x2c, 0x27, 0x65, 0xa7, 0x68, 0x8a, 0x96, 0x19, 0x93, 0x36,
|
||||
0x6b, 0x09, 0xc7, 0x39, 0x55, 0xc1, 0x83, 0xdd, 0x21, 0xb8, 0xc5, 0xc5, 0xee, 0x66, 0x76, 0x96,
|
||||
0x22, 0xae, 0xf2, 0x16, 0x79, 0x8d, 0xdc, 0xe6, 0x2e, 0x77, 0x29, 0x57, 0xee, 0xf3, 0x0a, 0xb9,
|
||||
0xcc, 0x33, 0xa4, 0xa6, 0x67, 0xf6, 0x04, 0x80, 0x96, 0x5c, 0xe5, 0xdc, 0xcd, 0x74, 0xf7, 0x9c,
|
||||
0x7a, 0xbe, 0xfe, 0xba, 0x67, 0x17, 0xee, 0x47, 0xce, 0xd5, 0x5e, 0xe8, 0xc5, 0x73, 0xd7, 0xdf,
|
||||
0x0b, 0x67, 0x7b, 0x33, 0x6a, 0x5f, 0x31, 0xdf, 0x19, 0x87, 0x3c, 0x10, 0x01, 0x29, 0x87, 0xb3,
|
||||
0xc1, 0xc3, 0x79, 0x10, 0xcc, 0x3d, 0xb6, 0x87, 0x92, 0x59, 0x7c, 0xb1, 0x27, 0xdc, 0x05, 0x8b,
|
||||
0x04, 0x5d, 0x84, 0xca, 0x68, 0x30, 0x90, 0x33, 0x78, 0xc1, 0xdc, 0xb5, 0xa9, 0xb7, 0xe7, 0x3a,
|
||||
0xcc, 0x17, 0xae, 0x58, 0x6a, 0x9d, 0x91, 0xd7, 0xa9, 0x55, 0x94, 0xc6, 0xac, 0x43, 0xf5, 0x68,
|
||||
0x11, 0x8a, 0xa5, 0x39, 0x84, 0xda, 0xe7, 0x8c, 0x3a, 0x8c, 0x93, 0xbb, 0x50, 0xbb, 0xc4, 0x96,
|
||||
0x51, 0x1a, 0x56, 0x46, 0x4d, 0x4b, 0xf7, 0xcc, 0x3f, 0x00, 0x9c, 0xc9, 0x31, 0x47, 0x9c, 0x07,
|
||||
0x9c, 0xdc, 0x83, 0x06, 0xe3, 0x7c, 0x2a, 0x96, 0x21, 0x33, 0x4a, 0xc3, 0xd2, 0xa8, 0x63, 0xd5,
|
||||
0x19, 0xe7, 0x93, 0x65, 0xc8, 0xc8, 0xff, 0x81, 0x6c, 0x4e, 0x17, 0xd1, 0xdc, 0x28, 0x0f, 0x4b,
|
||||
0x72, 0x06, 0xc6, 0xf9, 0x69, 0x34, 0x4f, 0xc6, 0xd8, 0x81, 0xc3, 0x8c, 0xca, 0xb0, 0x34, 0xaa,
|
||||
0xe0, 0x98, 0xc3, 0xc0, 0x61, 0xe6, 0x5f, 0x4a, 0x50, 0x3d, 0xa3, 0xe2, 0x32, 0x22, 0x04, 0xb6,
|
||||
0x78, 0x10, 0x08, 0xbd, 0x38, 0xb6, 0xc9, 0x08, 0x7a, 0xb1, 0x4f, 0x63, 0x71, 0x29, 0x4f, 0x65,
|
||||
0x53, 0xc1, 0x1c, 0xa3, 0x8c, 0xea, 0x55, 0x31, 0x79, 0x13, 0x3a, 0x5e, 0x60, 0x53, 0x6f, 0x1a,
|
||||
0x89, 0x80, 0xd3, 0xb9, 0x5c, 0x47, 0xda, 0xb5, 0x51, 0x78, 0xae, 0x64, 0x64, 0x17, 0xfa, 0x11,
|
||||
0xa3, 0xde, 0xf4, 0x05, 0xa7, 0x61, 0x6a, 0xb8, 0xa5, 0x26, 0x94, 0x8a, 0x6f, 0x38, 0x0d, 0xb5,
|
||||
0xad, 0xf9, 0xf7, 0x1a, 0xd4, 0x2d, 0xf6, 0xa7, 0x98, 0x45, 0x82, 0x74, 0xa1, 0xec, 0x3a, 0x78,
|
||||
0xda, 0xa6, 0x55, 0x76, 0x1d, 0x32, 0x06, 0x62, 0xb1, 0xd0, 0x93, 0x4b, 0xbb, 0x81, 0x7f, 0xe8,
|
||||
0xc5, 0x91, 0x60, 0x5c, 0x9f, 0x79, 0x83, 0x86, 0x3c, 0x80, 0x66, 0x10, 0x32, 0x8e, 0x32, 0x74,
|
||||
0x40, 0xd3, 0xca, 0x04, 0xf2, 0xe0, 0x21, 0x15, 0x97, 0xc6, 0x16, 0x2a, 0xb0, 0x2d, 0x65, 0x0e,
|
||||
0x15, 0xd4, 0xa8, 0x2a, 0x99, 0x6c, 0x13, 0x13, 0x6a, 0x11, 0xb3, 0x39, 0x13, 0x46, 0x6d, 0x58,
|
||||
0x1a, 0xb5, 0xf6, 0x61, 0x1c, 0xce, 0xc6, 0xe7, 0x28, 0xb1, 0xb4, 0x86, 0x3c, 0x80, 0x2d, 0xe9,
|
||||
0x17, 0xa3, 0x8e, 0x16, 0x0d, 0x69, 0x71, 0x10, 0x8b, 0x4b, 0x0b, 0xa5, 0x64, 0x1f, 0xea, 0xea,
|
||||
0x4e, 0x23, 0xa3, 0x31, 0xac, 0x8c, 0x5a, 0xfb, 0x86, 0x34, 0xd0, 0xa7, 0x1c, 0x2b, 0x18, 0x44,
|
||||
0x47, 0xbe, 0xe0, 0x4b, 0x2b, 0x31, 0x24, 0x6f, 0x40, 0xdb, 0xf6, 0x5c, 0xe6, 0x8b, 0xa9, 0x08,
|
||||
0xae, 0x98, 0x6f, 0x34, 0x71, 0x47, 0x2d, 0x25, 0x9b, 0x48, 0x11, 0xd9, 0x87, 0xd7, 0xf2, 0x26,
|
||||
0x53, 0x6a, 0xdb, 0x2c, 0x8a, 0x02, 0x6e, 0x00, 0xda, 0xde, 0xc9, 0xd9, 0x1e, 0x68, 0x95, 0x9c,
|
||||
0xd6, 0x71, 0xa3, 0xd0, 0xa3, 0xcb, 0xa9, 0x4f, 0x17, 0xcc, 0x68, 0xa9, 0x69, 0xb5, 0xec, 0x4b,
|
||||
0xba, 0x60, 0xe4, 0x21, 0xb4, 0x16, 0x41, 0xec, 0x8b, 0x69, 0x18, 0xb8, 0xbe, 0x30, 0xda, 0x68,
|
||||
0x01, 0x28, 0x3a, 0x93, 0x12, 0xf2, 0x3a, 0xa8, 0x9e, 0x02, 0x63, 0x47, 0xf9, 0x15, 0x25, 0x08,
|
||||
0xc7, 0x47, 0xd0, 0x55, 0xea, 0x74, 0x3f, 0x5d, 0x34, 0xe9, 0xa0, 0x34, 0xdd, 0xc9, 0x7b, 0xd0,
|
||||
0x44, 0x3c, 0xb8, 0xfe, 0x45, 0x60, 0xf4, 0xd0, 0x6f, 0x77, 0x72, 0x6e, 0x91, 0x98, 0x38, 0xf6,
|
||||
0x2f, 0x02, 0xab, 0xf1, 0x42, 0xb7, 0xc8, 0xc7, 0x70, 0xbf, 0x70, 0x5e, 0xce, 0x16, 0xd4, 0xf5,
|
||||
0x5d, 0x7f, 0x3e, 0x8d, 0x23, 0x16, 0x19, 0xdb, 0x88, 0x70, 0x23, 0x77, 0x6a, 0x2b, 0x31, 0xf8,
|
||||
0x3a, 0x62, 0x11, 0xb9, 0x0f, 0x4d, 0x15, 0xa4, 0x53, 0xd7, 0x31, 0xfa, 0xb8, 0xa5, 0x86, 0x12,
|
||||
0x1c, 0x3b, 0xe4, 0x2d, 0xe8, 0x85, 0x81, 0xe7, 0xda, 0xcb, 0x69, 0x70, 0xcd, 0x38, 0x77, 0x1d,
|
||||
0x66, 0x90, 0x61, 0x69, 0xd4, 0xb0, 0xba, 0x4a, 0xfc, 0x95, 0x96, 0x6e, 0x0a, 0x8d, 0x3b, 0x68,
|
||||
0xb8, 0x16, 0x1a, 0x63, 0x00, 0x3b, 0xf0, 0x7d, 0x66, 0x23, 0xfc, 0x76, 0xf0, 0x84, 0x5d, 0x79,
|
||||
0xc2, 0xc3, 0x54, 0x6a, 0xe5, 0x2c, 0x06, 0x9f, 0x41, 0x3b, 0x0f, 0x05, 0xb2, 0x0d, 0x95, 0x2b,
|
||||
0xb6, 0xd4, 0xf0, 0x97, 0x4d, 0x32, 0x84, 0xea, 0x35, 0xf5, 0x62, 0x86, 0x90, 0xd7, 0x40, 0x54,
|
||||
0x43, 0x2c, 0xa5, 0xf8, 0x45, 0xf9, 0x69, 0xc9, 0xfc, 0x77, 0x15, 0xb6, 0x24, 0xf8, 0xc8, 0x07,
|
||||
0xd0, 0xf1, 0x18, 0x8d, 0xd8, 0x34, 0x08, 0xe5, 0x02, 0x11, 0x4e, 0xd5, 0xda, 0xdf, 0x96, 0xc3,
|
||||
0x4e, 0xa4, 0xe2, 0x2b, 0x25, 0xb7, 0xda, 0x5e, 0xae, 0x27, 0x43, 0xda, 0xf5, 0x05, 0xe3, 0x3e,
|
||||
0xf5, 0xa6, 0x18, 0x0c, 0x2a, 0xc0, 0xda, 0x89, 0xf0, 0x99, 0x0c, 0x8a, 0x55, 0x1c, 0x55, 0xd6,
|
||||
0x71, 0x34, 0x80, 0x06, 0xfa, 0xce, 0x65, 0x91, 0x0e, 0xf6, 0xb4, 0x4f, 0xf6, 0xa1, 0xb1, 0x60,
|
||||
0x82, 0xea, 0x58, 0x93, 0x21, 0x71, 0x37, 0x89, 0x99, 0xf1, 0xa9, 0x56, 0xa8, 0x80, 0x48, 0xed,
|
||||
0xd6, 0x22, 0xa2, 0xb6, 0x1e, 0x11, 0x03, 0x68, 0xa4, 0xa0, 0xab, 0xab, 0x1b, 0x4e, 0xfa, 0x92,
|
||||
0x66, 0x43, 0xc6, 0xdd, 0xc0, 0x31, 0x1a, 0x08, 0x14, 0xdd, 0x93, 0x24, 0xe9, 0xc7, 0x0b, 0x05,
|
||||
0xa1, 0xa6, 0x22, 0x49, 0x3f, 0x5e, 0xac, 0x23, 0x06, 0x56, 0x10, 0xf3, 0x13, 0xa8, 0x52, 0xcf,
|
||||
0xa5, 0x11, 0x86, 0x90, 0xbc, 0x59, 0xcd, 0xf7, 0xe3, 0x03, 0x29, 0xb5, 0x94, 0x92, 0xbc, 0x0f,
|
||||
0x9d, 0x39, 0x0f, 0xe2, 0x70, 0x8a, 0x5d, 0x16, 0x19, 0x6d, 0x3c, 0xed, 0xaa, 0x75, 0x1b, 0x8d,
|
||||
0x0e, 0x94, 0x8d, 0x8c, 0xc0, 0x59, 0x10, 0xfb, 0xce, 0xd4, 0x76, 0x1d, 0x1e, 0x19, 0x1d, 0x74,
|
||||
0x1e, 0xa0, 0xe8, 0x50, 0x4a, 0x64, 0x88, 0xa9, 0x10, 0x48, 0x1d, 0xdc, 0x45, 0x9b, 0x0e, 0x4a,
|
||||
0xcf, 0x12, 0x2f, 0xff, 0x14, 0xfa, 0x49, 0x62, 0xca, 0x2c, 0x7b, 0x68, 0xb9, 0x9d, 0x28, 0x52,
|
||||
0xe3, 0x11, 0x6c, 0xb3, 0x1b, 0x49, 0xa1, 0xae, 0x98, 0x2e, 0xe8, 0xcd, 0x54, 0x08, 0x4f, 0x87,
|
||||
0x54, 0x37, 0x91, 0x9f, 0xd2, 0x9b, 0x89, 0xf0, 0x64, 0xfc, 0xab, 0xd5, 0x31, 0xfe, 0xfb, 0x98,
|
||||
0x8c, 0x9a, 0x28, 0xc1, 0xf8, 0xdf, 0x85, 0xbe, 0x1f, 0x4c, 0x1d, 0x76, 0x41, 0x63, 0x4f, 0xa8,
|
||||
0x75, 0x97, 0x3a, 0x98, 0x7a, 0x7e, 0xf0, 0x4c, 0xc9, 0x71, 0xd9, 0xe5, 0xe0, 0x97, 0xd0, 0x29,
|
||||
0x5c, 0xf7, 0x06, 0xd0, 0xef, 0xe4, 0x41, 0xdf, 0xcc, 0x03, 0xfd, 0x9f, 0x5b, 0x00, 0x78, 0xef,
|
||||
0x6a, 0xe8, 0x6a, 0xb6, 0xc8, 0x83, 0xa1, 0xbc, 0x01, 0x0c, 0x94, 0x33, 0x5f, 0x68, 0xe0, 0xea,
|
||||
0xde, 0xf7, 0x62, 0x36, 0xc9, 0x17, 0xd5, 0x5c, 0xbe, 0x78, 0x07, 0xb6, 0x24, 0x3e, 0x8d, 0x5a,
|
||||
0x46, 0xeb, 0xd9, 0x8e, 0x10, 0xc9, 0x0a, 0xc5, 0x68, 0xb5, 0x16, 0x34, 0xf5, 0xf5, 0xa0, 0xc9,
|
||||
0xa3, 0xb1, 0x51, 0x44, 0xe3, 0x9b, 0xd0, 0xb1, 0x39, 0xc3, 0xdc, 0x35, 0x95, 0xc5, 0x88, 0x46,
|
||||
0x6b, 0x3b, 0x11, 0x4e, 0xdc, 0x05, 0x93, 0xfe, 0x93, 0x17, 0x07, 0xa8, 0x92, 0xcd, 0x8d, 0xf7,
|
||||
0xda, 0xda, 0x78, 0xaf, 0x58, 0x09, 0x78, 0x4c, 0x33, 0x3e, 0xb6, 0x73, 0x51, 0xd3, 0x29, 0x44,
|
||||
0x4d, 0x21, 0x34, 0xba, 0x2b, 0xa1, 0xb1, 0x82, 0xdf, 0xde, 0x1a, 0x7e, 0xdf, 0x80, 0xb6, 0x74,
|
||||
0x40, 0x14, 0x52, 0x9b, 0xc9, 0x09, 0xb6, 0x95, 0x23, 0x52, 0xd9, 0xb1, 0x83, 0xd1, 0x1e, 0xcf,
|
||||
0x66, 0xcb, 0xcb, 0xc0, 0x63, 0x19, 0x61, 0xb7, 0x52, 0xd9, 0xb1, 0x23, 0xf7, 0x8b, 0x08, 0x24,
|
||||
0x88, 0x40, 0x6c, 0x0f, 0x3e, 0x84, 0x66, 0xea, 0xf5, 0x1f, 0x04, 0xa6, 0xbf, 0x96, 0xa0, 0x9d,
|
||||
0x27, 0x45, 0x39, 0x78, 0x32, 0x39, 0xc1, 0xc1, 0x15, 0x4b, 0x36, 0x65, 0x39, 0xc1, 0x99, 0xcf,
|
||||
0x5e, 0xd0, 0x99, 0xa7, 0x26, 0x68, 0x58, 0x99, 0x40, 0x6a, 0x5d, 0xdf, 0xe6, 0x6c, 0x91, 0xa0,
|
||||
0xaa, 0x62, 0x65, 0x02, 0xf2, 0x11, 0x80, 0x1b, 0x45, 0x31, 0x53, 0x37, 0xb7, 0x85, 0x94, 0x31,
|
||||
0x18, 0xab, 0x1a, 0x73, 0x9c, 0xd4, 0x98, 0xe3, 0x49, 0x52, 0x63, 0x5a, 0x4d, 0xb4, 0xc6, 0x2b,
|
||||
0xbd, 0x0b, 0x35, 0x79, 0x41, 0x93, 0x13, 0x44, 0x5e, 0xc5, 0xd2, 0x3d, 0xf3, 0xcf, 0x50, 0x53,
|
||||
0x55, 0xc8, 0xff, 0x94, 0xe8, 0xef, 0x41, 0x43, 0xcd, 0xed, 0x3a, 0x3a, 0x56, 0xea, 0xd8, 0x3f,
|
||||
0x76, 0xcc, 0xef, 0xca, 0xd0, 0xb0, 0x58, 0x14, 0x06, 0x7e, 0xc4, 0x72, 0x55, 0x52, 0xe9, 0xa5,
|
||||
0x55, 0x52, 0x79, 0x63, 0x95, 0x94, 0xd4, 0x5e, 0x95, 0x5c, 0xed, 0x35, 0x80, 0x06, 0x67, 0x8e,
|
||||
0xcb, 0x99, 0x2d, 0x74, 0x9d, 0x96, 0xf6, 0xa5, 0xee, 0x05, 0xe5, 0x32, 0xbd, 0x47, 0x98, 0x43,
|
||||
0x9a, 0x56, 0xda, 0x27, 0x4f, 0xf2, 0xc5, 0x85, 0x2a, 0xdb, 0x76, 0x54, 0x71, 0xa1, 0xb6, 0xbb,
|
||||
0xa1, 0xba, 0x78, 0x3f, 0x2b, 0xd2, 0xea, 0x18, 0xcd, 0xf7, 0xf2, 0x03, 0x36, 0x57, 0x69, 0x3f,
|
||||
0x5a, 0xce, 0xfe, 0xae, 0x0c, 0xdb, 0xab, 0x7b, 0xdb, 0x80, 0xc0, 0x1d, 0xa8, 0xaa, 0xdc, 0xa7,
|
||||
0xe1, 0x2b, 0xd6, 0xb2, 0x5e, 0x65, 0x85, 0xe8, 0x7e, 0xb5, 0x4a, 0x1a, 0x2f, 0x87, 0x5e, 0x91,
|
||||
0x50, 0xde, 0x86, 0x6d, 0xe9, 0xa2, 0x90, 0x39, 0x59, 0x3d, 0xa7, 0x18, 0xb0, 0xa7, 0xe5, 0x69,
|
||||
0x45, 0xb7, 0x0b, 0xfd, 0xc4, 0x34, 0xe3, 0x86, 0x5a, 0xc1, 0xf6, 0x28, 0xa1, 0x88, 0xbb, 0x50,
|
||||
0xbb, 0x08, 0xf8, 0x82, 0x0a, 0x4d, 0x82, 0xba, 0x57, 0x20, 0x39, 0x64, 0xdb, 0x86, 0xc2, 0x64,
|
||||
0x22, 0x94, 0x6f, 0x16, 0x49, 0x3e, 0xe9, 0x7b, 0x02, 0x59, 0xb0, 0x61, 0x35, 0x92, 0x77, 0x84,
|
||||
0xf9, 0x5b, 0xe8, 0xad, 0x94, 0x90, 0x1b, 0x1c, 0x99, 0x2d, 0x5f, 0x2e, 0x2c, 0x5f, 0x98, 0xb9,
|
||||
0xb2, 0x32, 0xf3, 0xef, 0xa0, 0xff, 0x39, 0xf5, 0x1d, 0x8f, 0xe9, 0xf9, 0x0f, 0xf8, 0x3c, 0x92,
|
||||
0xc9, 0x50, 0xbf, 0x68, 0xa6, 0x3a, 0xfb, 0x74, 0xac, 0xa6, 0x96, 0x1c, 0x3b, 0xe4, 0x11, 0xd4,
|
||||
0xb9, 0xb2, 0xd6, 0x00, 0x68, 0xe5, 0x6a, 0x5c, 0x2b, 0xd1, 0x99, 0xdf, 0x02, 0x29, 0x4c, 0x2d,
|
||||
0x1f, 0x33, 0x4b, 0x32, 0x92, 0xe8, 0x57, 0xa0, 0xd0, 0x51, 0xd5, 0xce, 0x63, 0xd2, 0x4a, 0xb5,
|
||||
0x64, 0x08, 0x15, 0xc6, 0xb9, 0x5e, 0x02, 0x8b, 0xcc, 0xec, 0xe9, 0x68, 0x49, 0x95, 0xf9, 0x33,
|
||||
0xe8, 0x9f, 0x87, 0xcc, 0x76, 0xa9, 0x87, 0xcf, 0x3e, 0xb5, 0xc0, 0x43, 0xa8, 0x4a, 0x27, 0x27,
|
||||
0x84, 0xd1, 0xc4, 0x81, 0xa8, 0x56, 0x72, 0xf3, 0x5b, 0x30, 0xd4, 0xbe, 0x8e, 0x6e, 0xdc, 0x48,
|
||||
0x30, 0xdf, 0x66, 0x87, 0x97, 0xcc, 0xbe, 0xfa, 0x11, 0x4f, 0x7e, 0x0d, 0xf7, 0x36, 0xad, 0x90,
|
||||
0xec, 0xaf, 0x65, 0xcb, 0xde, 0xf4, 0x42, 0xe6, 0x0e, 0x5c, 0xa3, 0x61, 0x01, 0x8a, 0x3e, 0x93,
|
||||
0x12, 0x79, 0x8f, 0x4c, 0x8e, 0x8b, 0x34, 0x1f, 0xeb, 0x5e, 0xe2, 0x8f, 0xca, 0xed, 0xfe, 0xf8,
|
||||
0x5b, 0x09, 0x9a, 0xe7, 0x4c, 0xc4, 0x21, 0x9e, 0xe5, 0x3e, 0x34, 0x67, 0x3c, 0xb8, 0x62, 0x3c,
|
||||
0x3b, 0x4a, 0x43, 0x09, 0x8e, 0x1d, 0xf2, 0x04, 0x6a, 0x87, 0x81, 0x7f, 0xe1, 0xce, 0xf1, 0x11,
|
||||
0xac, 0x89, 0x21, 0x1d, 0x3b, 0x56, 0x3a, 0x45, 0x0c, 0xda, 0x90, 0x0c, 0xa1, 0xa5, 0x3f, 0x29,
|
||||
0x7c, 0xfd, 0xf5, 0xf1, 0xb3, 0xa4, 0x3a, 0xce, 0x89, 0x06, 0x1f, 0x41, 0x2b, 0x37, 0xf0, 0x07,
|
||||
0xa5, 0xaa, 0xff, 0x07, 0xc0, 0xd5, 0x95, 0x8f, 0xb6, 0xd5, 0x51, 0xf5, 0x48, 0x79, 0xb4, 0x87,
|
||||
0xd0, 0x94, 0x85, 0x98, 0x52, 0x27, 0x49, 0xb2, 0x94, 0x25, 0x49, 0xf3, 0x11, 0xf4, 0x8f, 0xfd,
|
||||
0x6b, 0xea, 0xb9, 0x0e, 0x15, 0xec, 0x0b, 0xb6, 0x44, 0x17, 0xac, 0xed, 0xc0, 0x3c, 0x87, 0xb6,
|
||||
0x7e, 0x95, 0xbf, 0xd2, 0x1e, 0xdb, 0x7a, 0x8f, 0xdf, 0x1f, 0x44, 0x6f, 0x43, 0x4f, 0x4f, 0x7a,
|
||||
0xe2, 0xea, 0x10, 0x92, 0x35, 0x06, 0x67, 0x17, 0xee, 0x8d, 0x9e, 0x5a, 0xf7, 0xcc, 0xa7, 0xb0,
|
||||
0x9d, 0x33, 0x4d, 0x8f, 0x73, 0xc5, 0x96, 0x51, 0xf2, 0xb5, 0x42, 0xb6, 0x13, 0x0f, 0x94, 0x33,
|
||||
0x0f, 0x98, 0xd0, 0xd5, 0x23, 0x9f, 0x33, 0x71, 0xcb, 0xe9, 0xbe, 0x48, 0x37, 0xf2, 0x9c, 0xe9,
|
||||
0xc9, 0x1f, 0x43, 0x95, 0xc9, 0x93, 0xe6, 0xf3, 0x67, 0xde, 0x03, 0x96, 0x52, 0x6f, 0x58, 0xf0,
|
||||
0x69, 0xba, 0xe0, 0x59, 0xac, 0x16, 0x7c, 0xc5, 0xb9, 0xcc, 0x37, 0xd3, 0x6d, 0x9c, 0xc5, 0xe2,
|
||||
0xb6, 0x1b, 0x7d, 0x04, 0x7d, 0x6d, 0xf4, 0x8c, 0x79, 0x4c, 0xb0, 0x5b, 0x8e, 0xf4, 0x18, 0x48,
|
||||
0xc1, 0xec, 0xb6, 0xe9, 0x1e, 0x40, 0x63, 0x32, 0x39, 0x49, 0xb5, 0x45, 0x6e, 0x34, 0x3f, 0x86,
|
||||
0xfe, 0x79, 0xec, 0x04, 0x67, 0xdc, 0xbd, 0x76, 0x3d, 0x36, 0x57, 0x8b, 0x25, 0xc5, 0x6f, 0x29,
|
||||
0x57, 0xfc, 0x6e, 0xcc, 0x46, 0xe6, 0x08, 0x48, 0x61, 0x78, 0x7a, 0x6f, 0x51, 0xec, 0x04, 0x3a,
|
||||
0x84, 0xb1, 0x6d, 0x8e, 0xa0, 0x3d, 0xa1, 0xb2, 0xd8, 0x70, 0x94, 0x8d, 0x01, 0x75, 0xa1, 0xfa,
|
||||
0xda, 0x2c, 0xe9, 0x9a, 0xfb, 0xb0, 0x73, 0x48, 0xed, 0x4b, 0xd7, 0x9f, 0x3f, 0x73, 0x23, 0x59,
|
||||
0x6d, 0xe9, 0x11, 0x03, 0x68, 0x38, 0x5a, 0xa0, 0x87, 0xa4, 0x7d, 0xf3, 0x5d, 0x78, 0x2d, 0xf7,
|
||||
0x49, 0xe8, 0x5c, 0xd0, 0xc4, 0x1f, 0x3b, 0x50, 0x8d, 0x64, 0x0f, 0x47, 0x54, 0x2d, 0xd5, 0x31,
|
||||
0xbf, 0x84, 0x9d, 0x7c, 0x02, 0x96, 0xb5, 0x4f, 0x72, 0x70, 0xac, 0x4a, 0x4a, 0xb9, 0xaa, 0x44,
|
||||
0xfb, 0xac, 0x9c, 0xe5, 0x93, 0x6d, 0xa8, 0xfc, 0xfa, 0x9b, 0x89, 0x06, 0xbb, 0x6c, 0x9a, 0x7f,
|
||||
0x94, 0xcb, 0x17, 0xe7, 0x53, 0xcb, 0x17, 0x4a, 0x93, 0xd2, 0x2b, 0x95, 0x26, 0xeb, 0x78, 0x7b,
|
||||
0x17, 0xfa, 0xa7, 0x5e, 0x60, 0x5f, 0x1d, 0xf9, 0x39, 0x6f, 0x18, 0x50, 0x67, 0x7e, 0xde, 0x19,
|
||||
0x49, 0xd7, 0x7c, 0x0b, 0x7a, 0x27, 0x81, 0x4d, 0xbd, 0xd3, 0x20, 0xf6, 0x45, 0xea, 0x05, 0xfc,
|
||||
0x46, 0xa7, 0x4d, 0x55, 0xc7, 0x7c, 0x17, 0xba, 0x3a, 0x45, 0xfb, 0x17, 0x41, 0xc2, 0x8c, 0x59,
|
||||
0x32, 0x2f, 0x15, 0x0b, 0x7d, 0xf3, 0x04, 0x7a, 0x99, 0xb9, 0x9a, 0xf7, 0x2d, 0xa8, 0x29, 0xb5,
|
||||
0x3e, 0x5b, 0x2f, 0x7d, 0xe9, 0x2a, 0x4b, 0x4b, 0xab, 0x37, 0x1c, 0x6a, 0x01, 0xdd, 0x33, 0xfc,
|
||||
0x56, 0x7a, 0xe4, 0x5f, 0xab, 0xc9, 0x8e, 0x81, 0xa8, 0xaf, 0xa7, 0x53, 0xe6, 0x5f, 0xbb, 0x3c,
|
||||
0xf0, 0xb1, 0xb8, 0x2e, 0xe9, 0x12, 0x26, 0x99, 0x38, 0x1d, 0x94, 0x58, 0x58, 0xfd, 0x70, 0x55,
|
||||
0xb4, 0xd1, 0x87, 0x90, 0x7d, 0x89, 0x91, 0xa9, 0x86, 0xb3, 0x45, 0x20, 0xd8, 0x94, 0x3a, 0x4e,
|
||||
0x12, 0x2d, 0xa0, 0x44, 0x07, 0x8e, 0xc3, 0xf7, 0xff, 0x53, 0x86, 0xfa, 0xa7, 0x8a, 0xc0, 0xc9,
|
||||
0x27, 0xd0, 0x29, 0xa4, 0x6b, 0xf2, 0x1a, 0x96, 0x75, 0xab, 0xc5, 0xc1, 0xe0, 0xee, 0x9a, 0x58,
|
||||
0x9d, 0xeb, 0x3d, 0x68, 0xe7, 0x93, 0x31, 0xc1, 0xc4, 0x8b, 0xdf, 0x85, 0x07, 0x38, 0xd3, 0x7a,
|
||||
0xa6, 0x3e, 0x87, 0x9d, 0x4d, 0x69, 0x92, 0x3c, 0xc8, 0x56, 0x58, 0x4f, 0xd1, 0x83, 0xd7, 0x6f,
|
||||
0xd3, 0x26, 0xe9, 0xb5, 0x7e, 0xe8, 0x31, 0xea, 0xc7, 0x61, 0x7e, 0x07, 0x59, 0x93, 0x3c, 0x81,
|
||||
0x4e, 0x21, 0x51, 0xa8, 0x73, 0xae, 0xe5, 0x8e, 0xfc, 0x90, 0xc7, 0x50, 0xc5, 0xe4, 0x44, 0x3a,
|
||||
0x85, 0x2c, 0x39, 0xe8, 0xa6, 0x5d, 0xb5, 0xf6, 0x10, 0xb6, 0xf0, 0x6b, 0x41, 0x6e, 0x61, 0x1c,
|
||||
0x91, 0x66, 0xae, 0xfd, 0x7f, 0x95, 0xa0, 0x9e, 0x7c, 0x41, 0x7e, 0x02, 0x5b, 0x32, 0x07, 0x90,
|
||||
0x3b, 0x39, 0x1a, 0x4d, 0xf2, 0xc7, 0x60, 0x67, 0x45, 0xa8, 0x16, 0x18, 0x43, 0xe5, 0x39, 0x13,
|
||||
0x84, 0xe4, 0x94, 0x3a, 0x19, 0x0c, 0xee, 0x14, 0x65, 0xa9, 0xfd, 0x59, 0x5c, 0xb4, 0xd7, 0x5c,
|
||||
0x5e, 0xb0, 0x4f, 0x59, 0xfa, 0x43, 0xa8, 0x29, 0x96, 0x55, 0x4e, 0x59, 0xe3, 0x67, 0x75, 0xf9,
|
||||
0xeb, 0x7c, 0xbc, 0xff, 0x8f, 0x2d, 0x80, 0xf3, 0x65, 0x24, 0xd8, 0xe2, 0x37, 0x2e, 0x7b, 0x41,
|
||||
0x76, 0xa1, 0xa7, 0xbf, 0x89, 0xe0, 0x53, 0x4d, 0xb2, 0x49, 0xce, 0x27, 0x58, 0xf0, 0xa5, 0x64,
|
||||
0xfd, 0x18, 0x5a, 0xa7, 0xf4, 0xe6, 0xe5, 0x76, 0x9f, 0x40, 0xa7, 0xc0, 0xc1, 0x7a, 0x8b, 0xab,
|
||||
0xac, 0xae, 0xb7, 0xb8, 0xce, 0xd6, 0x8f, 0xa1, 0xae, 0x99, 0x39, 0xbf, 0x06, 0xe6, 0xb0, 0x02,
|
||||
0x63, 0xff, 0x1c, 0x7a, 0x2b, 0xbc, 0x9c, 0xb7, 0xc7, 0xcf, 0x21, 0x1b, 0x79, 0xfb, 0xa9, 0x7c,
|
||||
0xed, 0x14, 0xb9, 0x39, 0x3f, 0x50, 0xbf, 0xbc, 0x36, 0x91, 0xf7, 0xf3, 0xe2, 0x3b, 0x09, 0x9f,
|
||||
0xa8, 0xc6, 0x2a, 0x7d, 0x26, 0xe4, 0x3d, 0xb8, 0xb7, 0x49, 0x93, 0x86, 0x60, 0x9e, 0x41, 0xd7,
|
||||
0x42, 0x70, 0x9d, 0x5e, 0xdf, 0x01, 0xc8, 0x48, 0x34, 0x6f, 0x8f, 0xf0, 0x58, 0xe5, 0xd7, 0x0f,
|
||||
0x00, 0x32, 0x6a, 0x54, 0xa8, 0x2a, 0x32, 0xab, 0x1a, 0xb6, 0x4a, 0x9f, 0xbb, 0xd0, 0x4c, 0xe9,
|
||||
0x2c, 0xbf, 0x06, 0x4e, 0x50, 0x64, 0xc7, 0x4f, 0x77, 0x7f, 0x3f, 0x9a, 0xbb, 0xe2, 0x32, 0x9e,
|
||||
0x8d, 0xed, 0x60, 0xb1, 0x77, 0x49, 0xa3, 0x4b, 0xd7, 0x0e, 0x78, 0xb8, 0x77, 0x2d, 0xc1, 0xb4,
|
||||
0x57, 0xf8, 0xc1, 0x35, 0xab, 0xe1, 0x43, 0xef, 0xfd, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xbd,
|
||||
0xc6, 0x6e, 0xfa, 0xf8, 0x1a, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
|||
|
|
@ -210,6 +210,9 @@ message Auth {
|
|||
|
||||
// TokenType is the type of token being requested
|
||||
uint32 token_type = 17;
|
||||
|
||||
// Whether the default policy should be added automatically by core
|
||||
bool no_default_policy = 18;
|
||||
}
|
||||
|
||||
message TokenEntry {
|
||||
|
|
|
|||
|
|
@ -507,6 +507,7 @@ func LogicalAuthToProtoAuth(a *logical.Auth) (*Auth, error) {
|
|||
Policies: a.Policies,
|
||||
TokenPolicies: a.TokenPolicies,
|
||||
IdentityPolicies: a.IdentityPolicies,
|
||||
NoDefaultPolicy: a.NoDefaultPolicy,
|
||||
Metadata: a.Metadata,
|
||||
ClientToken: a.ClientToken,
|
||||
Accessor: a.Accessor,
|
||||
|
|
@ -554,6 +555,7 @@ func ProtoAuthToLogicalAuth(a *Auth) (*logical.Auth, error) {
|
|||
Policies: a.Policies,
|
||||
TokenPolicies: a.TokenPolicies,
|
||||
IdentityPolicies: a.IdentityPolicies,
|
||||
NoDefaultPolicy: a.NoDefaultPolicy,
|
||||
Metadata: a.Metadata,
|
||||
ClientToken: a.ClientToken,
|
||||
Accessor: a.Accessor,
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
import { computed } from '@ember/object';
|
||||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: 'span',
|
||||
classNames: 'tag is-outlined edition-badge',
|
||||
attributeBindings: ['edition:aria-label'],
|
||||
icon: computed('edition', function() {
|
||||
const edition = this.get('edition');
|
||||
const entEditions = ['Enterprise', 'Premium', 'Pro'];
|
||||
|
||||
if (entEditions.includes(edition)) {
|
||||
return 'edition-enterprise';
|
||||
} else {
|
||||
return 'edition-oss';
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
align-items: center;
|
||||
color: $grey;
|
||||
display: flex;
|
||||
background: $ui-gray-050;
|
||||
background: $ui-gray-010;
|
||||
justify-content: center;
|
||||
padding: $spacing-xxl $spacing-s;
|
||||
box-shadow: 0 -2px 0 -1px $ui-gray-300;
|
||||
|
|
|
|||
|
|
@ -1,63 +0,0 @@
|
|||
.upgrade-overlay {
|
||||
font-size: 1rem;
|
||||
opacity: 0;
|
||||
text-align: left;
|
||||
transition: opacity $speed-slow;
|
||||
will-change: opacity;
|
||||
z-index: 300;
|
||||
|
||||
&.is-animated {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.modal-background {
|
||||
background-image: url('/ui/vault-hex.svg'), linear-gradient(90deg, #191a1c, #1b212d);
|
||||
opacity: 0.97;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
transform: translateY(20%) scale(0.9);
|
||||
transition: transform $speed-slow;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
&.is-animated {
|
||||
.modal-content {
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.upgrade-overlay-title {
|
||||
border-bottom: 1px solid $grey;
|
||||
padding-bottom: $size-10;
|
||||
|
||||
.icon {
|
||||
width: 32px;
|
||||
|
||||
#edition-enterprise-hexagon {
|
||||
fill: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.columns {
|
||||
margin-bottom: $size-4;
|
||||
margin-top: $size-4;
|
||||
}
|
||||
|
||||
.column {
|
||||
display: flex;
|
||||
|
||||
.box {
|
||||
border-radius: $radius;
|
||||
box-shadow: inset 0 0 0 1px $grey;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
list-style: inside disc;
|
||||
}
|
||||
}
|
||||
|
|
@ -81,7 +81,6 @@
|
|||
@import './components/toolbar';
|
||||
@import './components/tool-tip';
|
||||
@import './components/unseal-warning';
|
||||
@import './components/upgrade-overlay';
|
||||
@import './components/ui-wizard';
|
||||
@import './components/vault-loading';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
{{#if icon}}
|
||||
<Icon @glyph={{icon}} />
|
||||
{{/if}}
|
||||
{{edition}}
|
||||
|
|
@ -1,76 +1,67 @@
|
|||
<div class="popup-menu-content">
|
||||
<div class="box">
|
||||
{{#if (and activeCluster.unsealed auth.currentToken)}}
|
||||
{{#if (has-permission 'status' routeParams='replication')}}
|
||||
<nav class="menu">
|
||||
<p class="menu-label">Replication</p>
|
||||
<ul>
|
||||
{{#if cluster.anyReplicationEnabled}}
|
||||
<li>
|
||||
{{#link-to
|
||||
"vault.cluster.replication.mode.index"
|
||||
"dr"
|
||||
disabled=(not currentToken)
|
||||
invokeAction=(action onLinkClick)
|
||||
}}
|
||||
{{replication-mode-summary
|
||||
mode="dr"
|
||||
display='menu'
|
||||
cluster=cluster
|
||||
}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li>
|
||||
{{#if (has-feature "Performance Replication")}}
|
||||
{{#unless version.isOSS}}
|
||||
{{#if (and activeCluster.unsealed auth.currentToken)}}
|
||||
{{#if (has-permission 'status' routeParams='replication')}}
|
||||
<nav class="menu">
|
||||
<p class="menu-label">Replication</p>
|
||||
<ul>
|
||||
{{#if cluster.anyReplicationEnabled}}
|
||||
<li>
|
||||
{{#link-to
|
||||
"vault.cluster.replication.mode.index"
|
||||
"performance"
|
||||
"dr"
|
||||
disabled=(not currentToken)
|
||||
invokeAction=(action onLinkClick)
|
||||
}}
|
||||
{{replication-mode-summary
|
||||
mode="dr"
|
||||
display='menu'
|
||||
cluster=cluster
|
||||
}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
<li>
|
||||
{{#if (has-feature "Performance Replication")}}
|
||||
{{#link-to
|
||||
"vault.cluster.replication.mode.index"
|
||||
"performance"
|
||||
disabled=(not currentToken)
|
||||
invokeAction=(action onLinkClick)
|
||||
}}
|
||||
{{replication-mode-summary
|
||||
mode="performance"
|
||||
display="menu"
|
||||
cluster=cluster
|
||||
tagName="span"
|
||||
}}
|
||||
{{/link-to}}
|
||||
{{else}}
|
||||
{{replication-mode-summary
|
||||
mode="performance"
|
||||
display="menu"
|
||||
cluster=cluster
|
||||
tagName="span"
|
||||
class="menu-item"
|
||||
}}
|
||||
{{/link-to}}
|
||||
{{else}}
|
||||
{{replication-mode-summary
|
||||
mode="performance"
|
||||
display="menu"
|
||||
cluster=cluster
|
||||
class="menu-item"
|
||||
{{/if}}
|
||||
</li>
|
||||
{{else}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.replication"
|
||||
invokeAction=(action onLinkClick)
|
||||
}}
|
||||
{{/if}}
|
||||
</li>
|
||||
{{else if version.isOSS}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.replication"}}
|
||||
<div class="level is-mobile">
|
||||
<span class="level-left">Learn more</span>
|
||||
<Icon @glyph="edition-enterprise" @class="level-right" />
|
||||
</div>
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{else}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.replication"
|
||||
invokeAction=(action onLinkClick)
|
||||
}}
|
||||
<div class="level is-mobile">
|
||||
<span class="level-left">Enable</span>
|
||||
<Icon @glyph="minus-circle-outline" @class="has-text-grey-light level-right" />
|
||||
</div>
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
<hr/>
|
||||
<div class="level is-mobile">
|
||||
<span class="level-left">Enable</span>
|
||||
<Icon @glyph="plus-circle-outline" @class="has-text-grey-light level-right" />
|
||||
</div>
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</nav>
|
||||
<hr/>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#unless version.isOSS}}
|
||||
{{#if (has-permission 'status' routeParams='license')}}
|
||||
<nav class="menu">
|
||||
<div class="menu-label">
|
||||
|
|
|
|||
|
|
@ -14,9 +14,12 @@
|
|||
</span>
|
||||
{{#if (is-version "OSS")}}
|
||||
<span>
|
||||
{{#upgrade-link linkClass="has-text-grey"}}
|
||||
<a
|
||||
href="https://hashicorp.com/products/vault/trial?source=vaultui"
|
||||
class="link has-text-grey"
|
||||
>
|
||||
Upgrade to Vault Enterprise
|
||||
{{/upgrade-link}}
|
||||
</a>
|
||||
</span>
|
||||
{{/if}}
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -28,29 +28,17 @@
|
|||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (has-permission "access" routeParams="namespaces")}}
|
||||
{{#if (and (has-feature "Namespaces") (has-permission "access" routeParams="namespaces"))}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.access.namespaces" data-test-link=true }}
|
||||
Namespaces
|
||||
{{#unless (has-feature "Namespaces")}}
|
||||
{{#if (is-version "OSS")}}
|
||||
{{edition-badge edition="Enterprise"}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (has-permission "access" routeParams="control-groups")}}
|
||||
{{#if (and (has-feature "Control Groups") (has-permission "access" routeParams="control-groups"))}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.access.control-groups" data-test-link=true current-when="vault.cluster.access.control-groups vault.cluster.access.control-group-accessor vault.cluster.access.control-groups-configure"}}
|
||||
Control Groups
|
||||
{{#unless (has-feature "Control Groups")}}
|
||||
{{#if (is-version "OSS")}}
|
||||
{{edition-badge edition="Enterprise"}}
|
||||
{{else}}
|
||||
{{edition-badge edition="Premium"}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,32 @@
|
|||
<div class="columns">
|
||||
{{#menu-sidebar title="Policies" class="is-3" data-test-sidebar=true}}
|
||||
{{#if (has-permission "policies" routeParams="acl")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "acl" data-test-link=true class=(if (is-active-route "vault.cluster.policies" "acl") "is-active")}}
|
||||
ACL Policies
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (has-permission "policies" routeParams="rgp")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "rgp" data-test-link=true class=(if (is-active-route "vault.cluster.policies" "rgp") "is-active")}}
|
||||
Role Governing Policies
|
||||
|
||||
{{#unless (has-feature "Sentinel")}}
|
||||
{{#if (is-version "OSS")}}
|
||||
{{edition-badge edition="Enterprise"}}
|
||||
{{else}}
|
||||
{{edition-badge edition="Premium"}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (has-permission "policies" routeParams="egp")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "egp" data-test-link=true class=(if (is-active-route "vault.cluster.policies" "egp") "is-active")}}
|
||||
Endpoint Governing Policies
|
||||
|
||||
{{#unless (has-feature "Sentinel")}}
|
||||
{{#if (is-version "OSS")}}
|
||||
{{edition-badge edition="Enterprise"}}
|
||||
{{else}}
|
||||
{{edition-badge edition="Premium"}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/menu-sidebar}}
|
||||
<div class="column is-9">
|
||||
{{outlet}}
|
||||
{{#if (and (has-feature "Sentinel") (or (has-permission "policies" routeParams="rgp") (has-permission "policies" routeParams="egp")))}}
|
||||
<div class="columns">
|
||||
{{#menu-sidebar title="Policies" class="is-3" data-test-sidebar=true}}
|
||||
{{#if (has-permission "policies" routeParams="acl")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "acl" data-test-link=true class=(if (is-active-route "vault.cluster.policies" "acl") "is-active")}}
|
||||
ACL Policies
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (has-permission "policies" routeParams="rgp")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "rgp" data-test-link=true class=(if (is-active-route "vault.cluster.policies" "rgp") "is-active")}}
|
||||
Role Governing Policies
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (has-permission "policies" routeParams="egp")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "egp" data-test-link=true class=(if (is-active-route "vault.cluster.policies" "egp") "is-active")}}
|
||||
Endpoint Governing Policies
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/menu-sidebar}}
|
||||
<div class="column is-9">
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
{{outlet}}
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -156,9 +156,11 @@
|
|||
>
|
||||
{{#link-to "vault.cluster.policies.create" class="link"}}
|
||||
Create {{uppercase policyType}} policy
|
||||
<Chevron />
|
||||
{{/link-to}}
|
||||
<LearnLink @path="/vault/getting-started/policies">
|
||||
Learn more
|
||||
<Chevron />
|
||||
</LearnLink>
|
||||
</EmptyState>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -7,33 +7,21 @@
|
|||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (has-permission "policies" routeParams="rgp")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "rgp" data-test-link=true class=(if (is-active-route "vault.cluster.policy" "rgp") "is-active")}}
|
||||
Role Governing Policies
|
||||
{{#unless (has-feature "Sentinel")}}
|
||||
{{#if (is-version "OSS")}}
|
||||
{{edition-badge edition="Enterprise"}}
|
||||
{{else}}
|
||||
{{edition-badge edition="Premium"}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (has-permission "policies" routeParams="egp")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "egp" data-test-link=true class=(if (is-active-route "vault.cluster.policy" "egp") "is-active")}}
|
||||
Endpoint Governing Policies
|
||||
{{#unless (has-feature "Sentinel")}}
|
||||
{{#if (is-version "OSS")}}
|
||||
{{edition-badge edition="Enterprise"}}
|
||||
{{else}}
|
||||
{{edition-badge edition="Premium"}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{#if (has-feature "Sentinel")}}
|
||||
{{#if (has-permission "policies" routeParams="rgp")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "rgp" data-test-link=true class=(if (is-active-route "vault.cluster.policy" "rgp") "is-active")}}
|
||||
Role Governing Policies
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#if (has-permission "policies" routeParams="egp")}}
|
||||
<li>
|
||||
{{#link-to "vault.cluster.policies" "egp" data-test-link=true class=(if (is-active-route "vault.cluster.policy" "egp") "is-active")}}
|
||||
Endpoint Governing Policies
|
||||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/menu-sidebar}}
|
||||
<div class="column is-9">
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
import { later } from '@ember/runloop';
|
||||
import Component from '@ember/component';
|
||||
import { computed } from '@ember/object';
|
||||
import layout from '../templates/components/upgrade-link';
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
modalContainer: computed('isActive', function() {
|
||||
return document.getElementById('modal-wormhole');
|
||||
}),
|
||||
isAnimated: false,
|
||||
isActive: false,
|
||||
tagName: 'span',
|
||||
trackingSource: computed('pageName', function() {
|
||||
let trackingSource = 'vaultui';
|
||||
let pageName = this.get('pageName');
|
||||
if (pageName) {
|
||||
trackingSource = trackingSource + '_' + encodeURIComponent(pageName);
|
||||
}
|
||||
return trackingSource;
|
||||
}),
|
||||
actions: {
|
||||
openOverlay() {
|
||||
this.set('isActive', true);
|
||||
later(
|
||||
this,
|
||||
function() {
|
||||
this.set('isAnimated', true);
|
||||
},
|
||||
10
|
||||
);
|
||||
},
|
||||
closeOverlay() {
|
||||
this.set('isAnimated', false);
|
||||
later(
|
||||
this,
|
||||
function() {
|
||||
this.set('isActive', false);
|
||||
},
|
||||
300
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -7,7 +7,7 @@ export default Component.extend({
|
|||
title: 'Vault Enterprise',
|
||||
featureName: computed('title', function() {
|
||||
let title = this.get('title');
|
||||
return title === 'Vault Enterprise' ? 'This' : title;
|
||||
return title === 'Vault Enterprise' ? 'this feature' : title;
|
||||
}),
|
||||
minimumEdition: 'Vault Enterprise',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<div class="empty-state" ...attributes>
|
||||
<div class="empty-state-content">
|
||||
<h3 class="empty-state-title">
|
||||
<h3 class="empty-state-title" data-test-empty-state-title>
|
||||
{{title}}
|
||||
</h3>
|
||||
{{#if message}}
|
||||
|
|
|
|||
|
|
@ -58,10 +58,14 @@
|
|||
Performance Replication is a feature of Vault Enterprise Premium.
|
||||
</p>
|
||||
<p class="has-text-centered">
|
||||
{{#upgrade-link linkClass="button is-ghost has-icon-right" pageName="Performance Replication"}}
|
||||
<a
|
||||
href="https://hashicorp.com/products/vault/trial?source=vaultui_Performance%20Replication"
|
||||
class="button is-ghost has-icon-right"
|
||||
data-test-upgrade-link="true"
|
||||
>
|
||||
Learn more
|
||||
<Icon @glyph="chevron-right" />
|
||||
{{/upgrade-link}}
|
||||
<Chevron />
|
||||
</a>
|
||||
</p>
|
||||
{{else if replicationEnabled}}
|
||||
<h5 class="title is-7 is-uppercase is-marginless">
|
||||
|
|
|
|||
|
|
@ -1,79 +0,0 @@
|
|||
<button class="link {{linkClass}}" {{action "openOverlay"}}>
|
||||
{{yield}}
|
||||
</button>
|
||||
|
||||
{{#maybe-in-element modalContainer false}}
|
||||
<div id="upgrade-modal" class="modal upgrade-overlay has-text-white {{if isActive "is-active"}} {{if isAnimated "is-animated"}}">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-content">
|
||||
<h2 class="title upgrade-overlay-title is-2 has-text-white">
|
||||
<Icon @glyph="edition-enterprise" aria-hidden="true" @size="xl" />
|
||||
Try Vault Enterprise free for 30 days
|
||||
</h2>
|
||||
<h3 class="title is-5 has-text-white">
|
||||
Collaborate on secrets management and access
|
||||
</h3>
|
||||
<p>
|
||||
Vault Enterprise has features to help unify disparate users and roles,
|
||||
use collaboration workflows, and disaster recovery for system recovery,
|
||||
provide governance over secrets management and access with multi-factor
|
||||
authentication. You'll have access to all the features below.
|
||||
</p>
|
||||
<div class="columns">
|
||||
<div class="column is-flex">
|
||||
<div class="box has-background-transparent has-text-white ">
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<h3 class="title is-4 has-text-white">
|
||||
Pro
|
||||
{{#unless (is-version "OSS")}}
|
||||
{{#unless version.hasPerfReplication}}
|
||||
{{edition-badge edition="Current"}}
|
||||
{{/unless}}
|
||||
{{/unless}}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="upgrade-features-list">
|
||||
<li>All Open Source features</li>
|
||||
<li>Disaster Recovery Replication</li>
|
||||
<li>Cluster management</li>
|
||||
<li>Init and unseal workflow</li>
|
||||
<li>GCP Cloud KMS Auto-unseal</li>
|
||||
<li>Silver support: 9x5 support w/SLA</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-flex">
|
||||
<div class="box has-background-transparent has-text-white">
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<h3 class="title is-4 has-text-white">
|
||||
Premium
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="upgrade-features-list">
|
||||
<li>All Pro features</li>
|
||||
<li>Performance Replication</li>
|
||||
<li>HSM Autounseal</li>
|
||||
<li>Mount Filters</li>
|
||||
<li>Multi-Factor Authentication</li>
|
||||
<li>Sentinel Integration</li>
|
||||
<li>Control Groups</li>
|
||||
<li>Seal Wrap / FIPS 140-2 Compliance</li>
|
||||
<li>Gold support: 24×7 support w/SLA</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="has-text-centered">
|
||||
<a href="https://hashicorp.com/products/vault/trial?source={{trackingSource}}" class="button is-primary" target="_blank" rel="noreferrer noopener">
|
||||
Start trial
|
||||
<Chevron @isButton={{true}} />
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<button class="modal-close is-large" aria-label="close" {{action "closeOverlay"}}></button>
|
||||
</div>
|
||||
{{/maybe-in-element}}
|
||||
|
|
@ -6,17 +6,18 @@
|
|||
</p.levelLeft>
|
||||
</PageHeader>
|
||||
|
||||
<div class="box is-sideless is-bottomless has-text-centered has-background-white-bis">
|
||||
<p class="has-text-grey-dark">
|
||||
<span data-test-upgrade-feature-description>
|
||||
{{featureName}} is a {{minimumEdition}} feature.
|
||||
</span>
|
||||
You can upgrade to {{minimumEdition}} to unlock additional collaboration and security features
|
||||
</p>
|
||||
<p>
|
||||
{{#upgrade-link linkClass="button is-ghost has-icon-right" data-test-upgrade-link="true" pageName=featureName}}
|
||||
Vault Enterprise
|
||||
<Chevron />
|
||||
{{/upgrade-link}}
|
||||
</p>
|
||||
</div>
|
||||
<EmptyState
|
||||
@title="Upgrade to use {{featureName}}"
|
||||
@message="You will need {{minimumEdition}} with {{featureName}} included to use this feature."
|
||||
>
|
||||
<a
|
||||
href="https://www.hashicorp.com/products/vault/enterprise?source=vaultui_{{featureName}}"
|
||||
class="link has-icon-right"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
data-test-upgrade-link="true"
|
||||
>
|
||||
Vault Enterprise
|
||||
<Chevron />
|
||||
</a>
|
||||
</EmptyState>
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
export { default } from 'core/components/upgrade-link';
|
||||
|
|
@ -58,14 +58,14 @@
|
|||
Performance Replication
|
||||
</h3>
|
||||
{{#if (not (has-feature "Performance Replication"))}}
|
||||
<p class="help has-text-grey-dark">
|
||||
Performance Replication is a feature of {{#upgrade-link pageName="Performance Replication"}}Vault Enterprise Premium{{/upgrade-link}}
|
||||
</p>
|
||||
{{else}}
|
||||
<p class="help has-text-grey-dark">
|
||||
Performance replication scales workloads horizontally across clusters to make requests faster. Local secondaries handle read requests but forward writes to the primary to be handled.
|
||||
</p>
|
||||
{{/if}}
|
||||
<p class="help has-text-grey-dark">
|
||||
Performance Replication is a feature of Vault Enterprise Premium
|
||||
</p>
|
||||
{{else}}
|
||||
<p class="help has-text-grey-dark">
|
||||
Performance replication scales workloads horizontally across clusters to make requests faster. Local secondaries handle read requests but forward writes to the primary to be handled.
|
||||
</p>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<p class="has-text-grey-dark box is-shadowless is-fullwidth has-slim-padding">
|
||||
|
|
@ -111,13 +111,10 @@
|
|||
@glyph="perf-replication"
|
||||
/>
|
||||
Performance
|
||||
{{#if (not (has-feature "Performance Replication"))}}
|
||||
{{edition-badge edition="Premium"}}
|
||||
{{/if}}
|
||||
</h3>
|
||||
{{#if (not (has-feature "Performance Replication"))}}
|
||||
<p class="help has-text-grey-dark">
|
||||
Performance Replication is a feature of {{#upgrade-link pageName="Performance Replication"}}Vault Enterprise Premium{{/upgrade-link}}
|
||||
Performance Replication is a feature of Vault Enterprise Premium
|
||||
</p>
|
||||
{{else}}
|
||||
<p class="help has-text-grey-dark">
|
||||
|
|
|
|||
|
|
@ -139,7 +139,6 @@
|
|||
"@storybook/ember": "^5.0.5",
|
||||
"@storybook/ember-cli-storybook": "meirish/ember-cli-storybook#6bd58326d8c21e986d390b541ae5e49089d61b93",
|
||||
"babel-loader": "^8.0.5",
|
||||
"husky": "^1.1.3",
|
||||
"jsdoc-to-markdown": "^4.0.1",
|
||||
"lint-staged": "^8.0.4"
|
||||
},
|
||||
|
|
@ -154,10 +153,5 @@
|
|||
"lib/replication"
|
||||
]
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="c">
|
||||
<stop stop-color="#FFF" stop-opacity=".25" offset="0%"/>
|
||||
<stop stop-color="#FFF" stop-opacity=".5" offset="100%"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<mask id="b" fill="#fff">
|
||||
<path d="M14 9.079V4.625L8 1.25 2 4.625v6.75l6 3.375 6-3.375V9.079zm-.5.264l-1 .529V5.5L8 3 3.5 5.5v4.372l-1-.529V4.875L8.001 1.75 13.5 4.875v4.468zM8.192 12.15l-.191.1L4 10.126v-4.25L8.001 3.75 12 5.875v4.25l-3.808 2.024zM8 0l7 4v8l-7 4-7-4V4l7-4zm0 13l5.5-3.1v1.2L8 14.25 2.5 11.1V9.9L8 13z"/>
|
||||
</mask>
|
||||
<g mask="url(#b)">
|
||||
<path d="M0 0h16v16H0z" id="edition-enterprise-hexagon" fill="#6a7786"/>
|
||||
</g>
|
||||
<path fill="url(#c)" opacity=".5" mask="url(#b)" d="M8 0l7 4v8l-7 4z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 895 B |
|
|
@ -1,17 +0,0 @@
|
|||
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<defs>
|
||||
<path d="M8 0l7 4v8l-7 4-7-4V4l7-4zm0 1.25L2 4.625v6.75l6 3.375 6-3.375v-6.75L8 1.25zm.001.5L13.5 4.875v6.25L8.001 14.25 2.5 11.125v-6.25L8.001 1.75z" id="a"/>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="c">
|
||||
<stop stop-color="#FFF" stop-opacity=".25" offset="0%"/>
|
||||
<stop stop-color="#FFF" stop-opacity=".5" offset="100%"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<mask id="b" fill="#fff">
|
||||
<use href="#a"/>
|
||||
</mask>
|
||||
<use fill="#fff" href="#a"/>
|
||||
<g mask="url(#b)" fill="#BAC1CC"><path d="M0 0h16v16H0z"/></g>
|
||||
<path fill="url(#c)" opacity=".5" mask="url(#b)" d="M8 0l7 4v8l-7 4z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 769 B |
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="74px" height="128px" viewBox="0 0 74 128" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="vault-hex" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.0299999993">
|
||||
<path d="M36,-1.96752179 L73.7513243,62 L-1.75132433,62 L36,-1.96752179 Z" id="Triangle" stroke="#FFFFFF" stroke-width="2"></path>
|
||||
<rect id="Rectangle" fill="#FFFFFF" x="0" y="125" width="72" height="2"></rect>
|
||||
<path d="M36,61.0324782 L73.7513243,125 L-1.75132433,125 L36,61.0324782 Z" id="Triangle" stroke="#FFFFFF" stroke-width="2" transform="translate(36.000000, 93.500000) scale(1, -1) translate(-36.000000, -93.500000) "></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 753 B |
|
|
@ -1,22 +0,0 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, find } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
module('Integration | Component | edition badge', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function(assert) {
|
||||
await render(hbs`
|
||||
{{edition-badge edition="Custom"}}
|
||||
`);
|
||||
|
||||
assert.equal(find('.edition-badge').textContent.trim(), 'Custom', 'contains edition');
|
||||
|
||||
await render(hbs`
|
||||
{{edition-badge edition="Enterprise"}}
|
||||
`);
|
||||
|
||||
assert.equal(find('.edition-badge').textContent.trim(), 'Enterprise', 'renders edition');
|
||||
});
|
||||
});
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, find, findAll } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
module('Integration | Component | upgrade link', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders with overlay', async function(assert) {
|
||||
await render(hbs`
|
||||
<div id="modal-wormhole"></div>
|
||||
<div class="upgrade-link-container">
|
||||
{{#upgrade-link data-test-link}}upgrade{{/upgrade-link}}
|
||||
</div>
|
||||
`);
|
||||
|
||||
assert.equal(
|
||||
find('.upgrade-link-container button').textContent.trim(),
|
||||
'upgrade',
|
||||
'renders link content'
|
||||
);
|
||||
assert.equal(
|
||||
find('#modal-wormhole .upgrade-overlay-title').textContent.trim(),
|
||||
'Try Vault Enterprise free for 30 days',
|
||||
'contains overlay content'
|
||||
);
|
||||
assert.equal(
|
||||
findAll('#modal-wormhole a[href^="https://hashicorp.com/products/vault/trial?source=vaultui"]').length,
|
||||
1,
|
||||
'contains info link'
|
||||
);
|
||||
});
|
||||
|
||||
test('it adds custom classes', async function(assert) {
|
||||
await render(hbs`
|
||||
<div id="modal-wormhole"></div>
|
||||
<div class="upgrade-link-container">
|
||||
{{#upgrade-link linkClass="button upgrade-button"}}upgrade{{/upgrade-link}}
|
||||
</div>
|
||||
`);
|
||||
|
||||
assert.equal(
|
||||
find('.upgrade-link-container button').getAttribute('class'),
|
||||
'link button upgrade-button',
|
||||
'adds classes to link'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -12,30 +12,44 @@ module('Integration | Component | upgrade page', function(hooks) {
|
|||
<div id="modal-wormhole"></div>
|
||||
`);
|
||||
|
||||
assert.equal(find('.page-header .title').textContent.trim(), 'Vault Enterprise', 'renders default title');
|
||||
assert.equal(
|
||||
find('[data-test-upgrade-feature-description]').textContent.trim(),
|
||||
'This is a Vault Enterprise feature.',
|
||||
'renders default description'
|
||||
find('.page-header .title').textContent.trim(),
|
||||
'Vault Enterprise',
|
||||
'renders default page title'
|
||||
);
|
||||
assert.equal(
|
||||
find('[data-test-empty-state-title]').textContent.trim(),
|
||||
'Upgrade to use this feature',
|
||||
'renders default title'
|
||||
);
|
||||
assert.equal(
|
||||
find('[data-test-empty-state-message]').textContent.trim(),
|
||||
'You will need Vault Enterprise with this feature included to use this feature.',
|
||||
'renders default message'
|
||||
);
|
||||
assert.equal(findAll('[data-test-upgrade-link]').length, 1, 'renders upgrade link');
|
||||
});
|
||||
|
||||
test('it renders with custom attributes', async function(assert) {
|
||||
await render(hbs`
|
||||
{{upgrade-page title="Test Feature Title" featureName="Specific Feature Name" minimumEdition="Premium"}}
|
||||
{{upgrade-page title="Test Feature Title" featureName="Specific Feature Name" minimumEdition="Vault Enterprise Premium"}}
|
||||
<div id="modal-wormhole"></div>
|
||||
`);
|
||||
|
||||
assert.equal(
|
||||
find('.page-header .title').textContent.trim(),
|
||||
'Test Feature Title',
|
||||
'renders default title'
|
||||
'renders custom page title'
|
||||
);
|
||||
assert.equal(
|
||||
find('[data-test-upgrade-feature-description]').textContent.trim(),
|
||||
'Specific Feature Name is a Premium feature.',
|
||||
'renders default description'
|
||||
find('[data-test-empty-state-title]').textContent.trim(),
|
||||
'Upgrade to use Specific Feature Name',
|
||||
'renders custom title'
|
||||
);
|
||||
assert.equal(
|
||||
find('[data-test-empty-state-message]').textContent.trim(),
|
||||
'You will need Vault Enterprise Premium with Specific Feature Name included to use this feature.',
|
||||
'renders custom message'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
57
ui/yarn.lock
57
ui/yarn.lock
|
|
@ -5479,11 +5479,6 @@ ci-info@^1.3.0, ci-info@^1.4.0:
|
|||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.5.0.tgz#38327c69e98dab18487744b84e5d6e841a09a1a7"
|
||||
integrity sha512-Bx/xWOzip4whERIvC97aIHjWCa8FxEn0ezng0oVn4kma6p+90Fbs3bTcJw6ZL0da2EPHydxsXJPZxNUv5oWb1Q==
|
||||
|
||||
ci-info@^1.5.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
|
||||
integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
|
||||
|
||||
cidr-regex@^2.0.8:
|
||||
version "2.0.9"
|
||||
resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-2.0.9.tgz#9c17bb2b18e15af07f7d0c3b994b961d687ed1c9"
|
||||
|
|
@ -6194,7 +6189,7 @@ cosmiconfig@^5.0.1:
|
|||
js-yaml "^3.9.0"
|
||||
parse-json "^4.0.0"
|
||||
|
||||
cosmiconfig@^5.0.2, cosmiconfig@^5.0.6:
|
||||
cosmiconfig@^5.0.2:
|
||||
version "5.0.7"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.7.tgz#39826b292ee0d78eda137dfa3173bd1c21a43b04"
|
||||
integrity sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==
|
||||
|
|
@ -8578,19 +8573,6 @@ execa@^0.7.0:
|
|||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
execa@^0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-0.9.0.tgz#adb7ce62cf985071f60580deb4a88b9e34712d01"
|
||||
integrity sha512-BbUMBiX4hqiHZUA5+JujIjNb6TyAlp2D5KLheMjMluwOuzcnylDL4AxZYLLn1n2AGB49eSWwyKvvEQoRpnAtmA==
|
||||
dependencies:
|
||||
cross-spawn "^5.0.1"
|
||||
get-stream "^3.0.0"
|
||||
is-stream "^1.1.0"
|
||||
npm-run-path "^2.0.0"
|
||||
p-finally "^1.0.0"
|
||||
signal-exit "^3.0.0"
|
||||
strip-eof "^1.0.0"
|
||||
|
||||
execa@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
|
||||
|
|
@ -10242,22 +10224,6 @@ humanize-ms@^1.2.1:
|
|||
dependencies:
|
||||
ms "^2.0.0"
|
||||
|
||||
husky@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/husky/-/husky-1.1.3.tgz#3ccfdb4d7332896bf7cd0e618c6fb8be09d9de4b"
|
||||
integrity sha512-6uc48B/A2Mqi65yeg37d/TPcTb0bZ1GTkMYOM0nXLOPuPaTRhXCeee80/noOrbavWd12x72Tusja7GJ5rzvV6g==
|
||||
dependencies:
|
||||
cosmiconfig "^5.0.6"
|
||||
execa "^0.9.0"
|
||||
find-up "^3.0.0"
|
||||
get-stdin "^6.0.0"
|
||||
is-ci "^1.2.1"
|
||||
pkg-dir "^3.0.0"
|
||||
please-upgrade-node "^3.1.1"
|
||||
read-pkg "^4.0.1"
|
||||
run-node "^1.0.0"
|
||||
slash "^2.0.0"
|
||||
|
||||
iconv-lite@0.4.19:
|
||||
version "0.4.19"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
|
||||
|
|
@ -10676,13 +10642,6 @@ is-ci@^1.0.10:
|
|||
dependencies:
|
||||
ci-info "^1.3.0"
|
||||
|
||||
is-ci@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
|
||||
integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
|
||||
dependencies:
|
||||
ci-info "^1.5.0"
|
||||
|
||||
is-cidr@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-2.0.6.tgz#4b01c9693d8e18399dacd18a4f3d60ea5871ac60"
|
||||
|
|
@ -14388,7 +14347,7 @@ pkg-up@2.0.0, pkg-up@^2.0.0:
|
|||
dependencies:
|
||||
find-up "^2.1.0"
|
||||
|
||||
please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1:
|
||||
please-upgrade-node@^3.0.2:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac"
|
||||
integrity sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==
|
||||
|
|
@ -15344,7 +15303,7 @@ read-pkg@^3.0.0:
|
|||
normalize-package-data "^2.3.2"
|
||||
path-type "^3.0.0"
|
||||
|
||||
read-pkg@^4.0.0, read-pkg@^4.0.1:
|
||||
read-pkg@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237"
|
||||
integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc=
|
||||
|
|
@ -16031,11 +15990,6 @@ run-async@^2.2.0:
|
|||
dependencies:
|
||||
is-promise "^2.1.0"
|
||||
|
||||
run-node@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e"
|
||||
integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==
|
||||
|
||||
run-queue@^1.0.0, run-queue@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
|
||||
|
|
@ -16511,11 +16465,6 @@ slash@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
|
||||
integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
|
||||
|
||||
slash@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
|
||||
integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
|
||||
|
||||
slice-ansi@0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
|
||||
|
|
|
|||
|
|
@ -287,6 +287,7 @@ func (b *AESGCMBarrier) ReloadKeyring(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// Setup the keyring and finish
|
||||
b.cache = make(map[uint32]cipher.AEAD)
|
||||
b.keyring = keyring
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -516,3 +516,82 @@ func TestEncrypt_BarrierEncryptor(t *testing.T) {
|
|||
t.Fatalf("bad: %s", plain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAESGCMBarrier_ReloadKeyring(t *testing.T) {
|
||||
inm, err := inmem.NewInmem(nil, logger)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
b, err := NewAESGCMBarrier(inm)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
// Initialize and unseal
|
||||
key, _ := b.GenerateKey()
|
||||
b.Initialize(context.Background(), key)
|
||||
b.Unseal(context.Background(), key)
|
||||
|
||||
keyringRaw, err := inm.Get(context.Background(), keyringPath)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
// Encrypt something to test cache invalidation
|
||||
_, err = b.Encrypt(context.Background(), "foo", []byte("quick brown fox"))
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
{
|
||||
// Create a second barrier and rotate the keyring
|
||||
b2, err := NewAESGCMBarrier(inm)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
b2.Unseal(context.Background(), key)
|
||||
_, err = b2.Rotate(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Reload the keyring on the first
|
||||
err = b.ReloadKeyring(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if b.keyring.ActiveTerm() != 2 {
|
||||
t.Fatal("failed to reload keyring")
|
||||
}
|
||||
if len(b.cache) != 0 {
|
||||
t.Fatal("failed to clear cache")
|
||||
}
|
||||
|
||||
// Encrypt something to test cache invalidation
|
||||
_, err = b.Encrypt(context.Background(), "foo", []byte("quick brown fox"))
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
// Restore old keyring to test rolling back
|
||||
err = inm.Put(context.Background(), keyringRaw)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
// Reload the keyring on the first
|
||||
err = b.ReloadKeyring(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if b.keyring.ActiveTerm() != 1 {
|
||||
t.Fatal("failed to reload keyring")
|
||||
}
|
||||
if len(b.cache) != 0 {
|
||||
t.Fatal("failed to clear cache")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -427,6 +427,8 @@ type Core struct {
|
|||
|
||||
// Stores request counters
|
||||
counters counters
|
||||
|
||||
coreNumber int
|
||||
}
|
||||
|
||||
// CoreConfig is used to parameterize a core
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ import (
|
|||
"github.com/hashicorp/vault/sdk/version"
|
||||
)
|
||||
|
||||
type ctxKeyForwardedRequestMountAccessor struct{}
|
||||
|
||||
func (c ctxKeyForwardedRequestMountAccessor) String() string {
|
||||
return "forwarded-req-mount-accessor"
|
||||
}
|
||||
|
||||
type dynamicSystemView struct {
|
||||
core *Core
|
||||
mountEntry *MountEntry
|
||||
|
|
@ -33,6 +39,17 @@ func (e extendedSystemView) Auditor() logical.Auditor {
|
|||
}
|
||||
}
|
||||
|
||||
func (e extendedSystemView) ForwardGenericRequest(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
||||
// Forward the request if allowed
|
||||
if couldForward(e.core) {
|
||||
ctx = namespace.ContextWithNamespace(ctx, e.mountEntry.Namespace())
|
||||
ctx = context.WithValue(ctx, ctxKeyForwardedRequestMountAccessor{}, e.mountEntry.Accessor)
|
||||
return forward(ctx, e.core, req)
|
||||
}
|
||||
|
||||
return nil, logical.ErrReadOnly
|
||||
}
|
||||
|
||||
func (d dynamicSystemView) DefaultLeaseTTL() time.Duration {
|
||||
def, _ := d.fetchTTLs()
|
||||
return def
|
||||
|
|
|
|||
89
vault/external_tests/policy/no_default_test.go
Normal file
89
vault/external_tests/policy/no_default_test.go
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package policy
|
||||
|
||||
// This is TODO once tokenhelper is added to ldaputil
|
||||
/*
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/go-test/deep"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/builtin/credential/ldap"
|
||||
vaulthttp "github.com/hashicorp/vault/http"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/hashicorp/vault/vault"
|
||||
)
|
||||
|
||||
func TestNoDefaultPolicy(t *testing.T) {
|
||||
var err error
|
||||
coreConfig := &vault.CoreConfig{
|
||||
DisableMlock: true,
|
||||
DisableCache: true,
|
||||
Logger: hclog.NewNullLogger(),
|
||||
CredentialBackends: map[string]logical.Factory{
|
||||
"ldap": ldap.Factory,
|
||||
},
|
||||
}
|
||||
|
||||
cluster := vault.NewTestCluster(t, coreConfig, &vault.TestClusterOptions{
|
||||
HandlerFunc: vaulthttp.Handler,
|
||||
})
|
||||
|
||||
cluster.Start()
|
||||
defer cluster.Cleanup()
|
||||
|
||||
cores := cluster.Cores
|
||||
|
||||
vault.TestWaitActive(t, cores[0].Core)
|
||||
|
||||
client := cores[0].Client
|
||||
|
||||
err = client.Sys().EnableAuthWithOptions("ldap", &api.EnableAuthOptions{
|
||||
Type: "ldap",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Configure LDAP auth backend
|
||||
secret, err := client.Logical().Write("auth/ldap/config", map[string]interface{}{
|
||||
"url": "ldap://ldap.forumsys.com",
|
||||
"userattr": "uid",
|
||||
"userdn": "dc=example,dc=com",
|
||||
"groupdn": "dc=example,dc=com",
|
||||
"binddn": "cn=read-only-admin,dc=example,dc=com",
|
||||
"token_no_default_policy": true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Create a local user in LDAP
|
||||
secret, err = client.Logical().Write("auth/ldap/users/tesla", map[string]interface{}{
|
||||
"policies": "foo",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Login with LDAP and create a token
|
||||
secret, err = client.Logical().Write("auth/ldap/login/tesla", map[string]interface{}{
|
||||
"password": "password",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
token := secret.Auth.ClientToken
|
||||
|
||||
// Lookup the token to get the entity ID
|
||||
secret, err = client.Auth().Token().Lookup(token)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff := deep.Equal(secret.Data["policies"], []interface{}{"foo"}); diff != nil {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
@ -46,7 +46,7 @@ This field is deprecated, use canonical_id.`,
|
|||
},
|
||||
},
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: i.handleAliasUpdateCommon(),
|
||||
logical.UpdateOperation: i.handleAliasCreateUpdate(),
|
||||
},
|
||||
|
||||
HelpSynopsis: strings.TrimSpace(aliasHelp["alias"][0]),
|
||||
|
|
@ -79,7 +79,7 @@ This field is deprecated, use canonical_id.`,
|
|||
},
|
||||
},
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: i.handleAliasUpdateCommon(),
|
||||
logical.UpdateOperation: i.handleAliasCreateUpdate(),
|
||||
logical.ReadOperation: i.pathAliasIDRead(),
|
||||
logical.DeleteOperation: i.pathAliasIDDelete(),
|
||||
},
|
||||
|
|
@ -99,31 +99,25 @@ This field is deprecated, use canonical_id.`,
|
|||
}
|
||||
}
|
||||
|
||||
// handleAliasUpdateCommon is used to update an alias
|
||||
func (i *IdentityStore) handleAliasUpdateCommon() framework.OperationFunc {
|
||||
// handleAliasCreateUpdate is used to create or update an alias
|
||||
func (i *IdentityStore) handleAliasCreateUpdate() framework.OperationFunc {
|
||||
return func(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||
var err error
|
||||
var alias *identity.Alias
|
||||
var entity *identity.Entity
|
||||
var previousEntity *identity.Entity
|
||||
|
||||
i.lock.Lock()
|
||||
defer i.lock.Unlock()
|
||||
|
||||
// Check for update or create
|
||||
aliasID := d.Get("id").(string)
|
||||
if aliasID != "" {
|
||||
alias, err = i.MemDBAliasByID(aliasID, true, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if alias == nil {
|
||||
return logical.ErrorResponse("invalid alias id"), nil
|
||||
}
|
||||
} else {
|
||||
alias = &identity.Alias{}
|
||||
ns, err := namespace.FromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get alias name, if any
|
||||
name := d.Get("name").(string)
|
||||
|
||||
// Get mount accessor, if any
|
||||
mountAccessor := d.Get("mount_accessor").(string)
|
||||
|
||||
// Get ID, if any
|
||||
id := d.Get("id").(string)
|
||||
|
||||
// Get entity id
|
||||
canonicalID := d.Get("canonical_id").(string)
|
||||
if canonicalID == "" {
|
||||
|
|
@ -131,155 +125,252 @@ func (i *IdentityStore) handleAliasUpdateCommon() framework.OperationFunc {
|
|||
canonicalID = d.Get("entity_id").(string)
|
||||
}
|
||||
|
||||
// Get alias name
|
||||
if aliasName := d.Get("name").(string); aliasName == "" {
|
||||
if alias.Name == "" {
|
||||
return logical.ErrorResponse("missing alias name"), nil
|
||||
}
|
||||
} else {
|
||||
alias.Name = aliasName
|
||||
}
|
||||
i.lock.Lock()
|
||||
defer i.lock.Unlock()
|
||||
|
||||
// Get mount accessor
|
||||
if mountAccessor := d.Get("mount_accessor").(string); mountAccessor == "" {
|
||||
if alias.MountAccessor == "" {
|
||||
return logical.ErrorResponse("missing mount_accessor"), nil
|
||||
}
|
||||
} else {
|
||||
alias.MountAccessor = mountAccessor
|
||||
}
|
||||
|
||||
mountValidationResp := i.core.router.validateMountByAccessor(alias.MountAccessor)
|
||||
if mountValidationResp == nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("invalid mount accessor %q", alias.MountAccessor)), nil
|
||||
}
|
||||
if mountValidationResp.MountLocal {
|
||||
return logical.ErrorResponse(fmt.Sprintf("mount_accessor %q is of a local mount", alias.MountAccessor)), nil
|
||||
}
|
||||
|
||||
// Verify that the combination of alias name and mount is not
|
||||
// already tied to a different alias
|
||||
aliasByFactors, err := i.MemDBAliasByFactors(mountValidationResp.MountAccessor, alias.Name, false, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if aliasByFactors != nil {
|
||||
// If it's a create we won't have an alias ID so this will correctly
|
||||
// bail. If it's an update alias will be the same as aliasbyfactors so
|
||||
// we don't need to transfer any info over
|
||||
if aliasByFactors.ID != alias.ID {
|
||||
return logical.ErrorResponse("combination of mount and alias name is already in use"), nil
|
||||
}
|
||||
|
||||
// Fetch the entity to which the alias is tied. We don't need to append
|
||||
// here, so the only further checking is whether the canonical ID is
|
||||
// different
|
||||
entity, err = i.MemDBEntityByAliasID(alias.ID, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entity == nil {
|
||||
return nil, fmt.Errorf("existing alias is not associated with an entity")
|
||||
}
|
||||
} else if alias.ID != "" {
|
||||
// This is an update, not a create; if we have an associated entity
|
||||
// already, load it
|
||||
entity, err = i.MemDBEntityByAliasID(alias.ID, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
resp := &logical.Response{}
|
||||
|
||||
// If we found an existing alias we won't hit this condition because
|
||||
// canonicalID being empty will result in nil being returned in the block
|
||||
// above, so in this case we know that creating a new entity is the right
|
||||
// thing.
|
||||
if canonicalID == "" {
|
||||
entity = &identity.Entity{
|
||||
Aliases: []*identity.Alias{
|
||||
alias,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// If we can look up by the given canonical ID, see if this is a
|
||||
// transfer; otherwise if we found no previous entity but we find one
|
||||
// here, use it.
|
||||
canonicalEntity, err := i.MemDBEntityByID(canonicalID, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if canonicalEntity == nil {
|
||||
return logical.ErrorResponse("invalid canonical ID"), nil
|
||||
}
|
||||
if entity == nil {
|
||||
// If entity is nil, we didn't find a previous alias from factors,
|
||||
// so append to this entity
|
||||
entity = canonicalEntity
|
||||
entity.Aliases = append(entity.Aliases, alias)
|
||||
} else if entity.ID != canonicalEntity.ID {
|
||||
// In this case we found an entity from alias factors or given
|
||||
// alias ID but it's not the same, so it's a migration
|
||||
previousEntity = entity
|
||||
entity = canonicalEntity
|
||||
|
||||
for aliasIndex, item := range previousEntity.Aliases {
|
||||
if item.ID == alias.ID {
|
||||
previousEntity.Aliases = append(previousEntity.Aliases[:aliasIndex], previousEntity.Aliases[aliasIndex+1:]...)
|
||||
break
|
||||
}
|
||||
// This block is run if they provided an ID
|
||||
{
|
||||
// If they provide an ID it must be an update. Find the alias, perform
|
||||
// due diligence, call the update function.
|
||||
if id != "" {
|
||||
alias, err := i.MemDBAliasByID(id, true, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if alias == nil {
|
||||
return logical.ErrorResponse("invalid alias ID provided"), nil
|
||||
}
|
||||
if alias.NamespaceID != ns.ID {
|
||||
return logical.ErrorResponse("cannot modify aliases across namespaces"), logical.ErrPermissionDenied
|
||||
}
|
||||
|
||||
entity.Aliases = append(entity.Aliases, alias)
|
||||
resp.AddWarning(fmt.Sprintf("alias is being transferred from entity %q to %q", previousEntity.ID, entity.ID))
|
||||
switch {
|
||||
case mountAccessor == "" && name == "":
|
||||
// Just a canonical ID update, maybe
|
||||
if canonicalID == "" {
|
||||
// Nothing to do, so be idempotent
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
name = alias.Name
|
||||
mountAccessor = alias.MountAccessor
|
||||
|
||||
case mountAccessor == "":
|
||||
// No change to mount accessor
|
||||
mountAccessor = alias.MountAccessor
|
||||
|
||||
case name == "":
|
||||
// No change to mount name
|
||||
name = alias.Name
|
||||
|
||||
default:
|
||||
// Both provided
|
||||
}
|
||||
|
||||
return i.handleAliasUpdate(ctx, req, canonicalID, name, mountAccessor, alias)
|
||||
}
|
||||
}
|
||||
|
||||
// ID creation and other validations; This is more useful for new entities
|
||||
// and may not perform anything for the existing entities. Placing the
|
||||
// check here to make the flow common for both new and existing entities.
|
||||
err = i.sanitizeEntity(ctx, entity)
|
||||
// If they didn't provide an ID, we must have both accessor and name provided
|
||||
if mountAccessor == "" || name == "" {
|
||||
return logical.ErrorResponse("'id' or 'mount_accessor' and 'name' must be provided"), nil
|
||||
}
|
||||
|
||||
// Look up the alias by factors; if it's found it's an update
|
||||
mountEntry := i.core.router.MatchingMountByAccessor(mountAccessor)
|
||||
if mountEntry == nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("invalid mount accessor %q", mountAccessor)), nil
|
||||
}
|
||||
if mountEntry.Local {
|
||||
return logical.ErrorResponse(fmt.Sprintf("mount accessor %q is of a local mount", mountAccessor)), nil
|
||||
}
|
||||
if mountEntry.NamespaceID != ns.ID {
|
||||
return logical.ErrorResponse("matching mount is in a different namespace than request"), logical.ErrPermissionDenied
|
||||
}
|
||||
alias, err := i.MemDBAliasByFactors(mountAccessor, name, false, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Explicitly set to empty as in the past we incorrectly saved it
|
||||
alias.MountPath = ""
|
||||
alias.MountType = ""
|
||||
|
||||
// Set the canonical ID in the alias index. This should be done after
|
||||
// sanitizing entity.
|
||||
alias.CanonicalID = entity.ID
|
||||
|
||||
// ID creation and other validations
|
||||
err = i.sanitizeAlias(ctx, alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for index, item := range entity.Aliases {
|
||||
if item.ID == alias.ID {
|
||||
entity.Aliases[index] = alias
|
||||
if alias != nil {
|
||||
if alias.NamespaceID != ns.ID {
|
||||
return logical.ErrorResponse("cannot modify aliases across namespaces"), logical.ErrPermissionDenied
|
||||
}
|
||||
|
||||
return i.handleAliasUpdate(ctx, req, alias.CanonicalID, name, mountAccessor, alias)
|
||||
}
|
||||
|
||||
// Index entity and its aliases in MemDB and persist entity along with
|
||||
// aliases in storage. If the alias is being transferred over from
|
||||
// one entity to another, previous entity needs to get refreshed in MemDB
|
||||
// and persisted in storage as well.
|
||||
if err := i.upsertEntity(ctx, entity, previousEntity, true); err != nil {
|
||||
// At this point we know it's a new creation request
|
||||
return i.handleAliasCreate(ctx, req, canonicalID, name, mountAccessor)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *IdentityStore) handleAliasCreate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string) (*logical.Response, error) {
|
||||
ns, err := namespace.FromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
alias := &identity.Alias{
|
||||
MountAccessor: mountAccessor,
|
||||
Name: name,
|
||||
}
|
||||
entity := &identity.Entity{}
|
||||
|
||||
// If a canonical ID is provided pull up the entity and make sure we're in
|
||||
// the right NS
|
||||
if canonicalID != "" {
|
||||
entity, err = i.MemDBEntityByID(canonicalID, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if entity == nil {
|
||||
return logical.ErrorResponse("invalid canonical ID"), nil
|
||||
}
|
||||
if entity.NamespaceID != ns.ID {
|
||||
return logical.ErrorResponse("entity found with 'canonical_id' not in request namespace"), logical.ErrPermissionDenied
|
||||
}
|
||||
}
|
||||
|
||||
// Return ID of both alias and entity
|
||||
resp.Data = map[string]interface{}{
|
||||
entity.Aliases = append(entity.Aliases, alias)
|
||||
|
||||
// ID creation and other validations; This is more useful for new entities
|
||||
// and may not perform anything for the existing entities. Placing the
|
||||
// check here to make the flow common for both new and existing entities.
|
||||
err = i.sanitizeEntity(ctx, entity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set the canonical ID in the alias index. This should be done after
|
||||
// sanitizing entity in case it's a new entity that didn't have an ID.
|
||||
alias.CanonicalID = entity.ID
|
||||
|
||||
// ID creation and other validations
|
||||
err = i.sanitizeAlias(ctx, alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Index entity and its aliases in MemDB and persist entity along with
|
||||
// aliases in storage.
|
||||
if err := i.upsertEntity(ctx, entity, nil, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Return ID of both alias and entity
|
||||
return &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"id": alias.ID,
|
||||
"canonical_id": entity.ID,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (i *IdentityStore) handleAliasUpdate(ctx context.Context, req *logical.Request, canonicalID, name, mountAccessor string, alias *identity.Alias) (*logical.Response, error) {
|
||||
if name == alias.Name &&
|
||||
mountAccessor == alias.MountAccessor &&
|
||||
(canonicalID == alias.CanonicalID || canonicalID == "") {
|
||||
// Nothing to do; return nil to be idempotent
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
alias.LastUpdateTime = ptypes.TimestampNow()
|
||||
|
||||
// If we're changing one or the other or both of these, make sure that
|
||||
// there isn't a matching alias already, and make sure it's in the same
|
||||
// namespace.
|
||||
if name != alias.Name || mountAccessor != alias.MountAccessor {
|
||||
// Check here to see if such an alias already exists, if so bail
|
||||
mountEntry := i.core.router.MatchingMountByAccessor(mountAccessor)
|
||||
if mountEntry == nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("invalid mount accessor %q", mountAccessor)), nil
|
||||
}
|
||||
if mountEntry.Local {
|
||||
return logical.ErrorResponse(fmt.Sprintf("mount_accessor %q is of a local mount", mountAccessor)), nil
|
||||
}
|
||||
if mountEntry.NamespaceID != alias.NamespaceID {
|
||||
return logical.ErrorResponse("given mount accessor is not in the same namespace as the existing alias"), logical.ErrPermissionDenied
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
existingAlias, err := i.MemDBAliasByFactors(mountAccessor, name, false, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Bail unless it's just a case change
|
||||
if existingAlias != nil && !strings.EqualFold(existingAlias.Name, name) {
|
||||
return logical.ErrorResponse("alias with combination of mount accessor and name already exists"), nil
|
||||
}
|
||||
|
||||
// Update the values in the alias
|
||||
alias.Name = name
|
||||
alias.MountAccessor = mountAccessor
|
||||
}
|
||||
|
||||
// Get our current entity, which may be the same as the new one if the
|
||||
// canonical ID hasn't changed
|
||||
currentEntity, err := i.MemDBEntityByAliasID(alias.ID, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if currentEntity == nil {
|
||||
return logical.ErrorResponse("given alias is not associated with an entity"), nil
|
||||
}
|
||||
if currentEntity.NamespaceID != alias.NamespaceID {
|
||||
return logical.ErrorResponse("alias associated with an entity in a different namespace"), logical.ErrPermissionDenied
|
||||
}
|
||||
|
||||
newEntity := currentEntity
|
||||
if canonicalID != "" && canonicalID != alias.CanonicalID {
|
||||
newEntity, err = i.MemDBEntityByID(canonicalID, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if newEntity == nil {
|
||||
return logical.ErrorResponse("given 'canonical_id' is not associated with an entity"), nil
|
||||
}
|
||||
if newEntity.NamespaceID != alias.NamespaceID {
|
||||
return logical.ErrorResponse("given 'canonical_id' associated with entity in a different namespace from the alias"), logical.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// Update the canonical ID value and move it from the current enitity to the new one
|
||||
alias.CanonicalID = newEntity.ID
|
||||
newEntity.Aliases = append(newEntity.Aliases, alias)
|
||||
for aliasIndex, item := range currentEntity.Aliases {
|
||||
if item.ID == alias.ID {
|
||||
currentEntity.Aliases = append(currentEntity.Aliases[:aliasIndex], currentEntity.Aliases[aliasIndex+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If it's not moving we still need to update it in the existing
|
||||
// entity's aliases
|
||||
for aliasIndex, item := range currentEntity.Aliases {
|
||||
if item.ID == alias.ID {
|
||||
currentEntity.Aliases[aliasIndex] = alias
|
||||
break
|
||||
}
|
||||
}
|
||||
// newEntity will be pointing to the same entity; set currentEntity nil
|
||||
// so the upsertCall gets nil for the previous entity as we're only
|
||||
// changing one.
|
||||
currentEntity = nil
|
||||
}
|
||||
|
||||
// Index entity and its aliases in MemDB and persist entity along with
|
||||
// aliases in storage. If the alias is being transferred over from
|
||||
// one entity to another, previous entity needs to get refreshed in MemDB
|
||||
// and persisted in storage as well.
|
||||
if err := i.upsertEntity(ctx, newEntity, currentEntity, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Return ID of both alias and entity
|
||||
return &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"id": alias.ID,
|
||||
"canonical_id": newEntity.ID,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// pathAliasIDRead returns the properties of an alias for a given
|
||||
|
|
@ -310,7 +401,7 @@ func (i *IdentityStore) handleAliasReadCommon(ctx context.Context, alias *identi
|
|||
return nil, err
|
||||
}
|
||||
if ns.ID != alias.NamespaceID {
|
||||
return nil, nil
|
||||
return logical.ErrorResponse("alias and request are in different namespaces"), logical.ErrPermissionDenied
|
||||
}
|
||||
|
||||
respData := map[string]interface{}{}
|
||||
|
|
@ -320,6 +411,7 @@ func (i *IdentityStore) handleAliasReadCommon(ctx context.Context, alias *identi
|
|||
respData["metadata"] = alias.Metadata
|
||||
respData["name"] = alias.Name
|
||||
respData["merged_from_canonical_ids"] = alias.MergedFromCanonicalIDs
|
||||
respData["namespace_id"] = alias.NamespaceID
|
||||
|
||||
if mountValidationResp := i.core.router.validateMountByAccessor(alias.MountAccessor); mountValidationResp != nil {
|
||||
respData["mount_path"] = mountValidationResp.MountPath
|
||||
|
|
@ -366,7 +458,7 @@ func (i *IdentityStore) pathAliasIDDelete() framework.OperationFunc {
|
|||
return nil, err
|
||||
}
|
||||
if ns.ID != alias.NamespaceID {
|
||||
return nil, logical.ErrUnsupportedPath
|
||||
return logical.ErrorResponse("request and alias are in different namespaces"), logical.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// Fetch the associated entity
|
||||
|
|
|
|||
|
|
@ -196,8 +196,8 @@ func TestIdentityStore_AliasSameAliasNames(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp == nil || !resp.IsError() {
|
||||
t.Fatalf("expected an error due to alias name not being unique")
|
||||
if resp != nil {
|
||||
t.Fatalf("expected no response since this modification should be idempotent")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -337,6 +337,7 @@ func (i *IdentityStore) handleEntityReadCommon(ctx context.Context, entity *iden
|
|||
respData["merged_entity_ids"] = entity.MergedEntityIDs
|
||||
respData["policies"] = entity.Policies
|
||||
respData["disabled"] = entity.Disabled
|
||||
respData["namespace_id"] = entity.NamespaceID
|
||||
|
||||
// Convert protobuf timestamp into RFC3339 format
|
||||
respData["creation_time"] = ptypes.TimestampString(entity.CreationTime)
|
||||
|
|
|
|||
|
|
@ -152,16 +152,16 @@ func (i *IdentityStore) handleGroupAliasUpdateCommon(ctx context.Context, req *l
|
|||
return logical.ErrorResponse("missing mount_accessor"), nil
|
||||
}
|
||||
|
||||
mountValidationResp := i.core.router.validateMountByAccessor(mountAccessor)
|
||||
if mountValidationResp == nil {
|
||||
mountEntry := i.core.router.MatchingMountByAccessor(mountAccessor)
|
||||
if mountEntry == nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf("invalid mount accessor %q", mountAccessor)), nil
|
||||
}
|
||||
|
||||
if mountValidationResp.MountLocal {
|
||||
if mountEntry.Local {
|
||||
return logical.ErrorResponse(fmt.Sprintf("mount_accessor %q is of a local mount", mountAccessor)), nil
|
||||
}
|
||||
|
||||
groupAliasByFactors, err := i.MemDBAliasByFactors(mountValidationResp.MountAccessor, groupAliasName, false, true)
|
||||
groupAliasByFactors, err := i.MemDBAliasByFactors(mountEntry.Accessor, groupAliasName, false, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -208,8 +208,13 @@ func (i *IdentityStore) handleGroupAliasUpdateCommon(ctx context.Context, req *l
|
|||
group.Alias = groupAlias
|
||||
}
|
||||
|
||||
// Check if the group we found belongs to a different namespace than the mount accessor
|
||||
if group.NamespaceID != mountEntry.NamespaceID {
|
||||
return logical.ErrorResponse("mount accessor and group are located in different namespaces"), nil
|
||||
}
|
||||
|
||||
group.Alias.Name = groupAliasName
|
||||
group.Alias.MountAccessor = mountValidationResp.MountAccessor
|
||||
group.Alias.MountAccessor = mountEntry.Accessor
|
||||
// Explicitly correct for previous versions that persisted this
|
||||
group.Alias.MountType = ""
|
||||
|
||||
|
|
|
|||
|
|
@ -335,6 +335,7 @@ func (i *IdentityStore) handleGroupReadCommon(ctx context.Context, group *identi
|
|||
respData["last_update_time"] = ptypes.TimestampString(group.LastUpdateTime)
|
||||
respData["modify_index"] = group.ModifyIndex
|
||||
respData["type"] = group.Type
|
||||
respData["namespace_id"] = group.NamespaceID
|
||||
|
||||
aliasMap := map[string]interface{}{}
|
||||
if group.Alias != nil {
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ vault <command> <path> metadata=key1=value1 metadata=key2=value2
|
|||
},
|
||||
},
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: i.handleAliasUpdateCommon(),
|
||||
logical.UpdateOperation: i.handleAliasCreateUpdate(),
|
||||
},
|
||||
|
||||
HelpSynopsis: strings.TrimSpace(aliasHelp["alias"][0]),
|
||||
|
|
@ -147,7 +147,7 @@ vault <command> <path> metadata=key1=value1 metadata=key2=value2
|
|||
},
|
||||
},
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: i.handleAliasUpdateCommon(),
|
||||
logical.UpdateOperation: i.handleAliasCreateUpdate(),
|
||||
logical.ReadOperation: i.pathAliasIDRead(),
|
||||
logical.DeleteOperation: i.pathAliasIDDelete(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -332,11 +332,19 @@ func (i *IdentityStore) upsertEntityInTxn(ctx context.Context, txn *memdb.Txn, e
|
|||
var err error
|
||||
|
||||
if txn == nil {
|
||||
return fmt.Errorf("txn is nil")
|
||||
return errors.New("txn is nil")
|
||||
}
|
||||
|
||||
if entity == nil {
|
||||
return fmt.Errorf("entity is nil")
|
||||
return errors.New("entity is nil")
|
||||
}
|
||||
|
||||
if entity.NamespaceID == "" {
|
||||
entity.NamespaceID = namespace.RootNamespaceID
|
||||
}
|
||||
|
||||
if previousEntity != nil && previousEntity.NamespaceID != entity.NamespaceID {
|
||||
return errors.New("entity and previous entity are not in the same namespace")
|
||||
}
|
||||
|
||||
aliasFactors := make([]string, len(entity.Aliases))
|
||||
|
|
@ -348,12 +356,24 @@ func (i *IdentityStore) upsertEntityInTxn(ctx context.Context, txn *memdb.Txn, e
|
|||
return err
|
||||
}
|
||||
|
||||
if alias.NamespaceID == "" {
|
||||
alias.NamespaceID = namespace.RootNamespaceID
|
||||
}
|
||||
|
||||
switch {
|
||||
case aliasByFactors == nil:
|
||||
// Not found, no merging needed
|
||||
// Not found, no merging needed, just check namespace
|
||||
if alias.NamespaceID != entity.NamespaceID {
|
||||
return errors.New("alias and entity are not in the same namespace")
|
||||
}
|
||||
|
||||
case aliasByFactors.CanonicalID == entity.ID:
|
||||
// Lookup found the same entity, so it's already attached to the
|
||||
// right place
|
||||
if aliasByFactors.NamespaceID != entity.NamespaceID {
|
||||
return errors.New("alias from factors and entity are not in the same namespace")
|
||||
}
|
||||
|
||||
case previousEntity != nil && aliasByFactors.CanonicalID == previousEntity.ID:
|
||||
// previousEntity isn't upserted yet so may still contain the old
|
||||
// alias reference in memdb if it was just changed; validate
|
||||
|
|
@ -372,8 +392,10 @@ func (i *IdentityStore) upsertEntityInTxn(ctx context.Context, txn *memdb.Txn, e
|
|||
}
|
||||
|
||||
// Otherwise it's still tied to previousEntity and fall through
|
||||
// into merging
|
||||
// into merging. We don't need a namespace check here as existing
|
||||
// checks when creating the aliases should ensure that all line up.
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
i.logger.Warn("alias is already tied to a different entity; these entities are being merged", "alias_id", alias.ID, "other_entity_id", aliasByFactors.CanonicalID, "entity_aliases", entity.Aliases, "alias_by_factors", aliasByFactors)
|
||||
|
||||
|
|
@ -943,7 +965,7 @@ func (i *IdentityStore) sanitizeAlias(ctx context.Context, alias *identity.Alias
|
|||
return err
|
||||
}
|
||||
if ns.ID != alias.NamespaceID {
|
||||
return fmt.Errorf("alias belongs to a different namespace")
|
||||
return errors.New("alias belongs to a different namespace")
|
||||
}
|
||||
|
||||
// Set the creation and last update times
|
||||
|
|
@ -983,7 +1005,7 @@ func (i *IdentityStore) sanitizeEntity(ctx context.Context, entity *identity.Ent
|
|||
entity.NamespaceID = ns.ID
|
||||
}
|
||||
if ns.ID != entity.NamespaceID {
|
||||
return fmt.Errorf("entity does not belong to this namespace")
|
||||
return errors.New("entity does not belong to this namespace")
|
||||
}
|
||||
|
||||
// Create a name if there isn't one already
|
||||
|
|
@ -1047,7 +1069,7 @@ func (i *IdentityStore) sanitizeAndUpsertGroup(ctx context.Context, group *ident
|
|||
return err
|
||||
}
|
||||
if ns.ID != group.NamespaceID {
|
||||
return fmt.Errorf("group does not belong to this namespace")
|
||||
return errors.New("group does not belong to this namespace")
|
||||
}
|
||||
|
||||
// Create a name if there isn't one already
|
||||
|
|
|
|||
|
|
@ -483,6 +483,8 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry, updateStora
|
|||
|
||||
addPathCheckers(c, entry, backend, viewPath)
|
||||
|
||||
addLicenseCallback(c, backend)
|
||||
|
||||
c.setCoreBackend(entry, backend, view)
|
||||
|
||||
// If the mount is filtered or we are on a DR secondary we don't want to
|
||||
|
|
@ -1199,6 +1201,7 @@ func (c *Core) newLogicalBackend(ctx context.Context, entry *MountEntry, sysView
|
|||
BackendUUID: entry.BackendAwareUUID,
|
||||
}
|
||||
|
||||
ctx = context.WithValue(ctx, "core_number", c.coreNumber)
|
||||
b, err := f(ctx, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ func removeAuditPathChecker(*Core, *MountEntry) {}
|
|||
func addFilterablePath(*Core, string) {}
|
||||
func preprocessMount(*Core, *MountEntry, *BarrierView) (bool, error) { return false, nil }
|
||||
func clearIgnoredPaths(context.Context, *Core, logical.Backend, string) error { return nil }
|
||||
func addLicenseCallback(*Core, logical.Backend) {}
|
||||
|
||||
// ViewPath returns storage prefix for the view
|
||||
func (e *MountEntry) ViewPath() string {
|
||||
|
|
|
|||
|
|
@ -1034,6 +1034,11 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
|
|||
var entity *identity.Entity
|
||||
auth = resp.Auth
|
||||
|
||||
// Only the token store can toggle this off, and that's via a different
|
||||
// path since it's not a login request; it's explicitly disallowed
|
||||
// above
|
||||
auth.Renewable = true
|
||||
|
||||
mEntry := c.router.MatchingMountEntry(ctx, req.Path)
|
||||
|
||||
if auth.Alias != nil &&
|
||||
|
|
@ -1109,7 +1114,7 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
|
|||
return nil, nil, ErrInternalError
|
||||
}
|
||||
|
||||
auth.TokenPolicies = policyutil.SanitizePolicies(auth.Policies, policyutil.AddDefaultPolicy)
|
||||
auth.TokenPolicies = policyutil.SanitizePolicies(auth.Policies, !auth.NoDefaultPolicy)
|
||||
allPolicies := policyutil.SanitizePolicies(append(auth.TokenPolicies, identityPolicies[ns.ID]...), policyutil.DoNotAddDefaultPolicy)
|
||||
|
||||
// Prevent internal policies from being assigned to tokens. We check
|
||||
|
|
|
|||
|
|
@ -989,6 +989,7 @@ type TestClusterOptions struct {
|
|||
TempDir string
|
||||
CACert []byte
|
||||
CAKey *ecdsa.PrivateKey
|
||||
FirstCoreNumber int
|
||||
}
|
||||
|
||||
var DefaultNumCores = 3
|
||||
|
|
@ -1019,6 +1020,11 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
|
|||
numCores = opts.NumCores
|
||||
}
|
||||
|
||||
var firstCoreNumber int
|
||||
if opts != nil {
|
||||
firstCoreNumber = opts.FirstCoreNumber
|
||||
}
|
||||
|
||||
certIPs := []net.IP{
|
||||
net.IPv6loopback,
|
||||
net.ParseIP("127.0.0.1"),
|
||||
|
|
@ -1371,6 +1377,7 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te
|
|||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
c.coreNumber = firstCoreNumber + i
|
||||
cores = append(cores, c)
|
||||
coreConfigs = append(coreConfigs, &localConfig)
|
||||
if opts != nil && opts.HandlerFunc != nil {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/hashicorp/vault/sdk/helper/policyutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/salt"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/tokenutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
"github.com/hashicorp/vault/sdk/plugin/pb"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
|
@ -47,7 +48,7 @@ const (
|
|||
accessorPrefix = "accessor/"
|
||||
|
||||
// parentPrefix is the prefix used to store tokens for their
|
||||
// secondar parent based index
|
||||
// secondary parent based index
|
||||
parentPrefix = "parent/"
|
||||
|
||||
// tokenSubPath is the sub-path used for the token store
|
||||
|
|
@ -103,7 +104,7 @@ var (
|
|||
)
|
||||
|
||||
func (ts *TokenStore) paths() []*framework.Path {
|
||||
return []*framework.Path{
|
||||
p := []*framework.Path{
|
||||
{
|
||||
Pattern: "roles/?$",
|
||||
|
||||
|
|
@ -126,76 +127,6 @@ func (ts *TokenStore) paths() []*framework.Path {
|
|||
HelpDescription: tokenListAccessorsHelp,
|
||||
},
|
||||
|
||||
{
|
||||
Pattern: "roles/" + framework.GenericNameRegex("role_name"),
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"role_name": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: "Name of the role",
|
||||
},
|
||||
|
||||
"allowed_policies": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: tokenAllowedPoliciesHelp,
|
||||
},
|
||||
|
||||
"disallowed_policies": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: tokenDisallowedPoliciesHelp,
|
||||
},
|
||||
|
||||
"orphan": &framework.FieldSchema{
|
||||
Type: framework.TypeBool,
|
||||
Default: false,
|
||||
Description: tokenOrphanHelp,
|
||||
},
|
||||
|
||||
"period": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Default: 0,
|
||||
Description: tokenPeriodHelp,
|
||||
},
|
||||
|
||||
"path_suffix": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Default: "",
|
||||
Description: tokenPathSuffixHelp + pathSuffixSanitize.String(),
|
||||
},
|
||||
|
||||
"explicit_max_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Default: 0,
|
||||
Description: tokenExplicitMaxTTLHelp,
|
||||
},
|
||||
|
||||
"renewable": &framework.FieldSchema{
|
||||
Type: framework.TypeBool,
|
||||
Default: true,
|
||||
Description: tokenRenewableHelp,
|
||||
},
|
||||
|
||||
"bound_cidrs": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `Comma separated string or JSON list of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.`,
|
||||
},
|
||||
|
||||
"token_type": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Default: "service",
|
||||
Description: "The type of token to generate, service or batch",
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.ReadOperation: ts.tokenStoreRoleRead,
|
||||
logical.CreateOperation: ts.tokenStoreRoleCreateUpdate,
|
||||
logical.UpdateOperation: ts.tokenStoreRoleCreateUpdate,
|
||||
logical.DeleteOperation: ts.tokenStoreRoleDelete,
|
||||
},
|
||||
|
||||
ExistenceCheck: ts.tokenStoreRoleExistenceCheck,
|
||||
},
|
||||
|
||||
{
|
||||
Pattern: "create-orphan$",
|
||||
|
||||
|
|
@ -414,6 +345,74 @@ func (ts *TokenStore) paths() []*framework.Path {
|
|||
HelpDescription: strings.TrimSpace(tokenTidyDesc),
|
||||
},
|
||||
}
|
||||
|
||||
rolesPath := &framework.Path{
|
||||
Pattern: "roles/" + framework.GenericNameRegex("role_name"),
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"role_name": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: "Name of the role",
|
||||
},
|
||||
|
||||
"allowed_policies": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: tokenAllowedPoliciesHelp,
|
||||
},
|
||||
|
||||
"disallowed_policies": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: tokenDisallowedPoliciesHelp,
|
||||
},
|
||||
|
||||
"orphan": &framework.FieldSchema{
|
||||
Type: framework.TypeBool,
|
||||
Description: tokenOrphanHelp,
|
||||
},
|
||||
|
||||
"period": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: "(DEPRECATED) Use 'token_period' instead. If this and 'token_period' are both specified both will be retained but 'token_period' will take precedence.",
|
||||
Deprecated: true,
|
||||
},
|
||||
|
||||
"path_suffix": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Description: tokenPathSuffixHelp + pathSuffixSanitize.String(),
|
||||
},
|
||||
|
||||
"explicit_max_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: "(DEPRECATED) Use 'token_explicit_max_ttl' instead. If this and 'token_explicit_max_ttl' are both specified both will be retained but 'token_explicit_max_ttl' will take precedence.",
|
||||
Deprecated: true,
|
||||
},
|
||||
|
||||
"renewable": &framework.FieldSchema{
|
||||
Type: framework.TypeBool,
|
||||
Default: true,
|
||||
Description: tokenRenewableHelp,
|
||||
},
|
||||
|
||||
"bound_cidrs": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: "(DEPRECATED) Use 'token_bound_cidrs' instead. If this and 'token_bound_cidrs' are both specified both will be retained but 'token_bound_cidrs' will take precedence.",
|
||||
Deprecated: true,
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.ReadOperation: ts.tokenStoreRoleRead,
|
||||
logical.CreateOperation: ts.tokenStoreRoleCreateUpdate,
|
||||
logical.UpdateOperation: ts.tokenStoreRoleCreateUpdate,
|
||||
logical.DeleteOperation: ts.tokenStoreRoleDelete,
|
||||
},
|
||||
|
||||
ExistenceCheck: ts.tokenStoreRoleExistenceCheck,
|
||||
}
|
||||
|
||||
tokenutil.AddTokenFieldsWithAllowList(rolesPath.Fields, []string{"token_bound_cidrs", "token_explicit_max_ttl", "token_period", "token_type", "token_no_default_policy", "token_num_uses"})
|
||||
p = append(p, rolesPath)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// LookupToken returns the properties of the token from the token store. This
|
||||
|
|
@ -540,7 +539,6 @@ func NewTokenStore(ctx context.Context, logger log.Logger, core *Core, config *l
|
|||
}
|
||||
|
||||
func (ts *TokenStore) Invalidate(ctx context.Context, key string) {
|
||||
//ts.logger.Debug("invalidating key", "key", key)
|
||||
|
||||
switch key {
|
||||
case tokenSubPath + salt.DefaultLocation:
|
||||
|
|
@ -581,6 +579,8 @@ func (ts *TokenStore) Salt(ctx context.Context) (*salt.Salt, error) {
|
|||
|
||||
// tsRoleEntry contains token store role information
|
||||
type tsRoleEntry struct {
|
||||
tokenutil.TokenParams
|
||||
|
||||
// The name of the role. Embedded so it can be used for pathing
|
||||
Name string `json:"name" mapstructure:"name" structs:"name"`
|
||||
|
||||
|
|
@ -611,9 +611,6 @@ type tsRoleEntry struct {
|
|||
|
||||
// The set of CIDRs that tokens generated using this role will be bound to
|
||||
BoundCIDRs []*sockaddr.SockAddrMarshaler `json:"bound_cidrs"`
|
||||
|
||||
// The type of token this role should issue
|
||||
TokenType logical.TokenType `json:"token_type" mapstructure:"token_type"`
|
||||
}
|
||||
|
||||
type accessorEntry struct {
|
||||
|
|
@ -2236,6 +2233,16 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
|||
renewable = false
|
||||
}
|
||||
|
||||
// Update te.NumUses which is equal to req.Data["num_uses"] at this point
|
||||
// 0 means unlimited so 1 is actually less than 0
|
||||
switch {
|
||||
case role.TokenNumUses == 0:
|
||||
case te.NumUses == 0:
|
||||
te.NumUses = role.TokenNumUses
|
||||
case role.TokenNumUses < te.NumUses:
|
||||
te.NumUses = role.TokenNumUses
|
||||
}
|
||||
|
||||
if role.PathSuffix != "" {
|
||||
te.Path = fmt.Sprintf("%s/%s", te.Path, role.PathSuffix)
|
||||
}
|
||||
|
|
@ -2284,7 +2291,7 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
|||
// isn't in the disallowed list, add it. This is in line with the idea
|
||||
// that roles, when allowed/disallowed ar set, allow a subset of
|
||||
// policies to be set disjoint from the parent token's policies.
|
||||
if !data.NoDefaultPolicy && !strutil.StrListContains(role.DisallowedPolicies, "default") {
|
||||
if !data.NoDefaultPolicy && !role.TokenNoDefaultPolicy && !strutil.StrListContains(role.DisallowedPolicies, "default") {
|
||||
localAddDefault = true
|
||||
}
|
||||
|
||||
|
|
@ -2406,8 +2413,8 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
|||
te.Parent = ""
|
||||
}
|
||||
|
||||
if len(role.BoundCIDRs) > 0 {
|
||||
te.BoundCIDRs = role.BoundCIDRs
|
||||
if len(role.TokenBoundCIDRs) > 0 {
|
||||
te.BoundCIDRs = role.TokenBoundCIDRs
|
||||
}
|
||||
|
||||
case data.NoParent:
|
||||
|
|
@ -2501,24 +2508,24 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
|||
// in role. Batch tokens will error out if not set via role, but here we
|
||||
// need to explicitly check
|
||||
if role != nil && te.Type != logical.TokenTypeBatch {
|
||||
if role.ExplicitMaxTTL != 0 {
|
||||
if role.TokenExplicitMaxTTL != 0 {
|
||||
switch {
|
||||
case explicitMaxTTLToUse == 0:
|
||||
explicitMaxTTLToUse = role.ExplicitMaxTTL
|
||||
explicitMaxTTLToUse = role.TokenExplicitMaxTTL
|
||||
default:
|
||||
if role.ExplicitMaxTTL < explicitMaxTTLToUse {
|
||||
explicitMaxTTLToUse = role.ExplicitMaxTTL
|
||||
if role.TokenExplicitMaxTTL < explicitMaxTTLToUse {
|
||||
explicitMaxTTLToUse = role.TokenExplicitMaxTTL
|
||||
}
|
||||
resp.AddWarning(fmt.Sprintf("Explicit max TTL specified both during creation call and in role; using the lesser value of %d seconds", int64(explicitMaxTTLToUse.Seconds())))
|
||||
}
|
||||
}
|
||||
if role.Period != 0 {
|
||||
if role.TokenPeriod != 0 {
|
||||
switch {
|
||||
case periodToUse == 0:
|
||||
periodToUse = role.Period
|
||||
periodToUse = role.TokenPeriod
|
||||
default:
|
||||
if role.Period < periodToUse {
|
||||
periodToUse = role.Period
|
||||
if role.TokenPeriod < periodToUse {
|
||||
periodToUse = role.TokenPeriod
|
||||
}
|
||||
resp.AddWarning(fmt.Sprintf("Period specified both during creation call and in role; using the lesser value of %d seconds", int64(periodToUse.Seconds())))
|
||||
}
|
||||
|
|
@ -2872,8 +2879,8 @@ func (ts *TokenStore) authRenew(ctx context.Context, req *logical.Request, d *fr
|
|||
return nil, fmt.Errorf("original token role %q could not be found, not renewing", te.Role)
|
||||
}
|
||||
|
||||
req.Auth.Period = role.Period
|
||||
req.Auth.ExplicitMaxTTL = role.ExplicitMaxTTL
|
||||
req.Auth.Period = role.TokenPeriod
|
||||
req.Auth.ExplicitMaxTTL = role.TokenExplicitMaxTTL
|
||||
return &logical.Response{Auth: req.Auth}, nil
|
||||
}
|
||||
|
||||
|
|
@ -2900,6 +2907,18 @@ func (ts *TokenStore) tokenStoreRole(ctx context.Context, name string) (*tsRoleE
|
|||
result.TokenType = logical.TokenTypeDefaultService
|
||||
}
|
||||
|
||||
// Token field upgrades. We preserve the original value for read
|
||||
// compatibility.
|
||||
if result.Period > 0 && result.TokenPeriod == 0 {
|
||||
result.TokenPeriod = result.Period
|
||||
}
|
||||
if result.ExplicitMaxTTL > 0 && result.TokenExplicitMaxTTL == 0 {
|
||||
result.TokenExplicitMaxTTL = result.ExplicitMaxTTL
|
||||
}
|
||||
if len(result.BoundCIDRs) > 0 && len(result.TokenBoundCIDRs) == 0 {
|
||||
result.TokenBoundCIDRs = result.BoundCIDRs
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
|
|
@ -2945,23 +2964,32 @@ func (ts *TokenStore) tokenStoreRoleRead(ctx context.Context, req *logical.Reque
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// TODO (1.4): Remove "period" and "explicit_max_ttl" if they're zero
|
||||
resp := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"period": int64(role.Period.Seconds()),
|
||||
"explicit_max_ttl": int64(role.ExplicitMaxTTL.Seconds()),
|
||||
"disallowed_policies": role.DisallowedPolicies,
|
||||
"allowed_policies": role.AllowedPolicies,
|
||||
"name": role.Name,
|
||||
"orphan": role.Orphan,
|
||||
"path_suffix": role.PathSuffix,
|
||||
"renewable": role.Renewable,
|
||||
"token_type": role.TokenType.String(),
|
||||
"period": int64(role.Period.Seconds()),
|
||||
"token_period": int64(role.TokenPeriod.Seconds()),
|
||||
"explicit_max_ttl": int64(role.ExplicitMaxTTL.Seconds()),
|
||||
"token_explicit_max_ttl": int64(role.TokenExplicitMaxTTL.Seconds()),
|
||||
"disallowed_policies": role.DisallowedPolicies,
|
||||
"allowed_policies": role.AllowedPolicies,
|
||||
"name": role.Name,
|
||||
"orphan": role.Orphan,
|
||||
"path_suffix": role.PathSuffix,
|
||||
"renewable": role.Renewable,
|
||||
"token_type": role.TokenType.String(),
|
||||
},
|
||||
}
|
||||
|
||||
if len(role.TokenBoundCIDRs) > 0 {
|
||||
resp.Data["token_bound_cidrs"] = role.TokenBoundCIDRs
|
||||
}
|
||||
if len(role.BoundCIDRs) > 0 {
|
||||
resp.Data["bound_cidrs"] = role.BoundCIDRs
|
||||
}
|
||||
if role.TokenNumUses > 0 {
|
||||
resp.Data["token_num_uses"] = role.TokenNumUses
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
|
@ -2997,140 +3025,160 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(ctx context.Context, req *logic
|
|||
}
|
||||
}
|
||||
|
||||
// In this series of blocks, if we do not find a user-provided value and
|
||||
// it's a creation operation, we call data.Get to get the appropriate
|
||||
// default
|
||||
|
||||
orphanInt, ok := data.GetOk("orphan")
|
||||
if ok {
|
||||
entry.Orphan = orphanInt.(bool)
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.Orphan = data.Get("orphan").(bool)
|
||||
}
|
||||
|
||||
periodInt, ok := data.GetOk("period")
|
||||
if ok {
|
||||
entry.Period = time.Second * time.Duration(periodInt.(int))
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.Period = time.Second * time.Duration(data.Get("period").(int))
|
||||
}
|
||||
|
||||
renewableInt, ok := data.GetOk("renewable")
|
||||
if ok {
|
||||
entry.Renewable = renewableInt.(bool)
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.Renewable = data.Get("renewable").(bool)
|
||||
}
|
||||
|
||||
boundCIDRsRaw, ok := data.GetOk("bound_cidrs")
|
||||
if ok {
|
||||
boundCIDRs := boundCIDRsRaw.([]string)
|
||||
if len(boundCIDRs) == 0 {
|
||||
entry.BoundCIDRs = nil
|
||||
} else {
|
||||
var parsedCIDRs []*sockaddr.SockAddrMarshaler
|
||||
for _, v := range boundCIDRs {
|
||||
parsedCIDR, err := sockaddr.NewSockAddr(v)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(errwrap.Wrapf(fmt.Sprintf("invalid value %q when parsing bound cidrs: {{err}}", v), err).Error()), nil
|
||||
}
|
||||
parsedCIDRs = append(parsedCIDRs, &sockaddr.SockAddrMarshaler{parsedCIDR})
|
||||
}
|
||||
entry.BoundCIDRs = parsedCIDRs
|
||||
// First parse fields not duplicated by the token helper
|
||||
{
|
||||
orphanInt, ok := data.GetOk("orphan")
|
||||
if ok {
|
||||
entry.Orphan = orphanInt.(bool)
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.Orphan = data.Get("orphan").(bool)
|
||||
}
|
||||
|
||||
renewableInt, ok := data.GetOk("renewable")
|
||||
if ok {
|
||||
entry.Renewable = renewableInt.(bool)
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.Renewable = data.Get("renewable").(bool)
|
||||
}
|
||||
|
||||
pathSuffixInt, ok := data.GetOk("path_suffix")
|
||||
if ok {
|
||||
pathSuffix := pathSuffixInt.(string)
|
||||
switch {
|
||||
case pathSuffix != "":
|
||||
matched := pathSuffixSanitize.MatchString(pathSuffix)
|
||||
if !matched {
|
||||
return logical.ErrorResponse(fmt.Sprintf(
|
||||
"given role path suffix contains invalid characters; must match %s",
|
||||
pathSuffixSanitize.String())), nil
|
||||
}
|
||||
}
|
||||
entry.PathSuffix = pathSuffix
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.PathSuffix = data.Get("path_suffix").(string)
|
||||
}
|
||||
|
||||
if strings.Contains(entry.PathSuffix, "..") {
|
||||
return logical.ErrorResponse(fmt.Sprintf("error registering path suffix: %s", consts.ErrPathContainsParentReferences)), nil
|
||||
}
|
||||
|
||||
allowedPoliciesRaw, ok := data.GetOk("allowed_policies")
|
||||
if ok {
|
||||
entry.AllowedPolicies = policyutil.SanitizePolicies(allowedPoliciesRaw.([]string), policyutil.DoNotAddDefaultPolicy)
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.AllowedPolicies = policyutil.SanitizePolicies(data.Get("allowed_policies").([]string), policyutil.DoNotAddDefaultPolicy)
|
||||
}
|
||||
|
||||
disallowedPoliciesRaw, ok := data.GetOk("disallowed_policies")
|
||||
if ok {
|
||||
entry.DisallowedPolicies = strutil.RemoveDuplicates(disallowedPoliciesRaw.([]string), true)
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.DisallowedPolicies = strutil.RemoveDuplicates(data.Get("disallowed_policies").([]string), true)
|
||||
}
|
||||
}
|
||||
|
||||
// Next parse token fields from the helper
|
||||
if err := entry.ParseTokenFields(req, data); err != nil {
|
||||
return logical.ErrorResponse(errwrap.Wrapf("error parsing role fields: {{err}}", err).Error()), nil
|
||||
}
|
||||
|
||||
var resp *logical.Response
|
||||
|
||||
explicitMaxTTLInt, ok := data.GetOk("explicit_max_ttl")
|
||||
if ok {
|
||||
entry.ExplicitMaxTTL = time.Second * time.Duration(explicitMaxTTLInt.(int))
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.ExplicitMaxTTL = time.Second * time.Duration(data.Get("explicit_max_ttl").(int))
|
||||
// Now handle backwards compat. Prefer token_ fields over others if both
|
||||
// are set. We set the original fields here so that on read of token role
|
||||
// we can return the same values that were set. We clear out the Token*
|
||||
// values because otherwise when we read the role back we'll read stale
|
||||
// data since if they're not emptied they'll take precedence.
|
||||
periodRaw, ok := data.GetOk("token_period")
|
||||
if !ok {
|
||||
periodRaw, ok = data.GetOk("period")
|
||||
if ok {
|
||||
entry.Period = time.Second * time.Duration(periodRaw.(int))
|
||||
entry.TokenPeriod = 0
|
||||
}
|
||||
} else {
|
||||
_, ok = data.GetOk("period")
|
||||
if ok {
|
||||
if resp == nil {
|
||||
resp = &logical.Response{}
|
||||
}
|
||||
resp.AddWarning("Both 'token_period' and deprecated 'period' value supplied, ignoring the deprecated value")
|
||||
}
|
||||
entry.Period = 0
|
||||
}
|
||||
if entry.ExplicitMaxTTL != 0 {
|
||||
|
||||
boundCIDRsRaw, ok := data.GetOk("token_bound_cidrs")
|
||||
if !ok {
|
||||
boundCIDRsRaw, ok = data.GetOk("bound_cidrs")
|
||||
if ok {
|
||||
boundCIDRs, err := parseutil.ParseAddrs(boundCIDRsRaw.([]string))
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(errwrap.Wrapf("error parsing bound_cidrs: {{err}}", err).Error()), nil
|
||||
}
|
||||
entry.BoundCIDRs = boundCIDRs
|
||||
entry.TokenBoundCIDRs = nil
|
||||
}
|
||||
} else {
|
||||
_, ok = data.GetOk("bound_cidrs")
|
||||
if ok {
|
||||
if resp == nil {
|
||||
resp = &logical.Response{}
|
||||
}
|
||||
resp.AddWarning("Both 'token_bound_cidrs' and deprecated 'bound_cidrs' value supplied, ignoring the deprecated value")
|
||||
}
|
||||
entry.BoundCIDRs = nil
|
||||
}
|
||||
|
||||
finalExplicitMaxTTL := entry.TokenExplicitMaxTTL
|
||||
explicitMaxTTLRaw, ok := data.GetOk("token_explicit_max_ttl")
|
||||
if !ok {
|
||||
explicitMaxTTLRaw, ok = data.GetOk("explicit_max_ttl")
|
||||
if ok {
|
||||
entry.ExplicitMaxTTL = time.Second * time.Duration(explicitMaxTTLRaw.(int))
|
||||
entry.TokenExplicitMaxTTL = 0
|
||||
}
|
||||
finalExplicitMaxTTL = entry.ExplicitMaxTTL
|
||||
} else {
|
||||
_, ok = data.GetOk("explicit_max_ttl")
|
||||
if ok {
|
||||
if resp == nil {
|
||||
resp = &logical.Response{}
|
||||
}
|
||||
resp.AddWarning("Both 'token_explicit_max_ttl' and deprecated 'explicit_max_ttl' value supplied, ignoring the deprecated value")
|
||||
}
|
||||
entry.ExplicitMaxTTL = 0
|
||||
}
|
||||
if finalExplicitMaxTTL != 0 {
|
||||
sysView := ts.System()
|
||||
|
||||
if sysView.MaxLeaseTTL() != time.Duration(0) && entry.ExplicitMaxTTL > sysView.MaxLeaseTTL() {
|
||||
if sysView.MaxLeaseTTL() != time.Duration(0) && finalExplicitMaxTTL > sysView.MaxLeaseTTL() {
|
||||
if resp == nil {
|
||||
resp = &logical.Response{}
|
||||
}
|
||||
resp.AddWarning(fmt.Sprintf(
|
||||
"Given explicit max TTL of %d is greater than system/mount allowed value of %d seconds; until this is fixed attempting to create tokens against this role will result in an error",
|
||||
int64(entry.ExplicitMaxTTL.Seconds()), int64(sysView.MaxLeaseTTL().Seconds())))
|
||||
int64(finalExplicitMaxTTL.Seconds()), int64(sysView.MaxLeaseTTL().Seconds())))
|
||||
}
|
||||
}
|
||||
|
||||
pathSuffixInt, ok := data.GetOk("path_suffix")
|
||||
// no legacy version without the token_ prefix to check for
|
||||
tokenNumUses, ok := data.GetOk("token_num_uses")
|
||||
if ok {
|
||||
pathSuffix := pathSuffixInt.(string)
|
||||
switch {
|
||||
case pathSuffix != "":
|
||||
matched := pathSuffixSanitize.MatchString(pathSuffix)
|
||||
if !matched {
|
||||
return logical.ErrorResponse(fmt.Sprintf(
|
||||
"given role path suffix contains invalid characters; must match %s",
|
||||
pathSuffixSanitize.String())), nil
|
||||
}
|
||||
}
|
||||
entry.PathSuffix = pathSuffix
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.PathSuffix = data.Get("path_suffix").(string)
|
||||
entry.TokenNumUses = tokenNumUses.(int)
|
||||
}
|
||||
|
||||
if strings.Contains(entry.PathSuffix, "..") {
|
||||
return logical.ErrorResponse(fmt.Sprintf("error registering path suffix: %s", consts.ErrPathContainsParentReferences)), nil
|
||||
}
|
||||
|
||||
allowedPoliciesRaw, ok := data.GetOk("allowed_policies")
|
||||
if ok {
|
||||
entry.AllowedPolicies = policyutil.SanitizePolicies(allowedPoliciesRaw.([]string), policyutil.DoNotAddDefaultPolicy)
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.AllowedPolicies = policyutil.SanitizePolicies(data.Get("allowed_policies").([]string), policyutil.DoNotAddDefaultPolicy)
|
||||
}
|
||||
|
||||
disallowedPoliciesRaw, ok := data.GetOk("disallowed_policies")
|
||||
if ok {
|
||||
entry.DisallowedPolicies = strutil.RemoveDuplicates(disallowedPoliciesRaw.([]string), true)
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
entry.DisallowedPolicies = strutil.RemoveDuplicates(data.Get("disallowed_policies").([]string), true)
|
||||
}
|
||||
|
||||
tokenType := entry.TokenType
|
||||
if tokenType == logical.TokenTypeDefault {
|
||||
tokenType = logical.TokenTypeDefaultService
|
||||
}
|
||||
tokenTypeRaw, ok := data.GetOk("token_type")
|
||||
if ok {
|
||||
tokenTypeStr := tokenTypeRaw.(string)
|
||||
switch tokenTypeStr {
|
||||
case "service":
|
||||
tokenType = logical.TokenTypeService
|
||||
case "batch":
|
||||
tokenType = logical.TokenTypeBatch
|
||||
case "default-service":
|
||||
tokenType = logical.TokenTypeDefaultService
|
||||
case "default-batch":
|
||||
tokenType = logical.TokenTypeDefaultBatch
|
||||
default:
|
||||
return logical.ErrorResponse(fmt.Sprintf("invalid 'token_type' value %q", tokenTypeStr)), nil
|
||||
}
|
||||
} else if req.Operation == logical.CreateOperation {
|
||||
tokenType = logical.TokenTypeDefaultService
|
||||
}
|
||||
entry.TokenType = tokenType
|
||||
|
||||
// Run validity checks on token type
|
||||
if entry.TokenType == logical.TokenTypeBatch {
|
||||
if !entry.Orphan {
|
||||
return logical.ErrorResponse("'token_type' cannot be 'batch' when role is set to generate non-orphan tokens"), nil
|
||||
}
|
||||
if entry.Period != 0 {
|
||||
if entry.Period != 0 || entry.TokenPeriod != 0 {
|
||||
return logical.ErrorResponse("'token_type' cannot be 'batch' when role is set to generate periodic tokens"), nil
|
||||
}
|
||||
if entry.Renewable {
|
||||
return logical.ErrorResponse("'token_type' cannot be 'batch' when role is set to generate renewable tokens"), nil
|
||||
}
|
||||
if entry.ExplicitMaxTTL != 0 {
|
||||
if entry.ExplicitMaxTTL != 0 || entry.TokenExplicitMaxTTL != 0 {
|
||||
return logical.ErrorResponse("'token_type' cannot be 'batch' when role is set to generate tokens with an explicit max TTL"), nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import (
|
|||
uuid "github.com/hashicorp/go-uuid"
|
||||
"github.com/hashicorp/vault/helper/namespace"
|
||||
"github.com/hashicorp/vault/sdk/helper/locksutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/parseutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/tokenutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
|
|
@ -2679,6 +2681,8 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
|
|||
"allowed_policies": "test1,test2",
|
||||
"path_suffix": "happenin",
|
||||
"bound_cidrs": []string{"0.0.0.0/0"},
|
||||
"explicit_max_ttl": "2h",
|
||||
"token_num_uses": 123,
|
||||
}
|
||||
|
||||
resp, err = core.HandleRequest(namespace.RootContext(nil), req)
|
||||
|
|
@ -2703,21 +2707,28 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
|
|||
}
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"name": "test",
|
||||
"orphan": true,
|
||||
"period": int64(259200),
|
||||
"allowed_policies": []string{"test1", "test2"},
|
||||
"disallowed_policies": []string{},
|
||||
"path_suffix": "happenin",
|
||||
"explicit_max_ttl": int64(0),
|
||||
"renewable": true,
|
||||
"token_type": "default-service",
|
||||
"name": "test",
|
||||
"orphan": true,
|
||||
"token_period": int64(259200),
|
||||
"period": int64(259200),
|
||||
"allowed_policies": []string{"test1", "test2"},
|
||||
"disallowed_policies": []string{},
|
||||
"path_suffix": "happenin",
|
||||
"explicit_max_ttl": int64(7200),
|
||||
"token_explicit_max_ttl": int64(7200),
|
||||
"renewable": true,
|
||||
"token_type": "default-service",
|
||||
"token_num_uses": 123,
|
||||
}
|
||||
|
||||
if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
|
||||
t.Fatal("unexpected bound cidrs")
|
||||
}
|
||||
delete(resp.Data, "bound_cidrs")
|
||||
if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
|
||||
t.Fatal("unexpected bound cidrs")
|
||||
}
|
||||
delete(resp.Data, "token_bound_cidrs")
|
||||
|
||||
if diff := deep.Equal(expected, resp.Data); diff != nil {
|
||||
t.Fatal(diff)
|
||||
|
|
@ -2731,6 +2742,8 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
|
|||
"allowed_policies": "test3",
|
||||
"path_suffix": "happenin",
|
||||
"renewable": false,
|
||||
"explicit_max_ttl": "80h",
|
||||
"token_num_uses": 0,
|
||||
}
|
||||
|
||||
resp, err = core.HandleRequest(namespace.RootContext(nil), req)
|
||||
|
|
@ -2754,21 +2767,27 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
|
|||
}
|
||||
|
||||
expected = map[string]interface{}{
|
||||
"name": "test",
|
||||
"orphan": true,
|
||||
"period": int64(284400),
|
||||
"allowed_policies": []string{"test3"},
|
||||
"disallowed_policies": []string{},
|
||||
"path_suffix": "happenin",
|
||||
"explicit_max_ttl": int64(0),
|
||||
"renewable": false,
|
||||
"token_type": "default-service",
|
||||
"name": "test",
|
||||
"orphan": true,
|
||||
"period": int64(284400),
|
||||
"token_period": int64(284400),
|
||||
"allowed_policies": []string{"test3"},
|
||||
"disallowed_policies": []string{},
|
||||
"path_suffix": "happenin",
|
||||
"token_explicit_max_ttl": int64(288000),
|
||||
"explicit_max_ttl": int64(288000),
|
||||
"renewable": false,
|
||||
"token_type": "default-service",
|
||||
}
|
||||
|
||||
if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
|
||||
t.Fatal("unexpected bound cidrs")
|
||||
}
|
||||
delete(resp.Data, "bound_cidrs")
|
||||
if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
|
||||
t.Fatal("unexpected bound cidrs")
|
||||
}
|
||||
delete(resp.Data, "token_bound_cidrs")
|
||||
|
||||
if diff := deep.Equal(expected, resp.Data); diff != nil {
|
||||
t.Fatal(diff)
|
||||
|
|
@ -2797,21 +2816,27 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
|
|||
}
|
||||
|
||||
expected = map[string]interface{}{
|
||||
"name": "test",
|
||||
"orphan": true,
|
||||
"explicit_max_ttl": int64(5),
|
||||
"allowed_policies": []string{"test3"},
|
||||
"disallowed_policies": []string{},
|
||||
"path_suffix": "happenin",
|
||||
"period": int64(0),
|
||||
"renewable": false,
|
||||
"token_type": "default-service",
|
||||
"name": "test",
|
||||
"orphan": true,
|
||||
"explicit_max_ttl": int64(5),
|
||||
"token_explicit_max_ttl": int64(5),
|
||||
"allowed_policies": []string{"test3"},
|
||||
"disallowed_policies": []string{},
|
||||
"path_suffix": "happenin",
|
||||
"period": int64(0),
|
||||
"token_period": int64(0),
|
||||
"renewable": false,
|
||||
"token_type": "default-service",
|
||||
}
|
||||
|
||||
if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
|
||||
t.Fatal("unexpected bound cidrs")
|
||||
}
|
||||
delete(resp.Data, "bound_cidrs")
|
||||
if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "0.0.0.0/0" {
|
||||
t.Fatal("unexpected bound cidrs")
|
||||
}
|
||||
delete(resp.Data, "token_bound_cidrs")
|
||||
|
||||
if diff := deep.Equal(expected, resp.Data); diff != nil {
|
||||
t.Fatal(diff)
|
||||
|
|
@ -2840,15 +2865,17 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
|
|||
}
|
||||
|
||||
expected = map[string]interface{}{
|
||||
"name": "test",
|
||||
"orphan": true,
|
||||
"explicit_max_ttl": int64(5),
|
||||
"allowed_policies": []string{"test3"},
|
||||
"disallowed_policies": []string{},
|
||||
"path_suffix": "",
|
||||
"period": int64(0),
|
||||
"renewable": false,
|
||||
"token_type": "default-service",
|
||||
"name": "test",
|
||||
"orphan": true,
|
||||
"token_explicit_max_ttl": int64(5),
|
||||
"explicit_max_ttl": int64(5),
|
||||
"allowed_policies": []string{"test3"},
|
||||
"disallowed_policies": []string{},
|
||||
"path_suffix": "",
|
||||
"period": int64(0),
|
||||
"token_period": int64(0),
|
||||
"renewable": false,
|
||||
"token_type": "default-service",
|
||||
}
|
||||
|
||||
if diff := deep.Equal(expected, resp.Data); diff != nil {
|
||||
|
|
@ -3585,6 +3612,248 @@ func TestTokenStore_RoleExplicitMaxTTL(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTokenStore_RoleTokenFields(t *testing.T) {
|
||||
c, _, _ := TestCoreUnsealed(t)
|
||||
//c, _, root := TestCoreUnsealed(t)
|
||||
ts := c.tokenStore
|
||||
rootContext := namespace.RootContext(context.Background())
|
||||
|
||||
boundCIDRs, err := parseutil.ParseAddrs([]string{"127.0.0.1/32"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// First test the upgrade case. Create a role with values and ensure they
|
||||
// are reflected properly on read.
|
||||
{
|
||||
roleEntry := &tsRoleEntry{
|
||||
Name: "test",
|
||||
TokenParams: tokenutil.TokenParams{
|
||||
TokenType: logical.TokenTypeBatch,
|
||||
},
|
||||
Period: time.Second,
|
||||
ExplicitMaxTTL: time.Hour,
|
||||
}
|
||||
roleEntry.BoundCIDRs = boundCIDRs
|
||||
ns := namespace.RootNamespace
|
||||
jsonEntry, err := logical.StorageEntryJSON("test", roleEntry)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := ts.rolesView(ns).Put(rootContext, jsonEntry); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Read it back
|
||||
roleEntry, err = ts.tokenStoreRole(rootContext, "test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expRoleEntry := &tsRoleEntry{
|
||||
Name: "test",
|
||||
TokenParams: tokenutil.TokenParams{
|
||||
TokenPeriod: time.Second,
|
||||
TokenExplicitMaxTTL: time.Hour,
|
||||
TokenBoundCIDRs: boundCIDRs,
|
||||
TokenType: logical.TokenTypeBatch,
|
||||
},
|
||||
Period: time.Second,
|
||||
ExplicitMaxTTL: time.Hour,
|
||||
BoundCIDRs: boundCIDRs,
|
||||
}
|
||||
if diff := deep.Equal(expRoleEntry, roleEntry); diff != nil {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// Now, read that back through the API and verify we see what we expect
|
||||
{
|
||||
req := logical.TestRequest(t, logical.ReadOperation, "roles/test")
|
||||
resp, err := ts.HandleRequest(rootContext, req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"name": "test",
|
||||
"orphan": false,
|
||||
"period": int64(1),
|
||||
"token_period": int64(1),
|
||||
"allowed_policies": []string(nil),
|
||||
"disallowed_policies": []string(nil),
|
||||
"path_suffix": "",
|
||||
"token_explicit_max_ttl": int64(3600),
|
||||
"explicit_max_ttl": int64(3600),
|
||||
"renewable": false,
|
||||
"token_type": "batch",
|
||||
}
|
||||
|
||||
if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
|
||||
t.Fatalf("unexpected bound cidrs: %s", resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
|
||||
}
|
||||
delete(resp.Data, "bound_cidrs")
|
||||
if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
|
||||
t.Fatalf("unexpected token bound cidrs: %s", resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
|
||||
}
|
||||
delete(resp.Data, "token_bound_cidrs")
|
||||
|
||||
if diff := deep.Equal(expected, resp.Data); diff != nil {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// Put values in just the old locations, but through the API
|
||||
{
|
||||
req := logical.TestRequest(t, logical.UpdateOperation, "roles/test")
|
||||
req.Data = map[string]interface{}{
|
||||
"explicit_max_ttl": 7200,
|
||||
"token_type": "default-batch",
|
||||
"period": 5,
|
||||
"bound_cidrs": boundCIDRs[0].String(),
|
||||
}
|
||||
|
||||
resp, err := ts.HandleRequest(rootContext, req)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("err: %v\nresp: %#v", err, resp)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("expected a nil response")
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "roles/test")
|
||||
resp, err = ts.HandleRequest(rootContext, req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"name": "test",
|
||||
"orphan": false,
|
||||
"period": int64(5),
|
||||
"token_period": int64(5),
|
||||
"allowed_policies": []string(nil),
|
||||
"disallowed_policies": []string(nil),
|
||||
"path_suffix": "",
|
||||
"token_explicit_max_ttl": int64(7200),
|
||||
"explicit_max_ttl": int64(7200),
|
||||
"renewable": false,
|
||||
"token_type": "default-batch",
|
||||
}
|
||||
|
||||
if resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
|
||||
t.Fatalf("unexpected bound cidrs: %s", resp.Data["bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
|
||||
}
|
||||
delete(resp.Data, "bound_cidrs")
|
||||
if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
|
||||
t.Fatalf("unexpected token bound cidrs: %s", resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
|
||||
}
|
||||
delete(resp.Data, "token_bound_cidrs")
|
||||
|
||||
if diff := deep.Equal(expected, resp.Data); diff != nil {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
// Same thing for just the new locations
|
||||
{
|
||||
req := logical.TestRequest(t, logical.UpdateOperation, "roles/test")
|
||||
req.Data = map[string]interface{}{
|
||||
"token_explicit_max_ttl": 5200,
|
||||
"token_type": "default-service",
|
||||
"token_period": 7,
|
||||
"token_bound_cidrs": boundCIDRs[0].String(),
|
||||
}
|
||||
|
||||
resp, err := ts.HandleRequest(rootContext, req)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("err: %v\nresp: %#v", err, resp)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("expected a nil response")
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "roles/test")
|
||||
resp, err = ts.HandleRequest(rootContext, req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"name": "test",
|
||||
"orphan": false,
|
||||
"period": int64(0),
|
||||
"token_period": int64(7),
|
||||
"allowed_policies": []string(nil),
|
||||
"disallowed_policies": []string(nil),
|
||||
"path_suffix": "",
|
||||
"token_explicit_max_ttl": int64(5200),
|
||||
"explicit_max_ttl": int64(0),
|
||||
"renewable": false,
|
||||
"token_type": "default-service",
|
||||
}
|
||||
|
||||
if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
|
||||
t.Fatalf("unexpected token bound cidrs: %s", resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
|
||||
}
|
||||
delete(resp.Data, "token_bound_cidrs")
|
||||
|
||||
if diff := deep.Equal(expected, resp.Data); diff != nil {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
// Put values in both locations
|
||||
{
|
||||
req := logical.TestRequest(t, logical.UpdateOperation, "roles/test")
|
||||
req.Data = map[string]interface{}{
|
||||
"token_explicit_max_ttl": 7200,
|
||||
"explicit_max_ttl": 5200,
|
||||
"token_type": "service",
|
||||
"token_period": 5,
|
||||
"period": 1,
|
||||
"token_bound_cidrs": boundCIDRs[0].String(),
|
||||
"bound_cidrs": boundCIDRs[0].String(),
|
||||
}
|
||||
|
||||
resp, err := ts.HandleRequest(rootContext, req)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("err: %v\nresp: %#v", err, resp)
|
||||
}
|
||||
if resp == nil {
|
||||
t.Fatalf("expected a non-nil response")
|
||||
}
|
||||
if len(resp.Warnings) != 3 {
|
||||
t.Fatalf("expected 3 warnings, got %#v", resp.Warnings)
|
||||
}
|
||||
|
||||
req = logical.TestRequest(t, logical.ReadOperation, "roles/test")
|
||||
resp, err = ts.HandleRequest(rootContext, req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
expected := map[string]interface{}{
|
||||
"name": "test",
|
||||
"orphan": false,
|
||||
"period": int64(0),
|
||||
"token_period": int64(5),
|
||||
"allowed_policies": []string(nil),
|
||||
"disallowed_policies": []string(nil),
|
||||
"path_suffix": "",
|
||||
"token_explicit_max_ttl": int64(7200),
|
||||
"explicit_max_ttl": int64(0),
|
||||
"renewable": false,
|
||||
"token_type": "service",
|
||||
}
|
||||
|
||||
if resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String() != "127.0.0.1" {
|
||||
t.Fatalf("unexpected token bound cidrs: %s", resp.Data["token_bound_cidrs"].([]*sockaddr.SockAddrMarshaler)[0].String())
|
||||
}
|
||||
delete(resp.Data, "token_bound_cidrs")
|
||||
|
||||
if diff := deep.Equal(expected, resp.Data); diff != nil {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenStore_Periodic(t *testing.T) {
|
||||
core, _, root := TestCoreUnsealed(t)
|
||||
|
||||
|
|
@ -3726,6 +3995,120 @@ func TestTokenStore_Periodic(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func testTokenStore_NumUses_ErrorCheckHelper(t *testing.T, resp *logical.Response, err error) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if resp == nil {
|
||||
t.Fatal("response was nil")
|
||||
}
|
||||
if resp.Auth == nil {
|
||||
t.Fatalf(fmt.Sprintf("response auth was nil, resp is %#v", *resp))
|
||||
}
|
||||
if resp.Auth.ClientToken == "" {
|
||||
t.Fatalf("bad: %#v", resp)
|
||||
}
|
||||
}
|
||||
|
||||
func testTokenStore_NumUses_SelfLookupHelper(t *testing.T, core *Core, clientToken string, expectedNumUses int) {
|
||||
req := logical.TestRequest(t, logical.ReadOperation, "auth/token/lookup-self")
|
||||
req.ClientToken = clientToken
|
||||
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
// Just used the token, this should decrement the num_uses counter
|
||||
expectedNumUses = expectedNumUses - 1
|
||||
actualNumUses := resp.Data["num_uses"].(int)
|
||||
|
||||
if actualNumUses != expectedNumUses {
|
||||
t.Fatalf("num_uses mismatch (expected %d, got %d)", expectedNumUses, actualNumUses)
|
||||
}
|
||||
}
|
||||
func TestTokenStore_NumUses(t *testing.T) {
|
||||
core, _, root := TestCoreUnsealed(t)
|
||||
roleNumUses := 10
|
||||
lesserNumUses := 5
|
||||
greaterNumUses := 15
|
||||
|
||||
// Create a test role with limited token_num_uses
|
||||
req := logical.TestRequest(t, logical.UpdateOperation, "auth/token/roles/test-limited-uses")
|
||||
req.ClientToken = root
|
||||
req.Data = map[string]interface{}{
|
||||
"token_num_uses": roleNumUses,
|
||||
}
|
||||
resp, err := core.HandleRequest(namespace.RootContext(nil), req)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("err: %v\nresp: %#v", err, resp)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("expected a nil response")
|
||||
}
|
||||
|
||||
// Create a test role with unlimited token_num_uses
|
||||
req.Path = "auth/token/roles/test-unlimited-uses"
|
||||
req.Data = map[string]interface{}{}
|
||||
resp, err = core.HandleRequest(namespace.RootContext(nil), req)
|
||||
if err != nil || (resp != nil && resp.IsError()) {
|
||||
t.Fatalf("err: %v\nresp: %#v", err, resp)
|
||||
}
|
||||
if resp != nil {
|
||||
t.Fatalf("expected a nil response")
|
||||
}
|
||||
|
||||
// Generate some tokens from the test roles
|
||||
req.Path = "auth/token/create/test-limited-uses"
|
||||
|
||||
// first token, num_uses is expected to come from the limited uses role
|
||||
resp, err = core.HandleRequest(namespace.RootContext(nil), req)
|
||||
testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
|
||||
noOverrideToken := resp.Auth.ClientToken
|
||||
|
||||
// second token, override num_uses with a lesser value, this should become the value
|
||||
// applied to the token
|
||||
req.Data = map[string]interface{}{
|
||||
"num_uses": lesserNumUses,
|
||||
}
|
||||
resp, err = core.HandleRequest(namespace.RootContext(nil), req)
|
||||
testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
|
||||
lesserOverrideToken := resp.Auth.ClientToken
|
||||
|
||||
// third token, override num_uses with a greater value, the value
|
||||
// applied to the token should come from the limited uses role
|
||||
req.Data = map[string]interface{}{
|
||||
"num_uses": greaterNumUses,
|
||||
}
|
||||
resp, err = core.HandleRequest(namespace.RootContext(nil), req)
|
||||
testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
|
||||
greaterOverrideToken := resp.Auth.ClientToken
|
||||
|
||||
// fourth token, override num_uses with a zero value, a num_uses value of zero
|
||||
// has an internal meaning of unlimited so num_uses == 1 is actually less than
|
||||
// num_uses == 0. In this case, the lesser value of the limited-uses role should be applied.
|
||||
req.Data = map[string]interface{}{
|
||||
"num_uses": 0,
|
||||
}
|
||||
resp, err = core.HandleRequest(namespace.RootContext(nil), req)
|
||||
testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
|
||||
zeroOverrideToken := resp.Auth.ClientToken
|
||||
|
||||
// fifth token, override num_uses with a value from a role that has unlimited num_uses. num_uses
|
||||
// should be the specified num_uses parameter at the create endpoint
|
||||
req.Path = "auth/token/create/test-unlimited-uses"
|
||||
req.Data = map[string]interface{}{
|
||||
"num_uses": lesserNumUses,
|
||||
}
|
||||
resp, err = core.HandleRequest(namespace.RootContext(nil), req)
|
||||
testTokenStore_NumUses_ErrorCheckHelper(t, resp, err)
|
||||
unlimitedRoleOverrideToken := resp.Auth.ClientToken
|
||||
|
||||
testTokenStore_NumUses_SelfLookupHelper(t, core, noOverrideToken, roleNumUses)
|
||||
testTokenStore_NumUses_SelfLookupHelper(t, core, lesserOverrideToken, lesserNumUses)
|
||||
testTokenStore_NumUses_SelfLookupHelper(t, core, greaterOverrideToken, roleNumUses)
|
||||
testTokenStore_NumUses_SelfLookupHelper(t, core, zeroOverrideToken, roleNumUses)
|
||||
testTokenStore_NumUses_SelfLookupHelper(t, core, unlimitedRoleOverrideToken, lesserNumUses)
|
||||
}
|
||||
|
||||
func TestTokenStore_Periodic_ExplicitMax(t *testing.T) {
|
||||
core, _, root := TestCoreUnsealed(t)
|
||||
|
||||
|
|
|
|||
2
vendor/github.com/hashicorp/vault/api/go.mod
generated
vendored
2
vendor/github.com/hashicorp/vault/api/go.mod
generated
vendored
|
|
@ -11,7 +11,7 @@ require (
|
|||
github.com/hashicorp/go-retryablehttp v0.5.3
|
||||
github.com/hashicorp/go-rootcerts v1.0.0
|
||||
github.com/hashicorp/hcl v1.0.0
|
||||
github.com/hashicorp/vault/sdk v0.1.8
|
||||
github.com/hashicorp/vault/sdk v0.1.12-0.20190614165924-47d4e5b1f688
|
||||
github.com/mitchellh/mapstructure v1.1.2
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
|
||||
|
|
|
|||
4
vendor/github.com/hashicorp/vault/api/sys_rekey.go
generated
vendored
4
vendor/github.com/hashicorp/vault/api/sys_rekey.go
generated
vendored
|
|
@ -234,7 +234,7 @@ func (c *Sys) RekeyRetrieveBackup() (*RekeyRetrieveResponse, error) {
|
|||
}
|
||||
|
||||
func (c *Sys) RekeyRetrieveRecoveryBackup() (*RekeyRetrieveResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey/recovery-backup")
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey/recovery-key-backup")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
|
@ -275,7 +275,7 @@ func (c *Sys) RekeyDeleteBackup() error {
|
|||
}
|
||||
|
||||
func (c *Sys) RekeyDeleteRecoveryBackup() error {
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey/recovery-backup")
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey/recovery-key-backup")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
|
|
|||
233
vendor/github.com/hashicorp/vault/sdk/helper/tokenutil/tokenutil.go
generated
vendored
Normal file
233
vendor/github.com/hashicorp/vault/sdk/helper/tokenutil/tokenutil.go
generated
vendored
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
package tokenutil
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
sockaddr "github.com/hashicorp/go-sockaddr"
|
||||
"github.com/hashicorp/vault/sdk/framework"
|
||||
"github.com/hashicorp/vault/sdk/helper/parseutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/hashicorp/vault/sdk/logical"
|
||||
)
|
||||
|
||||
// TokenParams contains a set of common parameters that auth plugins can use
|
||||
// for setting token behavior
|
||||
type TokenParams struct {
|
||||
// The set of CIDRs that tokens generated using this role will be bound to
|
||||
TokenBoundCIDRs []*sockaddr.SockAddrMarshaler `json:"token_bound_cidrs"`
|
||||
|
||||
// If set, the token entry will have an explicit maximum TTL set, rather
|
||||
// than deferring to role/mount values
|
||||
TokenExplicitMaxTTL time.Duration `json:"token_explicit_max_ttl" mapstructure:"token_explicit_max_ttl"`
|
||||
|
||||
// The max TTL to use for the token
|
||||
TokenMaxTTL time.Duration `json:"token_max_ttl" mapstructure:"token_max_ttl"`
|
||||
|
||||
// If set, core will not automatically add default to the policy list
|
||||
TokenNoDefaultPolicy bool `json:"token_no_default_policy" mapstructure:"token_no_default_policy"`
|
||||
|
||||
// The maximum number of times a token issued from this role may be used.
|
||||
TokenNumUses int `json:"token_num_uses" mapstructure:"token_num_uses"`
|
||||
|
||||
// If non-zero, tokens created using this role will be able to be renewed
|
||||
// forever, but will have a fixed renewal period of this value
|
||||
TokenPeriod time.Duration `json:"token_period" mapstructure:"token_period"`
|
||||
|
||||
// The policies to set
|
||||
TokenPolicies []string `json:"token_policies" mapstructure:"token_policies"`
|
||||
|
||||
// The type of token this role should issue
|
||||
TokenType logical.TokenType `json:"token_type" mapstructure:"token_type"`
|
||||
|
||||
// The TTL to user for the token
|
||||
TokenTTL time.Duration `json:"token_ttl" mapstructure:"token_ttl"`
|
||||
}
|
||||
|
||||
// AddTokenFields adds fields to an existing role. It panics if it would
|
||||
// overwrite an existing field.
|
||||
func AddTokenFields(m map[string]*framework.FieldSchema) {
|
||||
AddTokenFieldsWithAllowList(m, nil)
|
||||
}
|
||||
|
||||
// AddTokenFields adds fields to an existing role. It panics if it would
|
||||
// overwrite an existing field. Allowed can be use to restrict the set, e.g. if
|
||||
// there would be conflicts.
|
||||
func AddTokenFieldsWithAllowList(m map[string]*framework.FieldSchema, allowed []string) {
|
||||
r := TokenFields()
|
||||
for k, v := range r {
|
||||
if len(allowed) > 0 && !strutil.StrListContains(allowed, k) {
|
||||
continue
|
||||
}
|
||||
if _, has := m[k]; has {
|
||||
panic(fmt.Sprintf("adding role field %s would overwrite existing field", k))
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// TokenFields provides a set of field schemas for the parameters
|
||||
func TokenFields() map[string]*framework.FieldSchema {
|
||||
return map[string]*framework.FieldSchema{
|
||||
"token_bound_cidrs": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `Comma separated string or JSON list of CIDR blocks. If set, specifies the blocks of IP addresses which are allowed to use the generated token.`,
|
||||
},
|
||||
|
||||
"token_explicit_max_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: tokenExplicitMaxTTLHelp,
|
||||
},
|
||||
|
||||
"token_max_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: "The maximum lifetime of the generated token",
|
||||
},
|
||||
|
||||
"token_no_default_policy": &framework.FieldSchema{
|
||||
Type: framework.TypeBool,
|
||||
Description: "If true, the 'default' policy will not automatically be added to generated tokens",
|
||||
},
|
||||
|
||||
"token_period": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: tokenPeriodHelp,
|
||||
},
|
||||
|
||||
"token_policies": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: "Comma-separated list of policies",
|
||||
},
|
||||
|
||||
"token_type": &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Default: "default-service",
|
||||
Description: "The type of token to generate, service or batch",
|
||||
},
|
||||
|
||||
"token_ttl": &framework.FieldSchema{
|
||||
Type: framework.TypeDurationSecond,
|
||||
Description: "The initial ttl of the token to generate",
|
||||
},
|
||||
|
||||
"token_num_uses": &framework.FieldSchema{
|
||||
Type: framework.TypeInt,
|
||||
Description: "The maximum number of times a token may be used, a value of zero means unlimited",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ParseTokenFields provides common field parsing functionality into a TokenFields struct
|
||||
func (t *TokenParams) ParseTokenFields(req *logical.Request, d *framework.FieldData) error {
|
||||
if boundCIDRsRaw, ok := d.GetOk("token_bound_cidrs"); ok {
|
||||
boundCIDRs, err := parseutil.ParseAddrs(boundCIDRsRaw.([]string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.TokenBoundCIDRs = boundCIDRs
|
||||
}
|
||||
|
||||
if explicitMaxTTLRaw, ok := d.GetOk("token_explicit_max_ttl"); ok {
|
||||
t.TokenExplicitMaxTTL = time.Duration(explicitMaxTTLRaw.(int)) * time.Second
|
||||
}
|
||||
|
||||
if maxTTLRaw, ok := d.GetOk("token_max_ttl"); ok {
|
||||
t.TokenMaxTTL = time.Duration(maxTTLRaw.(int)) * time.Second
|
||||
}
|
||||
if t.TokenMaxTTL < 0 {
|
||||
return errors.New("'token_max_ttl' cannot be negative")
|
||||
}
|
||||
|
||||
if noDefaultRaw, ok := d.GetOk("token_no_default_policy"); ok {
|
||||
t.TokenNoDefaultPolicy = noDefaultRaw.(bool)
|
||||
}
|
||||
|
||||
if periodRaw, ok := d.GetOk("token_period"); ok {
|
||||
t.TokenPeriod = time.Duration(periodRaw.(int)) * time.Second
|
||||
}
|
||||
if t.TokenPeriod < 0 {
|
||||
return errors.New("'token_period' cannot be negative")
|
||||
}
|
||||
|
||||
if policiesRaw, ok := d.GetOk("token_policies"); ok {
|
||||
t.TokenPolicies = policiesRaw.([]string)
|
||||
}
|
||||
|
||||
if tokenTypeRaw, ok := d.GetOk("token_type"); ok {
|
||||
var tokenType logical.TokenType
|
||||
tokenTypeStr := tokenTypeRaw.(string)
|
||||
switch tokenTypeStr {
|
||||
case "service":
|
||||
tokenType = logical.TokenTypeService
|
||||
case "batch":
|
||||
tokenType = logical.TokenTypeBatch
|
||||
case "", "default", "default-service":
|
||||
tokenType = logical.TokenTypeDefaultService
|
||||
case "default-batch":
|
||||
tokenType = logical.TokenTypeDefaultBatch
|
||||
default:
|
||||
return fmt.Errorf("invalid 'token_type' value %q", tokenTypeStr)
|
||||
}
|
||||
t.TokenType = tokenType
|
||||
}
|
||||
|
||||
if ttlRaw, ok := d.GetOk("token_ttl"); ok {
|
||||
t.TokenTTL = time.Duration(ttlRaw.(int)) * time.Second
|
||||
}
|
||||
if t.TokenTTL < 0 {
|
||||
return errors.New("'token_ttl' cannot be negative")
|
||||
}
|
||||
if t.TokenTTL > 0 && t.TokenMaxTTL > 0 && t.TokenTTL > t.TokenMaxTTL {
|
||||
return errors.New("'token_ttl' cannot be greater than 'token_max_ttl'")
|
||||
}
|
||||
|
||||
if tokenNumUses, ok := d.GetOk("token_num_uses"); ok {
|
||||
t.TokenNumUses = tokenNumUses.(int)
|
||||
}
|
||||
if t.TokenNumUses < 0 {
|
||||
return errors.New("'token_num_uses' cannot be negative")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PopulateTokenData adds information from TokenParams into the map
|
||||
func (t *TokenParams) PopulateTokenData(m map[string]interface{}) {
|
||||
m["token_bound_cidrs"] = t.TokenBoundCIDRs
|
||||
m["token_explicit_max_ttl"] = t.TokenExplicitMaxTTL.Seconds()
|
||||
m["token_max_ttl"] = t.TokenMaxTTL.Seconds()
|
||||
m["token_no_default_policy"] = t.TokenNoDefaultPolicy
|
||||
m["token_period"] = t.TokenPeriod.Seconds()
|
||||
m["token_policies"] = t.TokenPolicies
|
||||
m["token_type"] = t.TokenType.String()
|
||||
m["token_ttl"] = t.TokenTTL.Seconds()
|
||||
m["token_num_uses"] = t.TokenNumUses
|
||||
}
|
||||
|
||||
// PopulateTokenAuth populates Auth with parameters
|
||||
func (t *TokenParams) PopulateTokenAuth(auth *logical.Auth) {
|
||||
auth.BoundCIDRs = t.TokenBoundCIDRs
|
||||
auth.ExplicitMaxTTL = t.TokenExplicitMaxTTL
|
||||
auth.MaxTTL = t.TokenMaxTTL
|
||||
auth.NoDefaultPolicy = t.TokenNoDefaultPolicy
|
||||
auth.Period = t.TokenPeriod
|
||||
auth.Policies = t.TokenPolicies
|
||||
auth.TokenType = t.TokenType
|
||||
auth.TTL = t.TokenTTL
|
||||
auth.NumUses = t.TokenNumUses
|
||||
}
|
||||
|
||||
const (
|
||||
tokenPeriodHelp = `If set, tokens created via this role
|
||||
will have no max lifetime; instead, their
|
||||
renewal period will be fixed to this value.
|
||||
This takes an integer number of seconds,
|
||||
or a string duration (e.g. "24h").`
|
||||
tokenExplicitMaxTTLHelp = `If set, tokens created via this role
|
||||
carry an explicit maximum TTL. During renewal,
|
||||
the current maximum TTL values of the role
|
||||
and the mount are not checked for changes,
|
||||
and any updates to these values will have
|
||||
no effect on the token being renewed.`
|
||||
)
|
||||
5
vendor/github.com/hashicorp/vault/sdk/logical/auth.go
generated
vendored
5
vendor/github.com/hashicorp/vault/sdk/logical/auth.go
generated
vendored
|
|
@ -38,6 +38,11 @@ type Auth struct {
|
|||
// different namespaces indexed by respective namespace identifiers
|
||||
ExternalNamespacePolicies map[string][]string `json:"external_namespace_policies" mapstructure:"external_namespace_policies" structs:"external_namespace_policies"`
|
||||
|
||||
// Indicates that the default policy should not be added by core when
|
||||
// creating a token. The default policy will still be added if it's
|
||||
// explicitly defined.
|
||||
NoDefaultPolicy bool `json:"no_default_policy" mapstructure:"no_default_policy" structs:"no_default_policy"`
|
||||
|
||||
// Metadata is used to attach arbitrary string-type metadata to
|
||||
// an authenticated user. This metadata will be outputted into the
|
||||
// audit log.
|
||||
|
|
|
|||
5
vendor/github.com/hashicorp/vault/sdk/logical/system_view.go
generated
vendored
5
vendor/github.com/hashicorp/vault/sdk/logical/system_view.go
generated
vendored
|
|
@ -72,6 +72,7 @@ type SystemView interface {
|
|||
|
||||
type ExtendedSystemView interface {
|
||||
Auditor() Auditor
|
||||
ForwardGenericRequest(context.Context, *Request) (*Response, error)
|
||||
}
|
||||
|
||||
type StaticSystemView struct {
|
||||
|
|
@ -104,6 +105,10 @@ func (d StaticSystemView) Auditor() Auditor {
|
|||
return noopAuditor{}
|
||||
}
|
||||
|
||||
func (d StaticSystemView) ForwardGenericRequest(ctx context.Context, req *Request) (*Response, error) {
|
||||
return nil, errors.New("ForwardGenericRequest is not implemented in StaticSystemView")
|
||||
}
|
||||
|
||||
func (d StaticSystemView) DefaultLeaseTTL() time.Duration {
|
||||
return d.DefaultLeaseTTLVal
|
||||
}
|
||||
|
|
|
|||
324
vendor/github.com/hashicorp/vault/sdk/plugin/pb/backend.pb.go
generated
vendored
324
vendor/github.com/hashicorp/vault/sdk/plugin/pb/backend.pb.go
generated
vendored
|
|
@ -526,7 +526,9 @@ type Auth struct {
|
|||
// TTL is a hard limit and cannot be exceeded, also counts for periodic tokens.
|
||||
ExplicitMaxTTL int64 `sentinel:"" protobuf:"varint,16,opt,name=explicit_max_ttl,json=explicitMaxTtl,proto3" json:"explicit_max_ttl,omitempty"`
|
||||
// TokenType is the type of token being requested
|
||||
TokenType uint32 `sentinel:"" protobuf:"varint,17,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
|
||||
TokenType uint32 `sentinel:"" protobuf:"varint,17,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
|
||||
// Whether the default policy should be added automatically by core
|
||||
NoDefaultPolicy bool `sentinel:"" protobuf:"varint,18,opt,name=no_default_policy,json=noDefaultPolicy,proto3" json:"no_default_policy,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
|
@ -676,6 +678,13 @@ func (m *Auth) GetTokenType() uint32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (m *Auth) GetNoDefaultPolicy() bool {
|
||||
if m != nil {
|
||||
return m.NoDefaultPolicy
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type TokenEntry struct {
|
||||
ID string `sentinel:"" protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Accessor string `sentinel:"" protobuf:"bytes,2,opt,name=accessor,proto3" json:"accessor,omitempty"`
|
||||
|
|
@ -2713,164 +2722,165 @@ func init() {
|
|||
func init() { proto.RegisterFile("sdk/plugin/pb/backend.proto", fileDescriptor_4dbf1dfe0c11846b) }
|
||||
|
||||
var fileDescriptor_4dbf1dfe0c11846b = []byte{
|
||||
// 2499 bytes of a gzipped FileDescriptorProto
|
||||
// 2519 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x59, 0xdb, 0x72, 0x1b, 0xc7,
|
||||
0xd1, 0x2e, 0x00, 0xc4, 0xa9, 0x71, 0x22, 0x46, 0xb4, 0xfe, 0x15, 0x24, 0xff, 0x82, 0xd7, 0x91,
|
||||
0x0c, 0x2b, 0x36, 0x68, 0x51, 0x71, 0x2c, 0x27, 0x65, 0xa7, 0x68, 0x8a, 0x96, 0x19, 0x93, 0x36,
|
||||
0x6b, 0x09, 0xc5, 0x39, 0x55, 0xc1, 0x83, 0xdd, 0x21, 0xb8, 0xc5, 0xc5, 0xee, 0x66, 0x76, 0x96,
|
||||
0x22, 0xae, 0xf2, 0x16, 0x79, 0x8d, 0xdc, 0xa6, 0x72, 0x93, 0xbb, 0x94, 0x2b, 0xf7, 0x79, 0x8d,
|
||||
0x3c, 0x43, 0x6a, 0x7a, 0x66, 0x4f, 0x00, 0x68, 0xc9, 0x55, 0xce, 0xdd, 0x4c, 0x77, 0xcf, 0xa9,
|
||||
0xe7, 0xeb, 0xaf, 0x7b, 0x76, 0xe1, 0x6e, 0xe4, 0x5c, 0xee, 0x86, 0x5e, 0x3c, 0x77, 0xfd, 0xdd,
|
||||
0x70, 0xb6, 0x3b, 0xa3, 0xf6, 0x25, 0xf3, 0x9d, 0x71, 0xc8, 0x03, 0x11, 0x90, 0x72, 0x38, 0x1b,
|
||||
0xdc, 0x9f, 0x07, 0xc1, 0xdc, 0x63, 0xbb, 0x28, 0x99, 0xc5, 0xe7, 0xbb, 0xc2, 0x5d, 0xb0, 0x48,
|
||||
0xd0, 0x45, 0xa8, 0x8c, 0x06, 0x03, 0x39, 0x83, 0x17, 0xcc, 0x5d, 0x9b, 0x7a, 0xbb, 0xae, 0xc3,
|
||||
0x7c, 0xe1, 0x8a, 0xa5, 0xd6, 0x19, 0x79, 0x9d, 0x5a, 0x45, 0x69, 0xcc, 0x3a, 0x54, 0x0f, 0x17,
|
||||
0xa1, 0x58, 0x9a, 0x43, 0xa8, 0x7d, 0xc1, 0xa8, 0xc3, 0x38, 0xb9, 0x0d, 0xb5, 0x0b, 0x6c, 0x19,
|
||||
0xa5, 0x61, 0x65, 0xd4, 0xb4, 0x74, 0xcf, 0xfc, 0x03, 0xc0, 0xa9, 0x1c, 0x73, 0xc8, 0x79, 0xc0,
|
||||
0xc9, 0x1d, 0x68, 0x30, 0xce, 0xa7, 0x62, 0x19, 0x32, 0xa3, 0x34, 0x2c, 0x8d, 0x3a, 0x56, 0x9d,
|
||||
0x71, 0x3e, 0x59, 0x86, 0x8c, 0xfc, 0x1f, 0xc8, 0xe6, 0x74, 0x11, 0xcd, 0x8d, 0xf2, 0xb0, 0x24,
|
||||
0x67, 0x60, 0x9c, 0x9f, 0x44, 0xf3, 0x64, 0x8c, 0x1d, 0x38, 0xcc, 0xa8, 0x0c, 0x4b, 0xa3, 0x0a,
|
||||
0x8e, 0x39, 0x08, 0x1c, 0x66, 0xfe, 0xa5, 0x04, 0xd5, 0x53, 0x2a, 0x2e, 0x22, 0x42, 0x60, 0x8b,
|
||||
0x07, 0x81, 0xd0, 0x8b, 0x63, 0x9b, 0x8c, 0xa0, 0x17, 0xfb, 0x34, 0x16, 0x17, 0xf2, 0x54, 0x36,
|
||||
0x15, 0xcc, 0x31, 0xca, 0xa8, 0x5e, 0x15, 0x93, 0xb7, 0xa1, 0xe3, 0x05, 0x36, 0xf5, 0xa6, 0x91,
|
||||
0x08, 0x38, 0x9d, 0xcb, 0x75, 0xa4, 0x5d, 0x1b, 0x85, 0x67, 0x4a, 0x46, 0x1e, 0x41, 0x3f, 0x62,
|
||||
0xd4, 0x9b, 0xbe, 0xe4, 0x34, 0x4c, 0x0d, 0xb7, 0xd4, 0x84, 0x52, 0xf1, 0x0d, 0xa7, 0xa1, 0xb6,
|
||||
0x35, 0xff, 0x51, 0x83, 0xba, 0xc5, 0xfe, 0x14, 0xb3, 0x48, 0x90, 0x2e, 0x94, 0x5d, 0x07, 0x4f,
|
||||
0xdb, 0xb4, 0xca, 0xae, 0x43, 0xc6, 0x40, 0x2c, 0x16, 0x7a, 0x72, 0x69, 0x37, 0xf0, 0x0f, 0xbc,
|
||||
0x38, 0x12, 0x8c, 0xeb, 0x33, 0x6f, 0xd0, 0x90, 0x7b, 0xd0, 0x0c, 0x42, 0xc6, 0x51, 0x86, 0x0e,
|
||||
0x68, 0x5a, 0x99, 0x40, 0x1e, 0x3c, 0xa4, 0xe2, 0xc2, 0xd8, 0x42, 0x05, 0xb6, 0xa5, 0xcc, 0xa1,
|
||||
0x82, 0x1a, 0x55, 0x25, 0x93, 0x6d, 0x62, 0x42, 0x2d, 0x62, 0x36, 0x67, 0xc2, 0xa8, 0x0d, 0x4b,
|
||||
0xa3, 0xd6, 0x1e, 0x8c, 0xc3, 0xd9, 0xf8, 0x0c, 0x25, 0x96, 0xd6, 0x90, 0x7b, 0xb0, 0x25, 0xfd,
|
||||
0x62, 0xd4, 0xd1, 0xa2, 0x21, 0x2d, 0xf6, 0x63, 0x71, 0x61, 0xa1, 0x94, 0xec, 0x41, 0x5d, 0xdd,
|
||||
0x69, 0x64, 0x34, 0x86, 0x95, 0x51, 0x6b, 0xcf, 0x90, 0x06, 0xfa, 0x94, 0x63, 0x05, 0x83, 0xe8,
|
||||
0xd0, 0x17, 0x7c, 0x69, 0x25, 0x86, 0xe4, 0x2d, 0x68, 0xdb, 0x9e, 0xcb, 0x7c, 0x31, 0x15, 0xc1,
|
||||
0x25, 0xf3, 0x8d, 0x26, 0xee, 0xa8, 0xa5, 0x64, 0x13, 0x29, 0x22, 0x7b, 0xf0, 0x46, 0xde, 0x64,
|
||||
0x4a, 0x6d, 0x9b, 0x45, 0x51, 0xc0, 0x0d, 0x40, 0xdb, 0x5b, 0x39, 0xdb, 0x7d, 0xad, 0x92, 0xd3,
|
||||
0x3a, 0x6e, 0x14, 0x7a, 0x74, 0x39, 0xf5, 0xe9, 0x82, 0x19, 0x2d, 0x35, 0xad, 0x96, 0x7d, 0x45,
|
||||
0x17, 0x8c, 0xdc, 0x87, 0xd6, 0x22, 0x88, 0x7d, 0x31, 0x0d, 0x03, 0xd7, 0x17, 0x46, 0x1b, 0x2d,
|
||||
0x00, 0x45, 0xa7, 0x52, 0x42, 0xde, 0x04, 0xd5, 0x53, 0x60, 0xec, 0x28, 0xbf, 0xa2, 0x04, 0xe1,
|
||||
0xf8, 0x00, 0xba, 0x4a, 0x9d, 0xee, 0xa7, 0x8b, 0x26, 0x1d, 0x94, 0xa6, 0x3b, 0xf9, 0x00, 0x9a,
|
||||
0x88, 0x07, 0xd7, 0x3f, 0x0f, 0x8c, 0x1e, 0xfa, 0xed, 0x56, 0xce, 0x2d, 0x12, 0x13, 0x47, 0xfe,
|
||||
0x79, 0x60, 0x35, 0x5e, 0xea, 0x16, 0xf9, 0x04, 0xee, 0x16, 0xce, 0xcb, 0xd9, 0x82, 0xba, 0xbe,
|
||||
0xeb, 0xcf, 0xa7, 0x71, 0xc4, 0x22, 0x63, 0x1b, 0x11, 0x6e, 0xe4, 0x4e, 0x6d, 0x25, 0x06, 0x2f,
|
||||
0x22, 0x16, 0x91, 0xbb, 0xd0, 0x54, 0x41, 0x3a, 0x75, 0x1d, 0xa3, 0x8f, 0x5b, 0x6a, 0x28, 0xc1,
|
||||
0x91, 0x43, 0xde, 0x81, 0x5e, 0x18, 0x78, 0xae, 0xbd, 0x9c, 0x06, 0x57, 0x8c, 0x73, 0xd7, 0x61,
|
||||
0x06, 0x19, 0x96, 0x46, 0x0d, 0xab, 0xab, 0xc4, 0x5f, 0x6b, 0xe9, 0xa6, 0xd0, 0xb8, 0x85, 0x86,
|
||||
0x6b, 0xa1, 0x31, 0x06, 0xb0, 0x03, 0xdf, 0x67, 0x36, 0xc2, 0x6f, 0x07, 0x4f, 0xd8, 0x95, 0x27,
|
||||
0x3c, 0x48, 0xa5, 0x56, 0xce, 0x62, 0xf0, 0x39, 0xb4, 0xf3, 0x50, 0x20, 0xdb, 0x50, 0xb9, 0x64,
|
||||
0x4b, 0x0d, 0x7f, 0xd9, 0x24, 0x43, 0xa8, 0x5e, 0x51, 0x2f, 0x66, 0x08, 0x79, 0x0d, 0x44, 0x35,
|
||||
0xc4, 0x52, 0x8a, 0x5f, 0x94, 0x9f, 0x96, 0xcc, 0xbf, 0x57, 0x61, 0x4b, 0x82, 0x8f, 0x7c, 0x08,
|
||||
0x1d, 0x8f, 0xd1, 0x88, 0x4d, 0x83, 0x50, 0x2e, 0x10, 0xe1, 0x54, 0xad, 0xbd, 0x6d, 0x39, 0xec,
|
||||
0x58, 0x2a, 0xbe, 0x56, 0x72, 0xab, 0xed, 0xe5, 0x7a, 0x32, 0xa4, 0x5d, 0x5f, 0x30, 0xee, 0x53,
|
||||
0x6f, 0x8a, 0xc1, 0xa0, 0x02, 0xac, 0x9d, 0x08, 0x9f, 0xc9, 0xa0, 0x58, 0xc5, 0x51, 0x65, 0x1d,
|
||||
0x47, 0x03, 0x68, 0xa0, 0xef, 0x5c, 0x16, 0xe9, 0x60, 0x4f, 0xfb, 0x64, 0x0f, 0x1a, 0x0b, 0x26,
|
||||
0xa8, 0x8e, 0x35, 0x19, 0x12, 0xb7, 0x93, 0x98, 0x19, 0x9f, 0x68, 0x85, 0x0a, 0x88, 0xd4, 0x6e,
|
||||
0x2d, 0x22, 0x6a, 0xeb, 0x11, 0x31, 0x80, 0x46, 0x0a, 0xba, 0xba, 0xba, 0xe1, 0xa4, 0x2f, 0x69,
|
||||
0x36, 0x64, 0xdc, 0x0d, 0x1c, 0xa3, 0x81, 0x40, 0xd1, 0x3d, 0x49, 0x92, 0x7e, 0xbc, 0x50, 0x10,
|
||||
0x6a, 0x2a, 0x92, 0xf4, 0xe3, 0xc5, 0x3a, 0x62, 0x60, 0x05, 0x31, 0x3f, 0x81, 0x2a, 0xf5, 0x5c,
|
||||
0x1a, 0x61, 0x08, 0xc9, 0x9b, 0xd5, 0x7c, 0x3f, 0xde, 0x97, 0x52, 0x4b, 0x29, 0xc9, 0x13, 0xe8,
|
||||
0xcc, 0x79, 0x10, 0x87, 0x53, 0xec, 0xb2, 0xc8, 0x68, 0xe3, 0x69, 0x57, 0xad, 0xdb, 0x68, 0xb4,
|
||||
0xaf, 0x6c, 0x64, 0x04, 0xce, 0x82, 0xd8, 0x77, 0xa6, 0xb6, 0xeb, 0xf0, 0xc8, 0xe8, 0xa0, 0xf3,
|
||||
0x00, 0x45, 0x07, 0x52, 0x22, 0x43, 0x4c, 0x85, 0x40, 0xea, 0xe0, 0x2e, 0xda, 0x74, 0x50, 0x7a,
|
||||
0x9a, 0x78, 0xf9, 0xa7, 0xd0, 0x4f, 0x12, 0x53, 0x66, 0xd9, 0x43, 0xcb, 0xed, 0x44, 0x91, 0x1a,
|
||||
0x8f, 0x60, 0x9b, 0x5d, 0x4b, 0x0a, 0x75, 0xc5, 0x74, 0x41, 0xaf, 0xa7, 0x42, 0x78, 0x3a, 0xa4,
|
||||
0xba, 0x89, 0xfc, 0x84, 0x5e, 0x4f, 0x84, 0x27, 0xe3, 0x5f, 0xad, 0x8e, 0xf1, 0xdf, 0xc7, 0x64,
|
||||
0xd4, 0x44, 0x89, 0x8c, 0xff, 0xc1, 0x2f, 0xa1, 0x53, 0xb8, 0xc2, 0x0d, 0x40, 0xde, 0xc9, 0x03,
|
||||
0xb9, 0x99, 0x07, 0xef, 0xbf, 0xb6, 0x00, 0xf0, 0x2e, 0xd5, 0xd0, 0xd5, 0x0c, 0x90, 0xbf, 0xe0,
|
||||
0xf2, 0x86, 0x0b, 0xa6, 0x9c, 0xf9, 0x42, 0x83, 0x51, 0xf7, 0xbe, 0x17, 0x87, 0x49, 0x0e, 0xa8,
|
||||
0xe6, 0x72, 0xc0, 0x7b, 0xb0, 0x25, 0x31, 0x67, 0xd4, 0x32, 0xaa, 0xce, 0x76, 0x84, 0xe8, 0x54,
|
||||
0xc8, 0x44, 0xab, 0xb5, 0x40, 0xa8, 0xaf, 0x07, 0x42, 0x1e, 0x61, 0x8d, 0x22, 0xc2, 0xde, 0x86,
|
||||
0x8e, 0xcd, 0x19, 0xe6, 0xa3, 0xa9, 0x2c, 0x30, 0x34, 0x02, 0xdb, 0x89, 0x70, 0xe2, 0x2e, 0x98,
|
||||
0xf4, 0x9f, 0xbc, 0x0c, 0x40, 0x95, 0x6c, 0x6e, 0xbc, 0xab, 0xd6, 0xc6, 0xbb, 0xc2, 0xec, 0xee,
|
||||
0x31, 0xcd, 0xe2, 0xd8, 0xce, 0x45, 0x42, 0xa7, 0x10, 0x09, 0x05, 0xb8, 0x77, 0x57, 0xe0, 0xbe,
|
||||
0x82, 0xc9, 0xde, 0x1a, 0x26, 0xdf, 0x82, 0xb6, 0x74, 0x40, 0x14, 0x52, 0x9b, 0xc9, 0x09, 0xb6,
|
||||
0x95, 0x23, 0x52, 0xd9, 0x91, 0x83, 0x11, 0x1c, 0xcf, 0x66, 0xcb, 0x8b, 0xc0, 0x63, 0x19, 0x09,
|
||||
0xb7, 0x52, 0xd9, 0x91, 0x23, 0xf7, 0x8b, 0xa8, 0x22, 0x88, 0x2a, 0x6c, 0x0f, 0x3e, 0x82, 0x66,
|
||||
0xea, 0xf5, 0x1f, 0x04, 0xa6, 0xbf, 0x96, 0xa0, 0x9d, 0x27, 0x3a, 0x39, 0x78, 0x32, 0x39, 0xc6,
|
||||
0xc1, 0x15, 0x4b, 0x36, 0x65, 0x89, 0xc0, 0x99, 0xcf, 0x5e, 0xd2, 0x99, 0xa7, 0x26, 0x68, 0x58,
|
||||
0x99, 0x40, 0x6a, 0x5d, 0xdf, 0xe6, 0x6c, 0x91, 0xa0, 0xaa, 0x62, 0x65, 0x02, 0xf2, 0x31, 0x80,
|
||||
0x1b, 0x45, 0x31, 0x53, 0x37, 0xb7, 0x85, 0x34, 0x30, 0x18, 0xab, 0xba, 0x71, 0x9c, 0xd4, 0x8d,
|
||||
0xe3, 0x49, 0x52, 0x37, 0x5a, 0x4d, 0xb4, 0xc6, 0x2b, 0xbd, 0x0d, 0x35, 0x79, 0x41, 0x93, 0x63,
|
||||
0x44, 0x5e, 0xc5, 0xd2, 0x3d, 0xf3, 0xcf, 0x50, 0x53, 0x95, 0xc5, 0xff, 0x94, 0xbc, 0xef, 0x40,
|
||||
0x43, 0xcd, 0xed, 0x3a, 0x3a, 0x56, 0xea, 0xd8, 0x3f, 0x72, 0xcc, 0xef, 0xca, 0xd0, 0xb0, 0x58,
|
||||
0x14, 0x06, 0x7e, 0xc4, 0x72, 0x95, 0x4f, 0xe9, 0x95, 0x95, 0x4f, 0x79, 0x63, 0xe5, 0x93, 0xd4,
|
||||
0x53, 0x95, 0x5c, 0x3d, 0x35, 0x80, 0x06, 0x67, 0x8e, 0xcb, 0x99, 0x2d, 0x74, 0xed, 0x95, 0xf6,
|
||||
0xa5, 0xee, 0x25, 0xe5, 0x32, 0x65, 0x47, 0x98, 0x17, 0x9a, 0x56, 0xda, 0x27, 0x8f, 0xf3, 0x05,
|
||||
0x83, 0x2a, 0xc5, 0x76, 0x54, 0xc1, 0xa0, 0xb6, 0xbb, 0xa1, 0x62, 0x78, 0x92, 0x15, 0x5e, 0x75,
|
||||
0x8c, 0xe6, 0x3b, 0xf9, 0x01, 0x9b, 0x2b, 0xaf, 0x1f, 0x2d, 0x0f, 0x7f, 0x57, 0x86, 0xed, 0xd5,
|
||||
0xbd, 0x6d, 0x40, 0xe0, 0x0e, 0x54, 0x55, 0x3e, 0xd3, 0xf0, 0x15, 0x6b, 0x99, 0xac, 0xb2, 0x42,
|
||||
0x74, 0xbf, 0x5a, 0x25, 0x8d, 0x57, 0x43, 0xaf, 0x48, 0x28, 0xef, 0xc2, 0xb6, 0x74, 0x51, 0xc8,
|
||||
0x9c, 0xac, 0x46, 0x53, 0x0c, 0xd8, 0xd3, 0xf2, 0xb4, 0x4a, 0x7b, 0x04, 0xfd, 0xc4, 0x34, 0xe3,
|
||||
0x86, 0x5a, 0xc1, 0xf6, 0x30, 0xa1, 0x88, 0xdb, 0x50, 0x3b, 0x0f, 0xf8, 0x82, 0x0a, 0x4d, 0x82,
|
||||
0xba, 0x57, 0x20, 0x39, 0x64, 0xdb, 0x86, 0xc2, 0x64, 0x22, 0x94, 0xef, 0x10, 0x49, 0x3e, 0xe9,
|
||||
0x1b, 0x01, 0x59, 0xb0, 0x61, 0x35, 0x92, 0xb7, 0x81, 0xf9, 0x5b, 0xe8, 0xad, 0x94, 0x85, 0x1b,
|
||||
0x1c, 0x99, 0x2d, 0x5f, 0x2e, 0x2c, 0x5f, 0x98, 0xb9, 0xb2, 0x32, 0xf3, 0xef, 0xa0, 0xff, 0x05,
|
||||
0xf5, 0x1d, 0x8f, 0xe9, 0xf9, 0xf7, 0xf9, 0x3c, 0x92, 0x09, 0x4e, 0xbf, 0x52, 0xa6, 0x3a, 0xfb,
|
||||
0x74, 0xac, 0xa6, 0x96, 0x1c, 0x39, 0xe4, 0x01, 0xd4, 0xb9, 0xb2, 0xd6, 0x00, 0x68, 0xe5, 0xea,
|
||||
0x56, 0x2b, 0xd1, 0x99, 0xdf, 0x02, 0x29, 0x4c, 0x2d, 0x1f, 0x28, 0x4b, 0x32, 0x92, 0xe8, 0x57,
|
||||
0xa0, 0xd0, 0x51, 0xd5, 0xce, 0x63, 0xd2, 0x4a, 0xb5, 0x64, 0x08, 0x15, 0xc6, 0xb9, 0x5e, 0x02,
|
||||
0x0b, 0xc7, 0xec, 0x39, 0x68, 0x49, 0x95, 0xf9, 0x33, 0xe8, 0x9f, 0x85, 0xcc, 0x76, 0xa9, 0x87,
|
||||
0x4f, 0x39, 0xb5, 0xc0, 0x7d, 0xa8, 0x4a, 0x27, 0x27, 0x84, 0xd1, 0xc4, 0x81, 0xa8, 0x56, 0x72,
|
||||
0xf3, 0x5b, 0x30, 0xd4, 0xbe, 0x0e, 0xaf, 0xdd, 0x48, 0x30, 0xdf, 0x66, 0x07, 0x17, 0xcc, 0xbe,
|
||||
0xfc, 0x11, 0x4f, 0x7e, 0x05, 0x77, 0x36, 0xad, 0x90, 0xec, 0xaf, 0x65, 0xcb, 0xde, 0xf4, 0x5c,
|
||||
0xe6, 0x0e, 0x5c, 0xa3, 0x61, 0x01, 0x8a, 0x3e, 0x97, 0x12, 0x79, 0x8f, 0x4c, 0x8e, 0x8b, 0x34,
|
||||
0x1f, 0xeb, 0x5e, 0xe2, 0x8f, 0xca, 0xcd, 0xfe, 0xf8, 0x5b, 0x09, 0x9a, 0x67, 0x4c, 0xc4, 0x21,
|
||||
0x9e, 0xe5, 0x2e, 0x34, 0x67, 0x3c, 0xb8, 0x64, 0x3c, 0x3b, 0x4a, 0x43, 0x09, 0x8e, 0x1c, 0xf2,
|
||||
0x18, 0x6a, 0x07, 0x81, 0x7f, 0xee, 0xce, 0xf1, 0x61, 0xab, 0x89, 0x21, 0x1d, 0x3b, 0x56, 0x3a,
|
||||
0x45, 0x0c, 0xda, 0x90, 0x0c, 0xa1, 0xa5, 0x3f, 0x13, 0xbc, 0x78, 0x71, 0xf4, 0x2c, 0xa9, 0x78,
|
||||
0x73, 0xa2, 0xc1, 0xc7, 0xd0, 0xca, 0x0d, 0xfc, 0x41, 0xa9, 0xea, 0xff, 0x01, 0x70, 0x75, 0xe5,
|
||||
0xa3, 0x6d, 0x75, 0x54, 0x3d, 0x52, 0x1e, 0xed, 0x3e, 0x34, 0x65, 0x71, 0xa5, 0xd4, 0x49, 0x92,
|
||||
0x2c, 0x65, 0x49, 0xd2, 0x7c, 0x00, 0xfd, 0x23, 0xff, 0x8a, 0x7a, 0xae, 0x43, 0x05, 0xfb, 0x92,
|
||||
0x2d, 0xd1, 0x05, 0x6b, 0x3b, 0x30, 0xcf, 0xa0, 0xad, 0x5f, 0xda, 0xaf, 0xb5, 0xc7, 0xb6, 0xde,
|
||||
0xe3, 0xf7, 0x07, 0xd1, 0xbb, 0xd0, 0xd3, 0x93, 0x1e, 0xbb, 0x3a, 0x84, 0x64, 0x8d, 0xc1, 0xd9,
|
||||
0xb9, 0x7b, 0xad, 0xa7, 0xd6, 0x3d, 0xf3, 0x29, 0x6c, 0xe7, 0x4c, 0xd3, 0xe3, 0x5c, 0xb2, 0x65,
|
||||
0x94, 0x7c, 0x81, 0x90, 0xed, 0xc4, 0x03, 0xe5, 0xcc, 0x03, 0x26, 0x74, 0xf5, 0xc8, 0xe7, 0x4c,
|
||||
0xdc, 0x70, 0xba, 0x2f, 0xd3, 0x8d, 0x3c, 0x67, 0x7a, 0xf2, 0x87, 0x50, 0x65, 0xf2, 0xa4, 0xf9,
|
||||
0xfc, 0x99, 0xf7, 0x80, 0xa5, 0xd4, 0x1b, 0x16, 0x7c, 0x9a, 0x2e, 0x78, 0x1a, 0xab, 0x05, 0x5f,
|
||||
0x73, 0x2e, 0xf3, 0xed, 0x74, 0x1b, 0xa7, 0xb1, 0xb8, 0xe9, 0x46, 0x1f, 0x40, 0x5f, 0x1b, 0x3d,
|
||||
0x63, 0x1e, 0x13, 0xec, 0x86, 0x23, 0x3d, 0x04, 0x52, 0x30, 0xbb, 0x69, 0xba, 0x7b, 0xd0, 0x98,
|
||||
0x4c, 0x8e, 0x53, 0x6d, 0x91, 0x1b, 0xcd, 0x4f, 0xa0, 0x7f, 0x16, 0x3b, 0xc1, 0x29, 0x77, 0xaf,
|
||||
0x5c, 0x8f, 0xcd, 0xd5, 0x62, 0x49, 0xf1, 0x5b, 0xca, 0x15, 0xbf, 0x1b, 0xb3, 0x91, 0x39, 0x02,
|
||||
0x52, 0x18, 0x9e, 0xde, 0x5b, 0x14, 0x3b, 0x81, 0x0e, 0x61, 0x6c, 0x9b, 0x23, 0x68, 0x4f, 0xa8,
|
||||
0x2c, 0x36, 0x1c, 0x65, 0x63, 0x40, 0x5d, 0xa8, 0xbe, 0x36, 0x4b, 0xba, 0xe6, 0x1e, 0xec, 0x1c,
|
||||
0x50, 0xfb, 0xc2, 0xf5, 0xe7, 0xcf, 0xdc, 0x48, 0x56, 0x5b, 0x7a, 0xc4, 0x00, 0x1a, 0x8e, 0x16,
|
||||
0xe8, 0x21, 0x69, 0xdf, 0x7c, 0x1f, 0xde, 0xc8, 0x7d, 0xe6, 0x39, 0x13, 0x34, 0xf1, 0xc7, 0x0e,
|
||||
0x54, 0x23, 0xd9, 0xc3, 0x11, 0x55, 0x4b, 0x75, 0xcc, 0xaf, 0x60, 0x27, 0x9f, 0x80, 0x65, 0xed,
|
||||
0x93, 0x1c, 0x1c, 0xab, 0x92, 0x52, 0xae, 0x2a, 0xd1, 0x3e, 0x2b, 0x67, 0xf9, 0x64, 0x1b, 0x2a,
|
||||
0xbf, 0xfe, 0x66, 0xa2, 0xc1, 0x2e, 0x9b, 0xe6, 0x1f, 0xe5, 0xf2, 0xc5, 0xf9, 0xd4, 0xf2, 0x85,
|
||||
0xd2, 0xa4, 0xf4, 0x5a, 0xa5, 0xc9, 0x3a, 0xde, 0xde, 0x87, 0xfe, 0x89, 0x17, 0xd8, 0x97, 0x87,
|
||||
0x7e, 0xce, 0x1b, 0x06, 0xd4, 0x99, 0x9f, 0x77, 0x46, 0xd2, 0x35, 0xdf, 0x81, 0xde, 0x71, 0x60,
|
||||
0x53, 0xef, 0x24, 0x88, 0x7d, 0x91, 0x7a, 0x01, 0xbf, 0xbb, 0x69, 0x53, 0xd5, 0x31, 0xdf, 0x87,
|
||||
0xae, 0x4e, 0xd1, 0xfe, 0x79, 0x90, 0x30, 0x63, 0x96, 0xcc, 0x4b, 0xc5, 0x42, 0xdf, 0x3c, 0x86,
|
||||
0x5e, 0x66, 0xae, 0xe6, 0x7d, 0x07, 0x6a, 0x4a, 0xad, 0xcf, 0xd6, 0x4b, 0x5f, 0xaf, 0xca, 0xd2,
|
||||
0xd2, 0xea, 0x0d, 0x87, 0x5a, 0x40, 0xf7, 0x14, 0xbf, 0x7f, 0x1e, 0xfa, 0x57, 0x6a, 0xb2, 0x23,
|
||||
0x20, 0xea, 0x8b, 0xe8, 0x94, 0xf9, 0x57, 0x2e, 0x0f, 0x7c, 0x2c, 0xae, 0x4b, 0xba, 0x84, 0x49,
|
||||
0x26, 0x4e, 0x07, 0x25, 0x16, 0x56, 0x3f, 0x5c, 0x15, 0x6d, 0xf4, 0x21, 0x64, 0x5f, 0x57, 0x64,
|
||||
0xaa, 0xe1, 0x6c, 0x11, 0x08, 0x36, 0xa5, 0x8e, 0x93, 0x44, 0x0b, 0x28, 0xd1, 0xbe, 0xe3, 0xf0,
|
||||
0xbd, 0xff, 0x94, 0xa1, 0xfe, 0x99, 0x22, 0x70, 0xf2, 0x29, 0x74, 0x0a, 0xe9, 0x9a, 0xbc, 0x81,
|
||||
0x65, 0xdd, 0x6a, 0x71, 0x30, 0xb8, 0xbd, 0x26, 0x56, 0xe7, 0xfa, 0x00, 0xda, 0xf9, 0x64, 0x4c,
|
||||
0x30, 0xf1, 0xe2, 0xb7, 0xde, 0x01, 0xce, 0xb4, 0x9e, 0xa9, 0xcf, 0x60, 0x67, 0x53, 0x9a, 0x24,
|
||||
0xf7, 0xb2, 0x15, 0xd6, 0x53, 0xf4, 0xe0, 0xcd, 0x9b, 0xb4, 0x49, 0x7a, 0xad, 0x1f, 0x78, 0x8c,
|
||||
0xfa, 0x71, 0x98, 0xdf, 0x41, 0xd6, 0x24, 0x8f, 0xa1, 0x53, 0x48, 0x14, 0xea, 0x9c, 0x6b, 0xb9,
|
||||
0x23, 0x3f, 0xe4, 0x21, 0x54, 0x31, 0x39, 0x91, 0x4e, 0x21, 0x4b, 0x0e, 0xba, 0x69, 0x57, 0xad,
|
||||
0x3d, 0x84, 0x2d, 0xfc, 0x02, 0x98, 0x5b, 0x18, 0x47, 0xa4, 0x99, 0x6b, 0xef, 0xdf, 0x25, 0xa8,
|
||||
0x27, 0x5f, 0x85, 0x1f, 0xc3, 0x96, 0xcc, 0x01, 0xe4, 0x56, 0x8e, 0x46, 0x93, 0xfc, 0x31, 0xd8,
|
||||
0x59, 0x11, 0xaa, 0x05, 0xc6, 0x50, 0x79, 0xce, 0x04, 0x21, 0x39, 0xa5, 0x4e, 0x06, 0x83, 0x5b,
|
||||
0x45, 0x59, 0x6a, 0x7f, 0x1a, 0x17, 0xed, 0x35, 0x97, 0x17, 0xec, 0x53, 0x96, 0xfe, 0x08, 0x6a,
|
||||
0x8a, 0x65, 0x95, 0x53, 0xd6, 0xf8, 0x59, 0x5d, 0xfe, 0x3a, 0x1f, 0xef, 0xfd, 0x73, 0x0b, 0xe0,
|
||||
0x6c, 0x19, 0x09, 0xb6, 0xf8, 0x8d, 0xcb, 0x5e, 0x92, 0x47, 0xd0, 0x7b, 0xc6, 0xce, 0x69, 0xec,
|
||||
0x09, 0x7c, 0xaa, 0x49, 0x36, 0xc9, 0xf9, 0x04, 0x0b, 0xbe, 0x94, 0xac, 0x1f, 0x42, 0xeb, 0x84,
|
||||
0x5e, 0xbf, 0xda, 0xee, 0x53, 0xe8, 0x14, 0x38, 0x58, 0x6f, 0x71, 0x95, 0xd5, 0xf5, 0x16, 0xd7,
|
||||
0xd9, 0xfa, 0x21, 0xd4, 0x35, 0x33, 0xe7, 0xd7, 0xc0, 0x1c, 0x56, 0x60, 0xec, 0x9f, 0x43, 0x6f,
|
||||
0x85, 0x97, 0xf3, 0xf6, 0xf8, 0x39, 0x64, 0x23, 0x6f, 0x3f, 0x95, 0xaf, 0x9d, 0x22, 0x37, 0xe7,
|
||||
0x07, 0xea, 0x97, 0xd7, 0x26, 0xf2, 0x7e, 0x5e, 0x7c, 0x27, 0xe1, 0x13, 0xd5, 0x58, 0xa5, 0xcf,
|
||||
0x84, 0xbc, 0x07, 0x77, 0x36, 0x69, 0xd2, 0x10, 0xcc, 0x33, 0xe8, 0x5a, 0x08, 0xae, 0xd3, 0xeb,
|
||||
0x7b, 0x00, 0x19, 0x89, 0xe6, 0xed, 0x11, 0x1e, 0xab, 0xfc, 0xfa, 0x21, 0x40, 0x46, 0x8d, 0x0a,
|
||||
0x55, 0x45, 0x66, 0x55, 0xc3, 0x56, 0xe9, 0xf3, 0x11, 0x34, 0x53, 0x3a, 0xcb, 0xaf, 0x81, 0x13,
|
||||
0x14, 0xd9, 0xf1, 0xb3, 0x47, 0xbf, 0x1f, 0xcd, 0x5d, 0x71, 0x11, 0xcf, 0xc6, 0x76, 0xb0, 0xd8,
|
||||
0xbd, 0xa0, 0xd1, 0x85, 0x6b, 0x07, 0x3c, 0xdc, 0xbd, 0x92, 0x60, 0xda, 0x2d, 0xfc, 0xb4, 0x9a,
|
||||
0xd5, 0xf0, 0xa1, 0xf7, 0xe4, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x5b, 0x0c, 0x01, 0xf3, 0xcc,
|
||||
0x1a, 0x00, 0x00,
|
||||
0x0c, 0x33, 0x36, 0x68, 0xd1, 0x71, 0x2c, 0x27, 0x65, 0xa7, 0x68, 0x8a, 0x96, 0x19, 0x93, 0x36,
|
||||
0x6b, 0x09, 0xc7, 0x39, 0x55, 0xc1, 0x83, 0xdd, 0x21, 0xb8, 0xc5, 0xc5, 0xee, 0x66, 0x76, 0x96,
|
||||
0x22, 0xae, 0xf2, 0x16, 0x79, 0x8d, 0xdc, 0xe6, 0x2e, 0x77, 0x29, 0x57, 0xee, 0xf3, 0x0a, 0xb9,
|
||||
0xcc, 0x33, 0xa4, 0xa6, 0x67, 0xf6, 0x04, 0x80, 0x96, 0x5c, 0xe5, 0xdc, 0xcd, 0x74, 0xf7, 0x9c,
|
||||
0x7a, 0xbe, 0xfe, 0xba, 0x67, 0x17, 0xee, 0x47, 0xce, 0xd5, 0x5e, 0xe8, 0xc5, 0x73, 0xd7, 0xdf,
|
||||
0x0b, 0x67, 0x7b, 0x33, 0x6a, 0x5f, 0x31, 0xdf, 0x19, 0x87, 0x3c, 0x10, 0x01, 0x29, 0x87, 0xb3,
|
||||
0xc1, 0xc3, 0x79, 0x10, 0xcc, 0x3d, 0xb6, 0x87, 0x92, 0x59, 0x7c, 0xb1, 0x27, 0xdc, 0x05, 0x8b,
|
||||
0x04, 0x5d, 0x84, 0xca, 0x68, 0x30, 0x90, 0x33, 0x78, 0xc1, 0xdc, 0xb5, 0xa9, 0xb7, 0xe7, 0x3a,
|
||||
0xcc, 0x17, 0xae, 0x58, 0x6a, 0x9d, 0x91, 0xd7, 0xa9, 0x55, 0x94, 0xc6, 0xac, 0x43, 0xf5, 0x68,
|
||||
0x11, 0x8a, 0xa5, 0x39, 0x84, 0xda, 0xe7, 0x8c, 0x3a, 0x8c, 0x93, 0xbb, 0x50, 0xbb, 0xc4, 0x96,
|
||||
0x51, 0x1a, 0x56, 0x46, 0x4d, 0x4b, 0xf7, 0xcc, 0x3f, 0x00, 0x9c, 0xc9, 0x31, 0x47, 0x9c, 0x07,
|
||||
0x9c, 0xdc, 0x83, 0x06, 0xe3, 0x7c, 0x2a, 0x96, 0x21, 0x33, 0x4a, 0xc3, 0xd2, 0xa8, 0x63, 0xd5,
|
||||
0x19, 0xe7, 0x93, 0x65, 0xc8, 0xc8, 0xff, 0x81, 0x6c, 0x4e, 0x17, 0xd1, 0xdc, 0x28, 0x0f, 0x4b,
|
||||
0x72, 0x06, 0xc6, 0xf9, 0x69, 0x34, 0x4f, 0xc6, 0xd8, 0x81, 0xc3, 0x8c, 0xca, 0xb0, 0x34, 0xaa,
|
||||
0xe0, 0x98, 0xc3, 0xc0, 0x61, 0xe6, 0x5f, 0x4a, 0x50, 0x3d, 0xa3, 0xe2, 0x32, 0x22, 0x04, 0xb6,
|
||||
0x78, 0x10, 0x08, 0xbd, 0x38, 0xb6, 0xc9, 0x08, 0x7a, 0xb1, 0x4f, 0x63, 0x71, 0x29, 0x4f, 0x65,
|
||||
0x53, 0xc1, 0x1c, 0xa3, 0x8c, 0xea, 0x55, 0x31, 0x79, 0x13, 0x3a, 0x5e, 0x60, 0x53, 0x6f, 0x1a,
|
||||
0x89, 0x80, 0xd3, 0xb9, 0x5c, 0x47, 0xda, 0xb5, 0x51, 0x78, 0xae, 0x64, 0x64, 0x17, 0xfa, 0x11,
|
||||
0xa3, 0xde, 0xf4, 0x05, 0xa7, 0x61, 0x6a, 0xb8, 0xa5, 0x26, 0x94, 0x8a, 0x6f, 0x38, 0x0d, 0xb5,
|
||||
0xad, 0xf9, 0xf7, 0x1a, 0xd4, 0x2d, 0xf6, 0xa7, 0x98, 0x45, 0x82, 0x74, 0xa1, 0xec, 0x3a, 0x78,
|
||||
0xda, 0xa6, 0x55, 0x76, 0x1d, 0x32, 0x06, 0x62, 0xb1, 0xd0, 0x93, 0x4b, 0xbb, 0x81, 0x7f, 0xe8,
|
||||
0xc5, 0x91, 0x60, 0x5c, 0x9f, 0x79, 0x83, 0x86, 0x3c, 0x80, 0x66, 0x10, 0x32, 0x8e, 0x32, 0x74,
|
||||
0x40, 0xd3, 0xca, 0x04, 0xf2, 0xe0, 0x21, 0x15, 0x97, 0xc6, 0x16, 0x2a, 0xb0, 0x2d, 0x65, 0x0e,
|
||||
0x15, 0xd4, 0xa8, 0x2a, 0x99, 0x6c, 0x13, 0x13, 0x6a, 0x11, 0xb3, 0x39, 0x13, 0x46, 0x6d, 0x58,
|
||||
0x1a, 0xb5, 0xf6, 0x61, 0x1c, 0xce, 0xc6, 0xe7, 0x28, 0xb1, 0xb4, 0x86, 0x3c, 0x80, 0x2d, 0xe9,
|
||||
0x17, 0xa3, 0x8e, 0x16, 0x0d, 0x69, 0x71, 0x10, 0x8b, 0x4b, 0x0b, 0xa5, 0x64, 0x1f, 0xea, 0xea,
|
||||
0x4e, 0x23, 0xa3, 0x31, 0xac, 0x8c, 0x5a, 0xfb, 0x86, 0x34, 0xd0, 0xa7, 0x1c, 0x2b, 0x18, 0x44,
|
||||
0x47, 0xbe, 0xe0, 0x4b, 0x2b, 0x31, 0x24, 0x6f, 0x40, 0xdb, 0xf6, 0x5c, 0xe6, 0x8b, 0xa9, 0x08,
|
||||
0xae, 0x98, 0x6f, 0x34, 0x71, 0x47, 0x2d, 0x25, 0x9b, 0x48, 0x11, 0xd9, 0x87, 0xd7, 0xf2, 0x26,
|
||||
0x53, 0x6a, 0xdb, 0x2c, 0x8a, 0x02, 0x6e, 0x00, 0xda, 0xde, 0xc9, 0xd9, 0x1e, 0x68, 0x95, 0x9c,
|
||||
0xd6, 0x71, 0xa3, 0xd0, 0xa3, 0xcb, 0xa9, 0x4f, 0x17, 0xcc, 0x68, 0xa9, 0x69, 0xb5, 0xec, 0x4b,
|
||||
0xba, 0x60, 0xe4, 0x21, 0xb4, 0x16, 0x41, 0xec, 0x8b, 0x69, 0x18, 0xb8, 0xbe, 0x30, 0xda, 0x68,
|
||||
0x01, 0x28, 0x3a, 0x93, 0x12, 0xf2, 0x3a, 0xa8, 0x9e, 0x02, 0x63, 0x47, 0xf9, 0x15, 0x25, 0x08,
|
||||
0xc7, 0x47, 0xd0, 0x55, 0xea, 0x74, 0x3f, 0x5d, 0x34, 0xe9, 0xa0, 0x34, 0xdd, 0xc9, 0x7b, 0xd0,
|
||||
0x44, 0x3c, 0xb8, 0xfe, 0x45, 0x60, 0xf4, 0xd0, 0x6f, 0x77, 0x72, 0x6e, 0x91, 0x98, 0x38, 0xf6,
|
||||
0x2f, 0x02, 0xab, 0xf1, 0x42, 0xb7, 0xc8, 0xc7, 0x70, 0xbf, 0x70, 0x5e, 0xce, 0x16, 0xd4, 0xf5,
|
||||
0x5d, 0x7f, 0x3e, 0x8d, 0x23, 0x16, 0x19, 0xdb, 0x88, 0x70, 0x23, 0x77, 0x6a, 0x2b, 0x31, 0xf8,
|
||||
0x3a, 0x62, 0x11, 0xb9, 0x0f, 0x4d, 0x15, 0xa4, 0x53, 0xd7, 0x31, 0xfa, 0xb8, 0xa5, 0x86, 0x12,
|
||||
0x1c, 0x3b, 0xe4, 0x2d, 0xe8, 0x85, 0x81, 0xe7, 0xda, 0xcb, 0x69, 0x70, 0xcd, 0x38, 0x77, 0x1d,
|
||||
0x66, 0x90, 0x61, 0x69, 0xd4, 0xb0, 0xba, 0x4a, 0xfc, 0x95, 0x96, 0x6e, 0x0a, 0x8d, 0x3b, 0x68,
|
||||
0xb8, 0x16, 0x1a, 0x63, 0x00, 0x3b, 0xf0, 0x7d, 0x66, 0x23, 0xfc, 0x76, 0xf0, 0x84, 0x5d, 0x79,
|
||||
0xc2, 0xc3, 0x54, 0x6a, 0xe5, 0x2c, 0x06, 0x9f, 0x41, 0x3b, 0x0f, 0x05, 0xb2, 0x0d, 0x95, 0x2b,
|
||||
0xb6, 0xd4, 0xf0, 0x97, 0x4d, 0x32, 0x84, 0xea, 0x35, 0xf5, 0x62, 0x86, 0x90, 0xd7, 0x40, 0x54,
|
||||
0x43, 0x2c, 0xa5, 0xf8, 0x45, 0xf9, 0x69, 0xc9, 0xfc, 0x77, 0x15, 0xb6, 0x24, 0xf8, 0xc8, 0x07,
|
||||
0xd0, 0xf1, 0x18, 0x8d, 0xd8, 0x34, 0x08, 0xe5, 0x02, 0x11, 0x4e, 0xd5, 0xda, 0xdf, 0x96, 0xc3,
|
||||
0x4e, 0xa4, 0xe2, 0x2b, 0x25, 0xb7, 0xda, 0x5e, 0xae, 0x27, 0x43, 0xda, 0xf5, 0x05, 0xe3, 0x3e,
|
||||
0xf5, 0xa6, 0x18, 0x0c, 0x2a, 0xc0, 0xda, 0x89, 0xf0, 0x99, 0x0c, 0x8a, 0x55, 0x1c, 0x55, 0xd6,
|
||||
0x71, 0x34, 0x80, 0x06, 0xfa, 0xce, 0x65, 0x91, 0x0e, 0xf6, 0xb4, 0x4f, 0xf6, 0xa1, 0xb1, 0x60,
|
||||
0x82, 0xea, 0x58, 0x93, 0x21, 0x71, 0x37, 0x89, 0x99, 0xf1, 0xa9, 0x56, 0xa8, 0x80, 0x48, 0xed,
|
||||
0xd6, 0x22, 0xa2, 0xb6, 0x1e, 0x11, 0x03, 0x68, 0xa4, 0xa0, 0xab, 0xab, 0x1b, 0x4e, 0xfa, 0x92,
|
||||
0x66, 0x43, 0xc6, 0xdd, 0xc0, 0x31, 0x1a, 0x08, 0x14, 0xdd, 0x93, 0x24, 0xe9, 0xc7, 0x0b, 0x05,
|
||||
0xa1, 0xa6, 0x22, 0x49, 0x3f, 0x5e, 0xac, 0x23, 0x06, 0x56, 0x10, 0xf3, 0x13, 0xa8, 0x52, 0xcf,
|
||||
0xa5, 0x11, 0x86, 0x90, 0xbc, 0x59, 0xcd, 0xf7, 0xe3, 0x03, 0x29, 0xb5, 0x94, 0x92, 0xbc, 0x0f,
|
||||
0x9d, 0x39, 0x0f, 0xe2, 0x70, 0x8a, 0x5d, 0x16, 0x19, 0x6d, 0x3c, 0xed, 0xaa, 0x75, 0x1b, 0x8d,
|
||||
0x0e, 0x94, 0x8d, 0x8c, 0xc0, 0x59, 0x10, 0xfb, 0xce, 0xd4, 0x76, 0x1d, 0x1e, 0x19, 0x1d, 0x74,
|
||||
0x1e, 0xa0, 0xe8, 0x50, 0x4a, 0x64, 0x88, 0xa9, 0x10, 0x48, 0x1d, 0xdc, 0x45, 0x9b, 0x0e, 0x4a,
|
||||
0xcf, 0x12, 0x2f, 0xff, 0x14, 0xfa, 0x49, 0x62, 0xca, 0x2c, 0x7b, 0x68, 0xb9, 0x9d, 0x28, 0x52,
|
||||
0xe3, 0x11, 0x6c, 0xb3, 0x1b, 0x49, 0xa1, 0xae, 0x98, 0x2e, 0xe8, 0xcd, 0x54, 0x08, 0x4f, 0x87,
|
||||
0x54, 0x37, 0x91, 0x9f, 0xd2, 0x9b, 0x89, 0xf0, 0x64, 0xfc, 0xab, 0xd5, 0x31, 0xfe, 0xfb, 0x98,
|
||||
0x8c, 0x9a, 0x28, 0xc1, 0xf8, 0xdf, 0x85, 0xbe, 0x1f, 0x4c, 0x1d, 0x76, 0x41, 0x63, 0x4f, 0xa8,
|
||||
0x75, 0x97, 0x3a, 0x98, 0x7a, 0x7e, 0xf0, 0x4c, 0xc9, 0x71, 0xd9, 0xe5, 0xe0, 0x97, 0xd0, 0x29,
|
||||
0x5c, 0xf7, 0x06, 0xd0, 0xef, 0xe4, 0x41, 0xdf, 0xcc, 0x03, 0xfd, 0x9f, 0x5b, 0x00, 0x78, 0xef,
|
||||
0x6a, 0xe8, 0x6a, 0xb6, 0xc8, 0x83, 0xa1, 0xbc, 0x01, 0x0c, 0x94, 0x33, 0x5f, 0x68, 0xe0, 0xea,
|
||||
0xde, 0xf7, 0x62, 0x36, 0xc9, 0x17, 0xd5, 0x5c, 0xbe, 0x78, 0x07, 0xb6, 0x24, 0x3e, 0x8d, 0x5a,
|
||||
0x46, 0xeb, 0xd9, 0x8e, 0x10, 0xc9, 0x0a, 0xc5, 0x68, 0xb5, 0x16, 0x34, 0xf5, 0xf5, 0xa0, 0xc9,
|
||||
0xa3, 0xb1, 0x51, 0x44, 0xe3, 0x9b, 0xd0, 0xb1, 0x39, 0xc3, 0xdc, 0x35, 0x95, 0xc5, 0x88, 0x46,
|
||||
0x6b, 0x3b, 0x11, 0x4e, 0xdc, 0x05, 0x93, 0xfe, 0x93, 0x17, 0x07, 0xa8, 0x92, 0xcd, 0x8d, 0xf7,
|
||||
0xda, 0xda, 0x78, 0xaf, 0x58, 0x09, 0x78, 0x4c, 0x33, 0x3e, 0xb6, 0x73, 0x51, 0xd3, 0x29, 0x44,
|
||||
0x4d, 0x21, 0x34, 0xba, 0x2b, 0xa1, 0xb1, 0x82, 0xdf, 0xde, 0x1a, 0x7e, 0xdf, 0x80, 0xb6, 0x74,
|
||||
0x40, 0x14, 0x52, 0x9b, 0xc9, 0x09, 0xb6, 0x95, 0x23, 0x52, 0xd9, 0xb1, 0x83, 0xd1, 0x1e, 0xcf,
|
||||
0x66, 0xcb, 0xcb, 0xc0, 0x63, 0x19, 0x61, 0xb7, 0x52, 0xd9, 0xb1, 0x23, 0xf7, 0x8b, 0x08, 0x24,
|
||||
0x88, 0x40, 0x6c, 0x0f, 0x3e, 0x84, 0x66, 0xea, 0xf5, 0x1f, 0x04, 0xa6, 0xbf, 0x96, 0xa0, 0x9d,
|
||||
0x27, 0x45, 0x39, 0x78, 0x32, 0x39, 0xc1, 0xc1, 0x15, 0x4b, 0x36, 0x65, 0x39, 0xc1, 0x99, 0xcf,
|
||||
0x5e, 0xd0, 0x99, 0xa7, 0x26, 0x68, 0x58, 0x99, 0x40, 0x6a, 0x5d, 0xdf, 0xe6, 0x6c, 0x91, 0xa0,
|
||||
0xaa, 0x62, 0x65, 0x02, 0xf2, 0x11, 0x80, 0x1b, 0x45, 0x31, 0x53, 0x37, 0xb7, 0x85, 0x94, 0x31,
|
||||
0x18, 0xab, 0x1a, 0x73, 0x9c, 0xd4, 0x98, 0xe3, 0x49, 0x52, 0x63, 0x5a, 0x4d, 0xb4, 0xc6, 0x2b,
|
||||
0xbd, 0x0b, 0x35, 0x79, 0x41, 0x93, 0x13, 0x44, 0x5e, 0xc5, 0xd2, 0x3d, 0xf3, 0xcf, 0x50, 0x53,
|
||||
0x55, 0xc8, 0xff, 0x94, 0xe8, 0xef, 0x41, 0x43, 0xcd, 0xed, 0x3a, 0x3a, 0x56, 0xea, 0xd8, 0x3f,
|
||||
0x76, 0xcc, 0xef, 0xca, 0xd0, 0xb0, 0x58, 0x14, 0x06, 0x7e, 0xc4, 0x72, 0x55, 0x52, 0xe9, 0xa5,
|
||||
0x55, 0x52, 0x79, 0x63, 0x95, 0x94, 0xd4, 0x5e, 0x95, 0x5c, 0xed, 0x35, 0x80, 0x06, 0x67, 0x8e,
|
||||
0xcb, 0x99, 0x2d, 0x74, 0x9d, 0x96, 0xf6, 0xa5, 0xee, 0x05, 0xe5, 0x32, 0xbd, 0x47, 0x98, 0x43,
|
||||
0x9a, 0x56, 0xda, 0x27, 0x4f, 0xf2, 0xc5, 0x85, 0x2a, 0xdb, 0x76, 0x54, 0x71, 0xa1, 0xb6, 0xbb,
|
||||
0xa1, 0xba, 0x78, 0x3f, 0x2b, 0xd2, 0xea, 0x18, 0xcd, 0xf7, 0xf2, 0x03, 0x36, 0x57, 0x69, 0x3f,
|
||||
0x5a, 0xce, 0xfe, 0xae, 0x0c, 0xdb, 0xab, 0x7b, 0xdb, 0x80, 0xc0, 0x1d, 0xa8, 0xaa, 0xdc, 0xa7,
|
||||
0xe1, 0x2b, 0xd6, 0xb2, 0x5e, 0x65, 0x85, 0xe8, 0x7e, 0xb5, 0x4a, 0x1a, 0x2f, 0x87, 0x5e, 0x91,
|
||||
0x50, 0xde, 0x86, 0x6d, 0xe9, 0xa2, 0x90, 0x39, 0x59, 0x3d, 0xa7, 0x18, 0xb0, 0xa7, 0xe5, 0x69,
|
||||
0x45, 0xb7, 0x0b, 0xfd, 0xc4, 0x34, 0xe3, 0x86, 0x5a, 0xc1, 0xf6, 0x28, 0xa1, 0x88, 0xbb, 0x50,
|
||||
0xbb, 0x08, 0xf8, 0x82, 0x0a, 0x4d, 0x82, 0xba, 0x57, 0x20, 0x39, 0x64, 0xdb, 0x86, 0xc2, 0x64,
|
||||
0x22, 0x94, 0x6f, 0x16, 0x49, 0x3e, 0xe9, 0x7b, 0x02, 0x59, 0xb0, 0x61, 0x35, 0x92, 0x77, 0x84,
|
||||
0xf9, 0x5b, 0xe8, 0xad, 0x94, 0x90, 0x1b, 0x1c, 0x99, 0x2d, 0x5f, 0x2e, 0x2c, 0x5f, 0x98, 0xb9,
|
||||
0xb2, 0x32, 0xf3, 0xef, 0xa0, 0xff, 0x39, 0xf5, 0x1d, 0x8f, 0xe9, 0xf9, 0x0f, 0xf8, 0x3c, 0x92,
|
||||
0xc9, 0x50, 0xbf, 0x68, 0xa6, 0x3a, 0xfb, 0x74, 0xac, 0xa6, 0x96, 0x1c, 0x3b, 0xe4, 0x11, 0xd4,
|
||||
0xb9, 0xb2, 0xd6, 0x00, 0x68, 0xe5, 0x6a, 0x5c, 0x2b, 0xd1, 0x99, 0xdf, 0x02, 0x29, 0x4c, 0x2d,
|
||||
0x1f, 0x33, 0x4b, 0x32, 0x92, 0xe8, 0x57, 0xa0, 0xd0, 0x51, 0xd5, 0xce, 0x63, 0xd2, 0x4a, 0xb5,
|
||||
0x64, 0x08, 0x15, 0xc6, 0xb9, 0x5e, 0x02, 0x8b, 0xcc, 0xec, 0xe9, 0x68, 0x49, 0x95, 0xf9, 0x33,
|
||||
0xe8, 0x9f, 0x87, 0xcc, 0x76, 0xa9, 0x87, 0xcf, 0x3e, 0xb5, 0xc0, 0x43, 0xa8, 0x4a, 0x27, 0x27,
|
||||
0x84, 0xd1, 0xc4, 0x81, 0xa8, 0x56, 0x72, 0xf3, 0x5b, 0x30, 0xd4, 0xbe, 0x8e, 0x6e, 0xdc, 0x48,
|
||||
0x30, 0xdf, 0x66, 0x87, 0x97, 0xcc, 0xbe, 0xfa, 0x11, 0x4f, 0x7e, 0x0d, 0xf7, 0x36, 0xad, 0x90,
|
||||
0xec, 0xaf, 0x65, 0xcb, 0xde, 0xf4, 0x42, 0xe6, 0x0e, 0x5c, 0xa3, 0x61, 0x01, 0x8a, 0x3e, 0x93,
|
||||
0x12, 0x79, 0x8f, 0x4c, 0x8e, 0x8b, 0x34, 0x1f, 0xeb, 0x5e, 0xe2, 0x8f, 0xca, 0xed, 0xfe, 0xf8,
|
||||
0x5b, 0x09, 0x9a, 0xe7, 0x4c, 0xc4, 0x21, 0x9e, 0xe5, 0x3e, 0x34, 0x67, 0x3c, 0xb8, 0x62, 0x3c,
|
||||
0x3b, 0x4a, 0x43, 0x09, 0x8e, 0x1d, 0xf2, 0x04, 0x6a, 0x87, 0x81, 0x7f, 0xe1, 0xce, 0xf1, 0x11,
|
||||
0xac, 0x89, 0x21, 0x1d, 0x3b, 0x56, 0x3a, 0x45, 0x0c, 0xda, 0x90, 0x0c, 0xa1, 0xa5, 0x3f, 0x29,
|
||||
0x7c, 0xfd, 0xf5, 0xf1, 0xb3, 0xa4, 0x3a, 0xce, 0x89, 0x06, 0x1f, 0x41, 0x2b, 0x37, 0xf0, 0x07,
|
||||
0xa5, 0xaa, 0xff, 0x07, 0xc0, 0xd5, 0x95, 0x8f, 0xb6, 0xd5, 0x51, 0xf5, 0x48, 0x79, 0xb4, 0x87,
|
||||
0xd0, 0x94, 0x85, 0x98, 0x52, 0x27, 0x49, 0xb2, 0x94, 0x25, 0x49, 0xf3, 0x11, 0xf4, 0x8f, 0xfd,
|
||||
0x6b, 0xea, 0xb9, 0x0e, 0x15, 0xec, 0x0b, 0xb6, 0x44, 0x17, 0xac, 0xed, 0xc0, 0x3c, 0x87, 0xb6,
|
||||
0x7e, 0x95, 0xbf, 0xd2, 0x1e, 0xdb, 0x7a, 0x8f, 0xdf, 0x1f, 0x44, 0x6f, 0x43, 0x4f, 0x4f, 0x7a,
|
||||
0xe2, 0xea, 0x10, 0x92, 0x35, 0x06, 0x67, 0x17, 0xee, 0x8d, 0x9e, 0x5a, 0xf7, 0xcc, 0xa7, 0xb0,
|
||||
0x9d, 0x33, 0x4d, 0x8f, 0x73, 0xc5, 0x96, 0x51, 0xf2, 0xb5, 0x42, 0xb6, 0x13, 0x0f, 0x94, 0x33,
|
||||
0x0f, 0x98, 0xd0, 0xd5, 0x23, 0x9f, 0x33, 0x71, 0xcb, 0xe9, 0xbe, 0x48, 0x37, 0xf2, 0x9c, 0xe9,
|
||||
0xc9, 0x1f, 0x43, 0x95, 0xc9, 0x93, 0xe6, 0xf3, 0x67, 0xde, 0x03, 0x96, 0x52, 0x6f, 0x58, 0xf0,
|
||||
0x69, 0xba, 0xe0, 0x59, 0xac, 0x16, 0x7c, 0xc5, 0xb9, 0xcc, 0x37, 0xd3, 0x6d, 0x9c, 0xc5, 0xe2,
|
||||
0xb6, 0x1b, 0x7d, 0x04, 0x7d, 0x6d, 0xf4, 0x8c, 0x79, 0x4c, 0xb0, 0x5b, 0x8e, 0xf4, 0x18, 0x48,
|
||||
0xc1, 0xec, 0xb6, 0xe9, 0x1e, 0x40, 0x63, 0x32, 0x39, 0x49, 0xb5, 0x45, 0x6e, 0x34, 0x3f, 0x86,
|
||||
0xfe, 0x79, 0xec, 0x04, 0x67, 0xdc, 0xbd, 0x76, 0x3d, 0x36, 0x57, 0x8b, 0x25, 0xc5, 0x6f, 0x29,
|
||||
0x57, 0xfc, 0x6e, 0xcc, 0x46, 0xe6, 0x08, 0x48, 0x61, 0x78, 0x7a, 0x6f, 0x51, 0xec, 0x04, 0x3a,
|
||||
0x84, 0xb1, 0x6d, 0x8e, 0xa0, 0x3d, 0xa1, 0xb2, 0xd8, 0x70, 0x94, 0x8d, 0x01, 0x75, 0xa1, 0xfa,
|
||||
0xda, 0x2c, 0xe9, 0x9a, 0xfb, 0xb0, 0x73, 0x48, 0xed, 0x4b, 0xd7, 0x9f, 0x3f, 0x73, 0x23, 0x59,
|
||||
0x6d, 0xe9, 0x11, 0x03, 0x68, 0x38, 0x5a, 0xa0, 0x87, 0xa4, 0x7d, 0xf3, 0x5d, 0x78, 0x2d, 0xf7,
|
||||
0x49, 0xe8, 0x5c, 0xd0, 0xc4, 0x1f, 0x3b, 0x50, 0x8d, 0x64, 0x0f, 0x47, 0x54, 0x2d, 0xd5, 0x31,
|
||||
0xbf, 0x84, 0x9d, 0x7c, 0x02, 0x96, 0xb5, 0x4f, 0x72, 0x70, 0xac, 0x4a, 0x4a, 0xb9, 0xaa, 0x44,
|
||||
0xfb, 0xac, 0x9c, 0xe5, 0x93, 0x6d, 0xa8, 0xfc, 0xfa, 0x9b, 0x89, 0x06, 0xbb, 0x6c, 0x9a, 0x7f,
|
||||
0x94, 0xcb, 0x17, 0xe7, 0x53, 0xcb, 0x17, 0x4a, 0x93, 0xd2, 0x2b, 0x95, 0x26, 0xeb, 0x78, 0x7b,
|
||||
0x17, 0xfa, 0xa7, 0x5e, 0x60, 0x5f, 0x1d, 0xf9, 0x39, 0x6f, 0x18, 0x50, 0x67, 0x7e, 0xde, 0x19,
|
||||
0x49, 0xd7, 0x7c, 0x0b, 0x7a, 0x27, 0x81, 0x4d, 0xbd, 0xd3, 0x20, 0xf6, 0x45, 0xea, 0x05, 0xfc,
|
||||
0x46, 0xa7, 0x4d, 0x55, 0xc7, 0x7c, 0x17, 0xba, 0x3a, 0x45, 0xfb, 0x17, 0x41, 0xc2, 0x8c, 0x59,
|
||||
0x32, 0x2f, 0x15, 0x0b, 0x7d, 0xf3, 0x04, 0x7a, 0x99, 0xb9, 0x9a, 0xf7, 0x2d, 0xa8, 0x29, 0xb5,
|
||||
0x3e, 0x5b, 0x2f, 0x7d, 0xe9, 0x2a, 0x4b, 0x4b, 0xab, 0x37, 0x1c, 0x6a, 0x01, 0xdd, 0x33, 0xfc,
|
||||
0x56, 0x7a, 0xe4, 0x5f, 0xab, 0xc9, 0x8e, 0x81, 0xa8, 0xaf, 0xa7, 0x53, 0xe6, 0x5f, 0xbb, 0x3c,
|
||||
0xf0, 0xb1, 0xb8, 0x2e, 0xe9, 0x12, 0x26, 0x99, 0x38, 0x1d, 0x94, 0x58, 0x58, 0xfd, 0x70, 0x55,
|
||||
0xb4, 0xd1, 0x87, 0x90, 0x7d, 0x89, 0x91, 0xa9, 0x86, 0xb3, 0x45, 0x20, 0xd8, 0x94, 0x3a, 0x4e,
|
||||
0x12, 0x2d, 0xa0, 0x44, 0x07, 0x8e, 0xc3, 0xf7, 0xff, 0x53, 0x86, 0xfa, 0xa7, 0x8a, 0xc0, 0xc9,
|
||||
0x27, 0xd0, 0x29, 0xa4, 0x6b, 0xf2, 0x1a, 0x96, 0x75, 0xab, 0xc5, 0xc1, 0xe0, 0xee, 0x9a, 0x58,
|
||||
0x9d, 0xeb, 0x3d, 0x68, 0xe7, 0x93, 0x31, 0xc1, 0xc4, 0x8b, 0xdf, 0x85, 0x07, 0x38, 0xd3, 0x7a,
|
||||
0xa6, 0x3e, 0x87, 0x9d, 0x4d, 0x69, 0x92, 0x3c, 0xc8, 0x56, 0x58, 0x4f, 0xd1, 0x83, 0xd7, 0x6f,
|
||||
0xd3, 0x26, 0xe9, 0xb5, 0x7e, 0xe8, 0x31, 0xea, 0xc7, 0x61, 0x7e, 0x07, 0x59, 0x93, 0x3c, 0x81,
|
||||
0x4e, 0x21, 0x51, 0xa8, 0x73, 0xae, 0xe5, 0x8e, 0xfc, 0x90, 0xc7, 0x50, 0xc5, 0xe4, 0x44, 0x3a,
|
||||
0x85, 0x2c, 0x39, 0xe8, 0xa6, 0x5d, 0xb5, 0xf6, 0x10, 0xb6, 0xf0, 0x6b, 0x41, 0x6e, 0x61, 0x1c,
|
||||
0x91, 0x66, 0xae, 0xfd, 0x7f, 0x95, 0xa0, 0x9e, 0x7c, 0x41, 0x7e, 0x02, 0x5b, 0x32, 0x07, 0x90,
|
||||
0x3b, 0x39, 0x1a, 0x4d, 0xf2, 0xc7, 0x60, 0x67, 0x45, 0xa8, 0x16, 0x18, 0x43, 0xe5, 0x39, 0x13,
|
||||
0x84, 0xe4, 0x94, 0x3a, 0x19, 0x0c, 0xee, 0x14, 0x65, 0xa9, 0xfd, 0x59, 0x5c, 0xb4, 0xd7, 0x5c,
|
||||
0x5e, 0xb0, 0x4f, 0x59, 0xfa, 0x43, 0xa8, 0x29, 0x96, 0x55, 0x4e, 0x59, 0xe3, 0x67, 0x75, 0xf9,
|
||||
0xeb, 0x7c, 0xbc, 0xff, 0x8f, 0x2d, 0x80, 0xf3, 0x65, 0x24, 0xd8, 0xe2, 0x37, 0x2e, 0x7b, 0x41,
|
||||
0x76, 0xa1, 0xa7, 0xbf, 0x89, 0xe0, 0x53, 0x4d, 0xb2, 0x49, 0xce, 0x27, 0x58, 0xf0, 0xa5, 0x64,
|
||||
0xfd, 0x18, 0x5a, 0xa7, 0xf4, 0xe6, 0xe5, 0x76, 0x9f, 0x40, 0xa7, 0xc0, 0xc1, 0x7a, 0x8b, 0xab,
|
||||
0xac, 0xae, 0xb7, 0xb8, 0xce, 0xd6, 0x8f, 0xa1, 0xae, 0x99, 0x39, 0xbf, 0x06, 0xe6, 0xb0, 0x02,
|
||||
0x63, 0xff, 0x1c, 0x7a, 0x2b, 0xbc, 0x9c, 0xb7, 0xc7, 0xcf, 0x21, 0x1b, 0x79, 0xfb, 0xa9, 0x7c,
|
||||
0xed, 0x14, 0xb9, 0x39, 0x3f, 0x50, 0xbf, 0xbc, 0x36, 0x91, 0xf7, 0xf3, 0xe2, 0x3b, 0x09, 0x9f,
|
||||
0xa8, 0xc6, 0x2a, 0x7d, 0x26, 0xe4, 0x3d, 0xb8, 0xb7, 0x49, 0x93, 0x86, 0x60, 0x9e, 0x41, 0xd7,
|
||||
0x42, 0x70, 0x9d, 0x5e, 0xdf, 0x01, 0xc8, 0x48, 0x34, 0x6f, 0x8f, 0xf0, 0x58, 0xe5, 0xd7, 0x0f,
|
||||
0x00, 0x32, 0x6a, 0x54, 0xa8, 0x2a, 0x32, 0xab, 0x1a, 0xb6, 0x4a, 0x9f, 0xbb, 0xd0, 0x4c, 0xe9,
|
||||
0x2c, 0xbf, 0x06, 0x4e, 0x50, 0x64, 0xc7, 0x4f, 0x77, 0x7f, 0x3f, 0x9a, 0xbb, 0xe2, 0x32, 0x9e,
|
||||
0x8d, 0xed, 0x60, 0xb1, 0x77, 0x49, 0xa3, 0x4b, 0xd7, 0x0e, 0x78, 0xb8, 0x77, 0x2d, 0xc1, 0xb4,
|
||||
0x57, 0xf8, 0xc1, 0x35, 0xab, 0xe1, 0x43, 0xef, 0xfd, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xbd,
|
||||
0xc6, 0x6e, 0xfa, 0xf8, 0x1a, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
|||
3
vendor/github.com/hashicorp/vault/sdk/plugin/pb/backend.proto
generated
vendored
3
vendor/github.com/hashicorp/vault/sdk/plugin/pb/backend.proto
generated
vendored
|
|
@ -210,6 +210,9 @@ message Auth {
|
|||
|
||||
// TokenType is the type of token being requested
|
||||
uint32 token_type = 17;
|
||||
|
||||
// Whether the default policy should be added automatically by core
|
||||
bool no_default_policy = 18;
|
||||
}
|
||||
|
||||
message TokenEntry {
|
||||
|
|
|
|||
2
vendor/github.com/hashicorp/vault/sdk/plugin/pb/translation.go
generated
vendored
2
vendor/github.com/hashicorp/vault/sdk/plugin/pb/translation.go
generated
vendored
|
|
@ -507,6 +507,7 @@ func LogicalAuthToProtoAuth(a *logical.Auth) (*Auth, error) {
|
|||
Policies: a.Policies,
|
||||
TokenPolicies: a.TokenPolicies,
|
||||
IdentityPolicies: a.IdentityPolicies,
|
||||
NoDefaultPolicy: a.NoDefaultPolicy,
|
||||
Metadata: a.Metadata,
|
||||
ClientToken: a.ClientToken,
|
||||
Accessor: a.Accessor,
|
||||
|
|
@ -554,6 +555,7 @@ func ProtoAuthToLogicalAuth(a *Auth) (*logical.Auth, error) {
|
|||
Policies: a.Policies,
|
||||
TokenPolicies: a.TokenPolicies,
|
||||
IdentityPolicies: a.IdentityPolicies,
|
||||
NoDefaultPolicy: a.NoDefaultPolicy,
|
||||
Metadata: a.Metadata,
|
||||
ClientToken: a.ClientToken,
|
||||
Accessor: a.Accessor,
|
||||
|
|
|
|||
5
vendor/modules.txt
vendored
5
vendor/modules.txt
vendored
|
|
@ -348,9 +348,9 @@ github.com/hashicorp/vault-plugin-secrets-gcp/plugin/util
|
|||
github.com/hashicorp/vault-plugin-secrets-gcpkms
|
||||
# github.com/hashicorp/vault-plugin-secrets-kv v0.5.2-0.20190416155133-fd495225dea0
|
||||
github.com/hashicorp/vault-plugin-secrets-kv
|
||||
# github.com/hashicorp/vault/api v1.0.1 => ./api
|
||||
# github.com/hashicorp/vault/api v1.0.3-0.20190614165924-47d4e5b1f688 => ./api
|
||||
github.com/hashicorp/vault/api
|
||||
# github.com/hashicorp/vault/sdk v0.1.11 => ./sdk
|
||||
# github.com/hashicorp/vault/sdk v0.1.12-0.20190614165924-47d4e5b1f688 => ./sdk
|
||||
github.com/hashicorp/vault/sdk/helper/salt
|
||||
github.com/hashicorp/vault/sdk/helper/strutil
|
||||
github.com/hashicorp/vault/sdk/helper/wrapping
|
||||
|
|
@ -388,6 +388,7 @@ github.com/hashicorp/vault/sdk/helper/pathmanager
|
|||
github.com/hashicorp/vault/sdk/database/helper/connutil
|
||||
github.com/hashicorp/vault/sdk/helper/license
|
||||
github.com/hashicorp/vault/sdk/helper/pluginutil
|
||||
github.com/hashicorp/vault/sdk/helper/tokenutil
|
||||
github.com/hashicorp/vault/sdk/plugin/pb
|
||||
github.com/hashicorp/vault/sdk/helper/kdf
|
||||
github.com/hashicorp/vault/sdk/plugin/mock
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ This endpoint creates or updates an Entity.
|
|||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"organization": "hashicorp",
|
||||
"organization": "hashicorp",
|
||||
"team": "vault"
|
||||
},
|
||||
"policies": ["eng-dev", "infra-dev"]
|
||||
|
|
@ -134,7 +134,7 @@ This endpoint is used to update an existing entity.
|
|||
{
|
||||
"name":"updatedEntityName",
|
||||
"metadata": {
|
||||
"organization": "hashi",
|
||||
"organization": "hashicorp",
|
||||
"team": "nomad"
|
||||
},
|
||||
"policies": ["eng-developers", "infra-developers"]
|
||||
|
|
@ -243,7 +243,7 @@ This endpoint is used to create or update an entity by a given name.
|
|||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"organization": "hashi",
|
||||
"organization": "hashicorp",
|
||||
"team": "nomad"
|
||||
},
|
||||
"policies": ["eng-developers", "infra-developers"]
|
||||
|
|
@ -306,7 +306,7 @@ $ curl \
|
|||
"last_update_time": "2018-09-19T17:20:27.705389973Z",
|
||||
"merged_entity_ids": null,
|
||||
"metadata": {
|
||||
"organization": "hashi",
|
||||
"organization": "hashicorp",
|
||||
"team": "nomad"
|
||||
},
|
||||
"name": "testentityname",
|
||||
|
|
|
|||
|
|
@ -146,9 +146,9 @@ This endpoint is used to update an existing group.
|
|||
```json
|
||||
{
|
||||
"name": "testgroupname",
|
||||
"metadata": {
|
||||
"hello": "everyone"
|
||||
},
|
||||
"metadata": {
|
||||
"hello": "everyone"
|
||||
},
|
||||
"policies": ["grouppolicy2", "grouppolicy3"]
|
||||
}
|
||||
```
|
||||
|
|
@ -261,9 +261,9 @@ This endpoint is used to create or update a group by its name.
|
|||
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"hello": "everyone"
|
||||
},
|
||||
"metadata": {
|
||||
"hello": "everyone"
|
||||
},
|
||||
"policies": ["grouppolicy2", "grouppolicy3"]
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ This endpoint creates or updates a group.
|
|||
|
||||
```json
|
||||
{
|
||||
"name": "engineering-group",
|
||||
"metadata": ["organization=hashicorp", "team=vault"],
|
||||
"policies": ["eng-dev", "infra-dev"]
|
||||
"name": "engineering-group",
|
||||
"metadata": ["organization=hashicorp", "team=vault"],
|
||||
"policies": ["eng-dev", "infra-dev"]
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -53,10 +53,10 @@ $ curl \
|
|||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8",
|
||||
"name": "engineering-group"
|
||||
}
|
||||
"data": {
|
||||
"id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8",
|
||||
"name": "engineering-group"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -86,8 +86,8 @@ This endpoint updates the group by its ID.
|
|||
|
||||
```json
|
||||
{
|
||||
"metadata": ["organization=updatedorg", "team=updatedteam"],
|
||||
"policies": ["updatedpolicy"]
|
||||
"metadata": ["organization=updatedorg", "team=updatedteam"],
|
||||
"policies": ["updatedpolicy"]
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -105,10 +105,10 @@ $ curl \
|
|||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8",
|
||||
"name": "engineering-group"
|
||||
}
|
||||
"data": {
|
||||
"id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8",
|
||||
"name": "engineering-group"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -136,22 +136,22 @@ $ curl \
|
|||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"creation_time": "2017-09-13T01:17:26.755474204Z",
|
||||
"id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8",
|
||||
"last_update_time": "2017-09-13T01:17:26.755474204Z",
|
||||
"member_entity_ids": [],
|
||||
"member_group_ids": null,
|
||||
"metadata": {
|
||||
"organization": "hashicorp",
|
||||
"team": "vault"
|
||||
},
|
||||
"modify_index": 1,
|
||||
"name": "engineering-group",
|
||||
"policies": [
|
||||
"dev-policy"
|
||||
]
|
||||
}
|
||||
"data": {
|
||||
"creation_time": "2017-09-13T01:17:26.755474204Z",
|
||||
"id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8",
|
||||
"last_update_time": "2017-09-13T01:17:26.755474204Z",
|
||||
"member_entity_ids": [],
|
||||
"member_group_ids": null,
|
||||
"metadata": {
|
||||
"organization": "hashicorp",
|
||||
"team": "vault"
|
||||
},
|
||||
"modify_index": 1,
|
||||
"name": "engineering-group",
|
||||
"policies": [
|
||||
"dev-policy"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -228,8 +228,8 @@ This endpoint queries the group by its ID.
|
|||
|
||||
```json
|
||||
{
|
||||
"type": "by_id",
|
||||
"group_id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8"
|
||||
"type": "by_id",
|
||||
"group_id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -247,21 +247,21 @@ $ curl \
|
|||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"creation_time": "2017-09-13T01:17:26.755474204Z",
|
||||
"id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8",
|
||||
"last_update_time": "2017-09-13T01:17:26.755474204Z",
|
||||
"member_entity_ids": [],
|
||||
"member_group_ids": null,
|
||||
"metadata": {
|
||||
"organization": "hashicorp",
|
||||
"team": "vault"
|
||||
},
|
||||
"modify_index": 1,
|
||||
"name": "engineering-group",
|
||||
"policies": [
|
||||
"dev-policy"
|
||||
]
|
||||
}
|
||||
"data": {
|
||||
"creation_time": "2017-09-13T01:17:26.755474204Z",
|
||||
"id": "454ceeb5-76d7-a131-b92a-7ecfb15523e8",
|
||||
"last_update_time": "2017-09-13T01:17:26.755474204Z",
|
||||
"member_entity_ids": [],
|
||||
"member_group_ids": null,
|
||||
"metadata": {
|
||||
"organization": "hashicorp",
|
||||
"team": "vault"
|
||||
},
|
||||
"modify_index": 1,
|
||||
"name": "engineering-group",
|
||||
"policies": [
|
||||
"dev-policy"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -267,9 +267,9 @@ list of available configuration options, please see the [API documentation](/api
|
|||
|
||||
```text
|
||||
$ vault write auth/jwt/config \
|
||||
oidc_discovery_url="https://myco.auth0.com/"
|
||||
oidc_client_id="m5i8bj3iofytj",
|
||||
oidc_client_secret="f4ubv72nfiu23hnsj",
|
||||
oidc_discovery_url="https://myco.auth0.com/" \
|
||||
oidc_client_id="m5i8bj3iofytj" \
|
||||
oidc_client_secret="f4ubv72nfiu23hnsj" \
|
||||
default_role="demo"
|
||||
```
|
||||
|
||||
|
|
|
|||
47
website/source/docs/commands/kv/delete.html.md
Normal file
47
website/source/docs/commands/kv/delete.html.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "kv delete - Command"
|
||||
sidebar_title: "<code>delete</code>"
|
||||
sidebar_current: "docs-commands-kv-delete"
|
||||
description: |-
|
||||
The "kv delete" command disables a secrets engine at a given PATH. The
|
||||
argument corresponds to the enabled PATH of the engine, not the TYPE! All
|
||||
secrets created by this engine are revoked and its Vault data is removed.
|
||||
---
|
||||
|
||||
# kv delete
|
||||
|
||||
The `kv delete` command deletes the data for the provided path in
|
||||
the key/value secrets engine. If using K/V Version 2, its versioned data will
|
||||
not be fully removed, but marked as deleted and will no longer be returned in
|
||||
normal get requests.
|
||||
|
||||
## Examples
|
||||
|
||||
Delete the latest version of the key "creds":
|
||||
|
||||
```text
|
||||
$ vault kv delete secret/creds
|
||||
Success! Data deleted (if it existed) at: secret/creds
|
||||
```
|
||||
|
||||
**[K/V Version 2]** Delete version 11 of key "creds":
|
||||
|
||||
```text
|
||||
$ vault kv delete -versions=11 secret/creds
|
||||
Success! Data deleted (if it existed) at: secret/creds
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
There are no flags beyond the [standard set of flags](/docs/commands/index.html)
|
||||
included on all commands.
|
||||
|
||||
|
||||
### Command Options
|
||||
|
||||
- `-versions` `([]int: <required>)` - The versions to be deleted. The versioned
|
||||
data will not be deleted, but it will no longer be returned in normal get
|
||||
requests.
|
||||
|
||||
~> **NOTE:** This command option is only for K/V v2.
|
||||
44
website/source/docs/commands/kv/destroy.html.md
Normal file
44
website/source/docs/commands/kv/destroy.html.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "kv destroy - Command"
|
||||
sidebar_title: "<code>destroy</code>"
|
||||
sidebar_current: "docs-commands-kv-destroy"
|
||||
description: |-
|
||||
The "kv destroy" command permanently removes the specified version data for
|
||||
the provided key and version numbers from the key-value store.
|
||||
---
|
||||
|
||||
# kv destroy
|
||||
|
||||
~> **NOTE:** This is a [K/V Version 2](/docs/secrets/kv/kv-v2.html) secrets
|
||||
engine command, and not available for Version 1.
|
||||
|
||||
The `secrets enable` command permanently removes the specified versions' data
|
||||
from the key/value secrets engine. If no key exists at the path, no action is
|
||||
taken.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
Destroy version 11 of the key "creds":
|
||||
|
||||
```text
|
||||
$ vault kv destroy -versions=11 secret/creds
|
||||
Success! Data written to: secret/destroy/creds
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
There are no flags beyond the [standard set of flags](/docs/commands/index.html)
|
||||
included on all commands.
|
||||
|
||||
### Output Options
|
||||
|
||||
- `-format` `(string: "table")` - Print the output in the given format. Valid
|
||||
formats are "table", "json", or "yaml". This can also be specified via the
|
||||
`VAULT_FORMAT` environment variable.
|
||||
|
||||
### Command Options
|
||||
|
||||
- `-versions` `([]int: <required>)` - The versions to destroy. Their data will
|
||||
be permanently deleted.
|
||||
35
website/source/docs/commands/kv/enable-versioning.html.md
Normal file
35
website/source/docs/commands/kv/enable-versioning.html.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "kv enable-versioning - Command"
|
||||
sidebar_title: "<code>enable-versioning</code>"
|
||||
sidebar_current: "docs-commands-kv-enable-versioning"
|
||||
description: |-
|
||||
The "kv enable-versioning" command turns on versioning for the backend
|
||||
at the provided path.
|
||||
---
|
||||
|
||||
# kv enable-versioning
|
||||
|
||||
The `kv enable-versioning` command turns on versioning for an existing
|
||||
non-versioned key/value secrets engine (K/V Version 1) at its path.
|
||||
|
||||
## Examples
|
||||
|
||||
This command turns on versioning for the K/V Version 1 secrets engine enabled at
|
||||
"secret".
|
||||
|
||||
```text
|
||||
$ vault kv enable-versioning secret
|
||||
Success! Tuned the secrets engine at: secret/
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
There are no flags beyond the [standard set of flags](/docs/commands/index.html)
|
||||
included on all commands.
|
||||
|
||||
### Output Options
|
||||
|
||||
- `-format` `(string: "table")` - Print the output in the given format. Valid
|
||||
formats are "table", "json", or "yaml". This can also be specified via the
|
||||
`VAULT_FORMAT` environment variable.
|
||||
68
website/source/docs/commands/kv/get.html.md
Normal file
68
website/source/docs/commands/kv/get.html.md
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "kv get - Command"
|
||||
sidebar_title: "<code>get</code>"
|
||||
sidebar_current: "docs-commands-kv-get"
|
||||
description: |-
|
||||
The "kv get" command retrieves the value from Vault's key-value store at the
|
||||
given key name. If no key exists with that name, an error is returned. If a
|
||||
key exists with that name but has no data, nothing is returned.
|
||||
---
|
||||
|
||||
# kv get
|
||||
|
||||
The `kv get` command retrieves the value from K/V secrets engine at the given
|
||||
key name. If no key exists with that name, an error is returned. If a key exists
|
||||
with the name but has no data, nothing is returned.
|
||||
|
||||
## Examples
|
||||
|
||||
Retrieve the data of the key "creds":
|
||||
|
||||
```text
|
||||
$ vault kv get secret/creds
|
||||
====== Metadata ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-06-06T06:03:26.595978Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
version 5
|
||||
|
||||
====== Data ======
|
||||
Key Value
|
||||
--- -----
|
||||
passcode my-long-passcode
|
||||
```
|
||||
|
||||
If K/V Version 1 secrets engine is enabled at "secret", the output has no
|
||||
metadata since there is no versioning information associated with the data:
|
||||
|
||||
```text
|
||||
$ vault kv get secret/creds
|
||||
====== Data ======
|
||||
Key Value
|
||||
--- -----
|
||||
passcode my-long-passcode
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
There are no flags beyond the [standard set of flags](/docs/commands/index.html)
|
||||
included on all commands.
|
||||
|
||||
### Output Options
|
||||
|
||||
- `-field` `(string: "")` - Print only the field with the given name. Specifying
|
||||
this option will take precedence over other formatting directives. The result
|
||||
will not have a trailing newline making it ideal for piping to other
|
||||
processes.
|
||||
|
||||
- `-format` `(string: "table")` - Print the output in the given format. Valid
|
||||
formats are "table", "json", or "yaml". This can also be specified via the
|
||||
`VAULT_FORMAT` environment variable.
|
||||
|
||||
### Command Options
|
||||
|
||||
- `-version` `(int: 0)` - Specifies the version to return. If not set the
|
||||
latest version is returned.
|
||||
114
website/source/docs/commands/kv/index.html.md
Normal file
114
website/source/docs/commands/kv/index.html.md
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "kv - Command"
|
||||
sidebar_title: "<code>kv</code>"
|
||||
sidebar_current: "docs-commands-kv"
|
||||
description: |-
|
||||
The "kv" command groups subcommands for interacting with Vault's key/value
|
||||
secret engine.
|
||||
---
|
||||
|
||||
# kv
|
||||
|
||||
The `kv` command groups subcommands for interacting with Vault's key/value
|
||||
secrets engine (both [K/V Version 1](/docs/secrets/kv/kv-v1.html) and [K/V
|
||||
Version 2](/docs/secrets/kv/kv-v2.html).
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
Create or update the key named "creds" in the K/V Version 2 enabled at "secret"
|
||||
with the value "passcode=my-long-passcode":
|
||||
|
||||
```text
|
||||
$ vault kv put secret/creds passcode=my-long-passcode
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-06-06T04:07:33.279432Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
version 1
|
||||
```
|
||||
|
||||
Read this value back:
|
||||
|
||||
```text
|
||||
$ vault kv get secret/creds
|
||||
====== Metadata ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-06-06T04:07:33.279432Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
version 1
|
||||
|
||||
====== Data ======
|
||||
Key Value
|
||||
--- -----
|
||||
passcode my-long-passcode
|
||||
```
|
||||
|
||||
Get metadata for the key named "creds":
|
||||
|
||||
```text
|
||||
$ vault kv metadata get secret/creds
|
||||
======= Metadata =======
|
||||
Key Value
|
||||
--- -----
|
||||
cas_required false
|
||||
created_time 2019-06-06T04:07:33.279432Z
|
||||
current_version 1
|
||||
max_versions 0
|
||||
oldest_version 0
|
||||
updated_time 2019-06-06T04:07:33.279432Z
|
||||
|
||||
====== Version 1 ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-06-06T04:07:33.279432Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
```
|
||||
|
||||
|
||||
Get a specific version of the key named "creds":
|
||||
|
||||
```text
|
||||
$ vault kv get -version=1 secret/creds
|
||||
====== Metadata ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-06-06T04:07:33.279432Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
version 1
|
||||
|
||||
====== Data ======
|
||||
Key Value
|
||||
--- -----
|
||||
passcode my-long-passcode
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```text
|
||||
Usage: vault kv <subcommand> [options] [args]
|
||||
|
||||
# ...
|
||||
|
||||
Subcommands:
|
||||
delete Deletes versions in the KV store
|
||||
destroy Permanently removes one or more versions in the KV store
|
||||
enable-versioning Turns on versioning for a KV store
|
||||
get Retrieves data from the KV store
|
||||
list List data or secrets
|
||||
metadata Interact with Vault's Key-Value storage
|
||||
patch Sets or updates data in the KV store without overwriting
|
||||
put Sets or updates data in the KV store
|
||||
rollback Rolls back to a previous version of data
|
||||
undelete Undeletes versions in the KV store
|
||||
```
|
||||
|
||||
For more information, examples, and usage about a subcommand, click on the name
|
||||
of the subcommand in the sidebar.
|
||||
45
website/source/docs/commands/kv/list.html.md
Normal file
45
website/source/docs/commands/kv/list.html.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "kv list - Command"
|
||||
sidebar_title: "<code>list</code>"
|
||||
sidebar_current: "docs-commands-kv-list"
|
||||
description: |-
|
||||
The "kv list" command lists data from Vault's K/V secrets engine at the given
|
||||
path.
|
||||
---
|
||||
|
||||
# kv list
|
||||
|
||||
The `kv list` command returns a list of key names at the specified location.
|
||||
Folders are suffixed with /. The input must be a folder; list on a file will not
|
||||
return a value. Note that no policy-based filtering is performed on keys; do not
|
||||
encode sensitive information in key names. The values themselves are not
|
||||
accessible via this command.
|
||||
|
||||
Use this command to list all existing key names at a specific path.
|
||||
|
||||
## Examples
|
||||
|
||||
List values under the key "my-app":
|
||||
|
||||
```text
|
||||
$ vault kv list secret/my-app/
|
||||
Keys
|
||||
----
|
||||
admin_creds
|
||||
domain
|
||||
eng_creds
|
||||
qa_creds
|
||||
release
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
There are no flags beyond the [standard set of flags](/docs/commands/index.html)
|
||||
included on all commands.
|
||||
|
||||
### Output Options
|
||||
|
||||
- `-format` `(string: "table")` - Print the output in the given format. Valid
|
||||
formats are "table", "json", or "yaml". This can also be specified via the
|
||||
`VAULT_FORMAT` environment variable.
|
||||
140
website/source/docs/commands/kv/metadata.html.md
Normal file
140
website/source/docs/commands/kv/metadata.html.md
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
---
|
||||
layout: "docs"
|
||||
page_title: "kv metadata - Command"
|
||||
sidebar_title: "<code>metadata</code>"
|
||||
sidebar_current: "docs-commands-kv-metadata"
|
||||
description: |-
|
||||
The "kv metadata" command has subcommands for interacting with the metadata
|
||||
endpoint in Vault's key-value store.
|
||||
---
|
||||
|
||||
# kv metadata
|
||||
|
||||
~> **NOTE:** This is a [K/V Version 2](/docs/secrets/kv/kv-v2.html) secrets
|
||||
engine command, and not available for Version 1.
|
||||
|
||||
|
||||
The `kv metadata` command has subcommands for interacting with the metadata and
|
||||
versions for the versioned secrets (K/V Version 2 secrets engine) at the
|
||||
specified path.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```text
|
||||
Usage: vault kv metadata <subcommand> [options] [args]
|
||||
|
||||
# ...
|
||||
|
||||
Subcommands:
|
||||
delete Deletes all versions and metadata for a key in the KV store
|
||||
get Retrieves key metadata from the KV store
|
||||
put Sets or updates key settings in the KV store
|
||||
```
|
||||
|
||||
### kv metadata delete
|
||||
|
||||
The `kv metadata delete` command deletes all versions and metadata for the
|
||||
provided key.
|
||||
|
||||
#### Examples
|
||||
|
||||
Deletes all versions and metadata of the key "creds":
|
||||
|
||||
```text
|
||||
$ vault kv metadata delete secret/creds
|
||||
Success! Data deleted (if it existed) at: secret/metadata/creds
|
||||
```
|
||||
|
||||
|
||||
### kv metadata get
|
||||
|
||||
The `kv metadata get` command retrieves the metadata of the versioned secrets at
|
||||
the given key name. If no key exists with that name, an error is returned.
|
||||
|
||||
#### Examples
|
||||
|
||||
Retrieves the metadata of the key name, "creds":
|
||||
|
||||
```text
|
||||
$ vault kv metadata get secret/creds
|
||||
======= Metadata =======
|
||||
Key Value
|
||||
--- -----
|
||||
cas_required false
|
||||
created_time 2019-06-06T04:07:33.279432Z
|
||||
current_version 5
|
||||
max_versions 0
|
||||
oldest_version 0
|
||||
updated_time 2019-06-06T06:03:26.595978Z
|
||||
|
||||
====== Version 1 ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-06-06T04:07:33.279432Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
|
||||
====== Version 2 ======
|
||||
Key Value
|
||||
--- -----
|
||||
created_time 2019-06-06T06:03:12.187441Z
|
||||
deletion_time n/a
|
||||
destroyed false
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
### kv metadata put
|
||||
|
||||
The `kv metadata put` command can be used to create a blank key in the K/V v2
|
||||
secrets engine or to update key configuration for a specified key.
|
||||
|
||||
|
||||
#### Examples
|
||||
|
||||
Create a key in the K/V v2 with no data at the key "creds":
|
||||
|
||||
```text
|
||||
$ vault kv metadata put secret/creds
|
||||
Success! Data written to: secret/metadata/creds
|
||||
```
|
||||
|
||||
Set the maximum number of versions to keep for the key "creds":
|
||||
|
||||
```text
|
||||
$ vault kv metadata put -max-versions=5 secret/creds
|
||||
Success! Data written to: secret/metadata/creds
|
||||
```
|
||||
|
||||
**NOTE:** If not set, the backend’s configured max version is used. Once a key
|
||||
has more than the configured allowed versions the oldest version will be
|
||||
permanently deleted.
|
||||
|
||||
|
||||
Require Check-and-Set for the key "creds":
|
||||
|
||||
```text
|
||||
$ vault kv metadata put -cas-required secret/creds
|
||||
```
|
||||
|
||||
**NOTE:** When check-and-set is required, the key will require the `cas`
|
||||
parameter to be set on all write requests. Otherwise, the backend’s
|
||||
configuration will be used.
|
||||
|
||||
#### Output Options
|
||||
|
||||
- `-format` `(string: "table")` - Print the output in the given format. Valid
|
||||
formats are "table", "json", or "yaml". This can also be specified via the
|
||||
`VAULT_FORMAT` environment variable.
|
||||
|
||||
#### Subcommand Options
|
||||
|
||||
- `-cas-required` `(bool: false)` - If true the key will require the cas
|
||||
parameter to be set on all write requests. If false, the backend’s
|
||||
configuration will be used. The default is false.
|
||||
|
||||
- `-max-versions` `(int: 0)` - The number of versions to keep per key. If not
|
||||
set, the backend’s configured max version is used. Once a key has more than the
|
||||
configured allowed versions the oldest version will be permanently deleted.
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue