parent
3f7454939e
commit
b46c42179e
|
@ -0,0 +1,207 @@
|
|||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "cloud.google.com/go"
|
||||
packages = ["compute/metadata"]
|
||||
revision = "5a9e19d4e1e41a734154e44a2132b358afb49a03"
|
||||
version = "v0.13.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/SermoDigital/jose"
|
||||
packages = [".","crypto","jws","jwt"]
|
||||
revision = "f6df55f235c24f236d11dbcf665249a59ac2021f"
|
||||
version = "1.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/armon/go-radix"
|
||||
packages = ["."]
|
||||
revision = "1fca145dffbcaa8fe914309b1ec0cfc67500fe61"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/fatih/structs"
|
||||
packages = ["."]
|
||||
revision = "a720dfa8df582c51dee1b36feabb906bde1588bd"
|
||||
version = "v1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = ["proto","ptypes","ptypes/any","ptypes/duration","ptypes/timestamp"]
|
||||
revision = "17ce1425424ab154092bbb43af630bd647f3bb0d"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/snappy"
|
||||
packages = ["."]
|
||||
revision = "553a641470496b2327abcac10b36396bd98e45c9"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/errwrap"
|
||||
packages = ["."]
|
||||
revision = "7554cd9344cec97297fa6649b055a8c98c2a1e55"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-cleanhttp"
|
||||
packages = ["."]
|
||||
revision = "3573b8b52aa7b37b9358d966a898feb387f62437"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-hclog"
|
||||
packages = ["."]
|
||||
revision = "8105cc0a3736cc153a2025f5d0d91b80045fc9ff"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-multierror"
|
||||
packages = ["."]
|
||||
revision = "83588e72410abfbe4df460eeb6f30841ae47d4c4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-plugin"
|
||||
packages = ["."]
|
||||
revision = "3e6d191694b5a3a2b99755f31b47fa209e4bcd09"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-rootcerts"
|
||||
packages = ["."]
|
||||
revision = "6bb64b370b90e7ef1fa532be9e591a81c3493e00"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-uuid"
|
||||
packages = ["."]
|
||||
revision = "64130c7a86d732268a38cb04cfbaf0cc987fda98"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/hcl"
|
||||
packages = [".","hcl/ast","hcl/parser","hcl/scanner","hcl/strconv","hcl/token","json/parser","json/scanner","json/token"]
|
||||
revision = "68e816d1c783414e79bc65b3994d9ab6b0a722ab"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/vault"
|
||||
packages = ["api","helper/certutil","helper/compressutil","helper/consts","helper/errutil","helper/jsonutil","helper/logformat","helper/mlock","helper/parseutil","helper/pluginutil","helper/policyutil","helper/salt","helper/strutil","helper/wrapping","logical","logical/framework","logical/plugin","version"]
|
||||
revision = "27197f728e7fc8bffc9eaa59e8af4e0766b81320"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/yamux"
|
||||
packages = ["."]
|
||||
revision = "d1caa6c97c9fc1cc9e83bbe34d0603f9ff0ce8bd"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-colorable"
|
||||
packages = ["."]
|
||||
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072"
|
||||
version = "v0.0.9"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-isatty"
|
||||
packages = ["."]
|
||||
revision = "fc9e8d8ef48496124e79ae0df75490096eccf6fe"
|
||||
version = "v0.0.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mgutz/ansi"
|
||||
packages = ["."]
|
||||
revision = "9520e82c474b0a04dd04f8a40959027271bab992"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mgutz/logxi"
|
||||
packages = ["v1"]
|
||||
revision = "aebf8a7d67ab4625e0fd4a665766fef9a709161b"
|
||||
version = "v1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mitchellh/go-homedir"
|
||||
packages = ["."]
|
||||
revision = "b8bc1bf767474819792c23f32d8286a45736f1c6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mitchellh/go-testing-interface"
|
||||
packages = ["."]
|
||||
revision = "7bf6f6eaf1bed2fd3c6c63114b18cb64facb9de2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mitchellh/mapstructure"
|
||||
packages = ["."]
|
||||
revision = "d0303fe809921458f417bcf828397a65db30a7e4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/sethgrid/pester"
|
||||
packages = ["."]
|
||||
revision = "a86a2d88f4dc3c7dbf3a6a6bbbfb095690b834b6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["context","context/ctxhttp","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace"]
|
||||
revision = "859d1a86bb617c0c20d154590c3c5d3fcb670b07"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
packages = [".","google","internal","jws","jwt"]
|
||||
revision = "13449ad91cb26cb47661c1b080790392170385fd"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "062cd7e4e68206d8bab9b18396626e855c992658"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/text"
|
||||
packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
|
||||
revision = "ab5ac5f9a8deb4855a60fab02bc61a4ec770bd49"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "google.golang.org/api"
|
||||
packages = ["compute/v1","gensupport","googleapi","googleapi/internal/uritemplates","iam/v1","oauth2/v2"]
|
||||
revision = "519500316f39a9934d1d88615a1a047035a4bae5"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/appengine"
|
||||
packages = [".","internal","internal/app_identity","internal/base","internal/datastore","internal/log","internal/modules","internal/remote_api","internal/urlfetch","urlfetch"]
|
||||
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "google.golang.org/genproto"
|
||||
packages = ["googleapis/rpc/status"]
|
||||
revision = "595979c8a7bf586b2d293fb42246bf91a0b893d9"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/grpc"
|
||||
packages = [".","codes","connectivity","credentials","grpclb/grpc_lb_v1/messages","grpclog","health","health/grpc_health_v1","internal","keepalive","metadata","naming","peer","stats","status","tap","transport"]
|
||||
revision = "f92cdcd7dcdc69e81b2d7b338479a19a8723cfa3"
|
||||
version = "v1.6.0"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/square/go-jose.v2"
|
||||
packages = [".","cipher","json","jwt"]
|
||||
revision = "b25e6cab129e4a54675b42ea49d38e9c33ade9e6"
|
||||
version = "v2.1.2"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "f9ed330c7039eae92bba02edc9d8463bb8f3dd93229e287004acc600825f9e92"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/SermoDigital/jose"
|
||||
version = "1.1.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-cleanhttp"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/hashicorp/vault"
|
||||
branch = "master"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/mgutz/logxi"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/oauth2"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "google.golang.org/api"
|
|
@ -0,0 +1,58 @@
|
|||
TOOL?=vault-gcp-auth-plugin
|
||||
TEST?=$$(go list ./... | grep -v /vendor/)
|
||||
VETARGS?=-asmdecl -atomic -bool -buildtags -copylocks -methods -nilfunc -printf -rangeloops -shift -structtags -unsafeptr
|
||||
EXTERNAL_TOOLS=\
|
||||
github.com/mitchellh/gox \
|
||||
github.com/kardianos/govendor
|
||||
BUILD_TAGS?=${TOOL}
|
||||
GOFMT_FILES?=$$(find . -name '*.go' | grep -v vendor)
|
||||
|
||||
# bin generates the releaseable binaries for this plugin
|
||||
bin: fmtcheck generate
|
||||
@CGO_ENABLED=0 BUILD_TAGS='$(BUILD_TAGS)' sh -c "'$(CURDIR)/scripts/build.sh'"
|
||||
|
||||
default: dev
|
||||
|
||||
# dev creates binaries for testing Vault locally. These are put
|
||||
# into ./bin/ as well as $GOPATH/bin, except for quickdev which
|
||||
# is only put into /bin/
|
||||
quickdev: generate
|
||||
@CGO_ENABLED=0 go build -i -tags='$(BUILD_TAGS)' -o bin/vault-gcp-auth-plugin
|
||||
dev: fmtcheck generate
|
||||
@CGO_ENABLED=0 BUILD_TAGS='$(BUILD_TAGS)' VAULT_DEV_BUILD=1 sh -c "'$(CURDIR)/scripts/build.sh'"
|
||||
dev-dynamic: generate
|
||||
@CGO_ENABLED=1 BUILD_TAGS='$(BUILD_TAGS)' VAULT_DEV_BUILD=1 sh -c "'$(CURDIR)/scripts/build.sh'"
|
||||
|
||||
testcompile: fmtcheck generate
|
||||
@for pkg in $(TEST) ; do \
|
||||
go test -v -c -tags='$(BUILD_TAGS)' $$pkg -parallel=4 ; \
|
||||
done
|
||||
|
||||
# test runs all tests
|
||||
test: fmtcheck generate
|
||||
@if [ "$(TEST)" = "./..." ]; then \
|
||||
echo "ERROR: Set TEST to a specific package"; \
|
||||
exit 1; \
|
||||
fi
|
||||
VAULT_ACC=1 go test -tags='$(BUILD_TAGS)' $(TEST) -v $(TESTARGS) -timeout 45m
|
||||
|
||||
# generate runs `go generate` to build the dynamically generated
|
||||
# source files.
|
||||
generate:
|
||||
go generate $(go list ./... | grep -v /vendor/)
|
||||
|
||||
# bootstrap the build by downloading additional tools
|
||||
bootstrap:
|
||||
@for tool in $(EXTERNAL_TOOLS) ; do \
|
||||
echo "Installing/Updating $$tool" ; \
|
||||
go get -u $$tool; \
|
||||
done
|
||||
|
||||
fmtcheck:
|
||||
@sh -c "'$(CURDIR)/scripts/gofmtcheck.sh'"
|
||||
|
||||
fmt:
|
||||
gofmt -w $(GOFMT_FILES)
|
||||
|
||||
|
||||
.PHONY: bin default generate test vet bootstrap fmt fmtcheck
|
|
@ -0,0 +1,149 @@
|
|||
# Vault Plugin: Google Cloud Platform Auth Backend
|
||||
|
||||
This is a standalone backend plugin for use with [Hashicorp Vault](https://www.github.com/hashicorp/vault).
|
||||
This plugin allows for various GCP entities to authenticate with Vault.
|
||||
This is currently included in Vault distributions.
|
||||
|
||||
Currently, this plugin supports login for:
|
||||
- IAM service accounts
|
||||
- GCE Instances
|
||||
|
||||
**Please note**: We take Vault's security and our users' trust very seriously. If you believe you have found a security issue in Vault, _please responsibly disclose_ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com).
|
||||
|
||||
## Quick Links
|
||||
|
||||
- [Vault Website](https://www.vaultproject.io)
|
||||
- [GCP Auth BE Docs](https://www.vaultproject.io/docs/auth/gcp.html)
|
||||
- [Vault Github](https://www.github.com/hashicorp/vault)
|
||||
- [General Announcement List](https://groups.google.com/forum/#!forum/hashicorp-announce)
|
||||
- [Discussion List](https://groups.google.com/forum/#!forum/vault-tool)
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
This is a [Vault plugin](https://www.vaultproject.io/docs/internals/plugins.html)
|
||||
and is meant to work with Vault. This guide assumes you have already installed Vault
|
||||
and have a basic understanding of how Vault works.
|
||||
|
||||
Otherwise, first read this guide on how to [get started with Vault](https://www.vaultproject.io/intro/getting-started/install.html).
|
||||
|
||||
To learn specifically about how plugins work, see documentation on [Vault plugins](https://www.vaultproject.io/docs/internals/plugins.html).
|
||||
|
||||
### Usage
|
||||
|
||||
Please see [documentation for the plugin](https://www.vaultproject.io/docs/auth/gcp.html)
|
||||
on the Vault website.
|
||||
|
||||
This plugin is currently built into Vault and by default is accessed
|
||||
at `auth/gcp`. To enable this in a running Vault server:
|
||||
|
||||
```sh
|
||||
$ vault auth-enable 'gcp'
|
||||
Successfully enabled 'gcp' at 'gcp'!
|
||||
```
|
||||
|
||||
To see all the supported paths, see the [GCP auth backend docs](https://www.vaultproject.io/docs/auth/gcp.html).
|
||||
|
||||
## Developing
|
||||
|
||||
If you wish to work on this plugin, you'll first need
|
||||
[Go](https://www.golang.org) installed on your machine
|
||||
(version 1.8+ is *required*).
|
||||
|
||||
For local dev first make sure Go is properly installed, including
|
||||
setting up a [GOPATH](https://golang.org/doc/code.html#GOPATH).
|
||||
Next, clone this repository into
|
||||
`$GOPATH/src/github.com/hashicorp/vault-gcp-auth-plugin`.
|
||||
You can then download any required build tools by bootstrapping your
|
||||
environment:
|
||||
|
||||
```sh
|
||||
$ make bootstrap
|
||||
```
|
||||
|
||||
To compile a development version of this plugin, run `make` or `make dev`.
|
||||
This will put the plugin binary in the `bin` and `$GOPATH/bin` folders. `dev`
|
||||
mode will only generate the binary for your platform and is faster:
|
||||
|
||||
```sh
|
||||
$ make
|
||||
$ make dev
|
||||
```
|
||||
|
||||
Put the plugin binary into a location of your choice. This directory
|
||||
will be specified as the [`plugin_directory`](https://www.vaultproject.io/docs/configuration/index.html#plugin_directory)
|
||||
in the Vault config used to start the server.
|
||||
|
||||
```json
|
||||
...
|
||||
plugin_directory = "path/to/plugin/directory"
|
||||
...
|
||||
```
|
||||
|
||||
Start a Vault server with this config file:
|
||||
```sh
|
||||
$ vault server -config=path/to/config.json ...
|
||||
...
|
||||
```
|
||||
|
||||
Once the server is started, register the plugin in the Vault server's [plugin catalog](https://www.vaultproject.io/docs/internals/plugins.html#plugin-catalog):
|
||||
|
||||
```sh
|
||||
$ vault write sys/plugins/catalog/mygcpplugin \
|
||||
sha_256=<expected SHA256 Hex value of the plugin binary> \
|
||||
command="vault-plugin-auth-gcp"
|
||||
...
|
||||
Success! Data written to: sys/plugins/catalog/mygcpplugin
|
||||
```
|
||||
|
||||
Note you should generate a new sha256 checksum if you have made changes
|
||||
to the plugin. Example using openssl:
|
||||
|
||||
```sh
|
||||
openssl dgst -sha256 $GOPATH/vault-plugin-gcp-auth
|
||||
...
|
||||
SHA256(.../go/bin/vault-plugin-auth-gcp)= 896c13c0f5305daed381952a128322e02bc28a57d0c862a78cbc2ea66e8c6fa1
|
||||
```
|
||||
|
||||
Any name can be substituted for the plugin name "mygcpplugin". This
|
||||
name will be referenced in the next step, where we enable the auth
|
||||
plugin backend using the GCP auth plugin:
|
||||
|
||||
```sh
|
||||
$ vault auth-enable -plugin-name='mygcpplugin' -path='gcp' plugin
|
||||
...
|
||||
|
||||
Successfully enabled 'plugin' at 'gcp'!
|
||||
```
|
||||
|
||||
#### Tests
|
||||
|
||||
This plugin has comprehensive [acceptance tests](https://en.wikipedia.org/wiki/Acceptance_testing)
|
||||
covering most of the features of this auth backend.
|
||||
|
||||
If you are developing this plugin and want to verify it is still
|
||||
functioning (and you haven't broken anything else), we recommend
|
||||
running the acceptance tests.
|
||||
|
||||
Acceptance tests typically require other environment variables to be set for
|
||||
things such as access keys. The test itself should error early and tell
|
||||
you what to set, so it is not documented here.
|
||||
|
||||
**Warning:** The acceptance tests create/destroy/modify *real resources*,
|
||||
which may incur real costs in some cases. In the presence of a bug,
|
||||
it is technically possible that broken backends could leave dangling
|
||||
data behind. Therefore, please run the acceptance tests at your own risk.
|
||||
At the very least, we recommend running them in their own private
|
||||
account for whatever backend you're testing.
|
||||
|
||||
To run the acceptance tests, invoke `make test`:
|
||||
|
||||
```sh
|
||||
$ make test
|
||||
```
|
||||
|
||||
You can also specify a `TESTARGS` variable to filter tests like so:
|
||||
|
||||
```sh
|
||||
$ make test TESTARGS='--run=TestConfig'
|
||||
```
|
|
@ -0,0 +1,28 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
gcpbackend "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
|
||||
"github.com/hashicorp/vault/helper/pluginutil"
|
||||
"github.com/hashicorp/vault/logical/plugin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
apiClientMeta := &pluginutil.APIClientMeta{}
|
||||
flags := apiClientMeta.FlagSet()
|
||||
flags.Parse(os.Args[1:])
|
||||
|
||||
tlsConfig := apiClientMeta.GetTLSConfig()
|
||||
tlsProviderFunc := pluginutil.VaultPluginTLSProvider(tlsConfig)
|
||||
|
||||
err := plugin.Serve(&plugin.ServeOpts{
|
||||
BackendFactoryFunc: gcpbackend.Factory,
|
||||
TLSProviderFunc: tlsProviderFunc,
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -3,6 +3,10 @@ package gcpauth
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault-plugin-auth-gcp/plugin/util"
|
||||
"github.com/hashicorp/vault/helper/policyutil"
|
||||
"github.com/hashicorp/vault/helper/strutil"
|
||||
|
@ -11,9 +15,6 @@ import (
|
|||
"google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/iam/v1"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -40,7 +41,7 @@ GCE identity metadata token ('iam', 'gce' roles).`,
|
|||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: b.pathLogin,
|
||||
logical.PersonaLookaheadOperation: b.pathLogin,
|
||||
logical.AliasLookaheadOperation: b.pathLogin,
|
||||
},
|
||||
|
||||
HelpSynopsis: pathLoginHelpSyn,
|
||||
|
@ -82,11 +83,11 @@ func (b *GcpAuthBackend) pathLoginRenew(req *logical.Request, data *framework.Fi
|
|||
|
||||
switch role.RoleType {
|
||||
case iamRoleType:
|
||||
if err := b.pathIamRenew(req, role); err != nil {
|
||||
if err := b.pathIamRenew(req, roleName, role); err != nil {
|
||||
return logical.ErrorResponse(err.Error()), nil
|
||||
}
|
||||
case gceRoleType:
|
||||
if err := b.pathGceRenew(req, role); err != nil {
|
||||
if err := b.pathGceRenew(req, roleName, role); err != nil {
|
||||
return logical.ErrorResponse(err.Error()), nil
|
||||
}
|
||||
default:
|
||||
|
@ -263,7 +264,7 @@ func (b *GcpAuthBackend) pathIamLogin(req *logical.Request, loginInfo *gcpLoginI
|
|||
role := loginInfo.Role
|
||||
if !role.AllowGCEInference && loginInfo.GceMetadata != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf(
|
||||
"IAM role '%s' does not allow gce inference but GCE instance metadata token given", loginInfo.RoleName)), nil
|
||||
"Got GCE token but IAM role '%s' does not allow GCE inference", loginInfo.RoleName)), nil
|
||||
}
|
||||
|
||||
// TODO(emilymye): move to general JWT validation once custom expiry is supported for other JWT types.
|
||||
|
@ -280,10 +281,10 @@ func (b *GcpAuthBackend) pathIamLogin(req *logical.Request, loginInfo *gcpLoginI
|
|||
return nil, errors.New("service account is empty")
|
||||
}
|
||||
|
||||
if req.Operation == logical.PersonaLookaheadOperation {
|
||||
if req.Operation == logical.AliasLookaheadOperation {
|
||||
return &logical.Response{
|
||||
Auth: &logical.Auth{
|
||||
Persona: &logical.Persona{
|
||||
Alias: &logical.Alias{
|
||||
Name: serviceAccount.UniqueId,
|
||||
},
|
||||
},
|
||||
|
@ -298,15 +299,11 @@ func (b *GcpAuthBackend) pathIamLogin(req *logical.Request, loginInfo *gcpLoginI
|
|||
resp := &logical.Response{
|
||||
Auth: &logical.Auth{
|
||||
Period: role.Period,
|
||||
Persona: &logical.Persona{
|
||||
Alias: &logical.Alias{
|
||||
Name: serviceAccount.UniqueId,
|
||||
},
|
||||
Policies: role.Policies,
|
||||
Metadata: map[string]string{
|
||||
"service_account_id": serviceAccount.UniqueId,
|
||||
"service_account_email": serviceAccount.Email,
|
||||
"role": loginInfo.RoleName,
|
||||
},
|
||||
Metadata: authMetadata(loginInfo, serviceAccount),
|
||||
DisplayName: serviceAccount.Email,
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
Renewable: true,
|
||||
|
@ -320,7 +317,7 @@ func (b *GcpAuthBackend) pathIamLogin(req *logical.Request, loginInfo *gcpLoginI
|
|||
|
||||
// pathIamRenew returns an error if the service account referenced in the auth token metadata cannot renew the
|
||||
// auth token for the given role.
|
||||
func (b *GcpAuthBackend) pathIamRenew(req *logical.Request, role *gcpRole) error {
|
||||
func (b *GcpAuthBackend) pathIamRenew(req *logical.Request, roleName string, role *gcpRole) error {
|
||||
iamClient, err := b.IAM(req.Storage)
|
||||
if err != nil {
|
||||
return fmt.Errorf(clientErrorTemplate, "IAM", err)
|
||||
|
@ -336,8 +333,13 @@ func (b *GcpAuthBackend) pathIamRenew(req *logical.Request, role *gcpRole) error
|
|||
return fmt.Errorf("cannot find service account %s", serviceAccountId)
|
||||
}
|
||||
|
||||
_, isGceInferred := req.Auth.Metadata["instance_id"]
|
||||
if isGceInferred && !role.AllowGCEInference {
|
||||
return fmt.Errorf("GCE inferrence is no longer allowed for role %s", roleName)
|
||||
}
|
||||
|
||||
if err := b.authorizeIAMServiceAccount(serviceAccount, role); err != nil {
|
||||
return errors.New("service account is no longer authorized for role")
|
||||
return fmt.Errorf("service account is no longer authorized for role %s", roleName)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -370,8 +372,6 @@ func (b *GcpAuthBackend) authorizeIAMServiceAccount(serviceAccount *iam.ServiceA
|
|||
func (b *GcpAuthBackend) pathGceLogin(req *logical.Request, loginInfo *gcpLoginInfo) (*logical.Response, error) {
|
||||
role := loginInfo.Role
|
||||
metadata := loginInfo.GceMetadata
|
||||
fmt.Printf("here\n")
|
||||
fmt.Printf("metadata.CreatedAt \n")
|
||||
if metadata == nil {
|
||||
return logical.ErrorResponse("could not get GCE metadata from given JWT"), nil
|
||||
}
|
||||
|
@ -399,24 +399,27 @@ func (b *GcpAuthBackend) pathGceLogin(req *logical.Request, loginInfo *gcpLoginI
|
|||
return logical.ErrorResponse(err.Error()), nil
|
||||
}
|
||||
|
||||
iamClient, err := b.IAM(req.Storage)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf(clientErrorTemplate, "IAM", err)), nil
|
||||
}
|
||||
|
||||
serviceAccount, err := util.ServiceAccount(iamClient, loginInfo.ServiceAccountId, loginInfo.Role.ProjectId)
|
||||
if err != nil {
|
||||
return logical.ErrorResponse(fmt.Sprintf(
|
||||
"Could not find service account '%s' used for GCE metadata token: %s",
|
||||
loginInfo.ServiceAccountId, err)), nil
|
||||
}
|
||||
|
||||
resp := &logical.Response{
|
||||
Auth: &logical.Auth{
|
||||
InternalData: map[string]interface{}{},
|
||||
Period: role.Period,
|
||||
Persona: &logical.Persona{
|
||||
Alias: &logical.Alias{
|
||||
Name: fmt.Sprintf("gce-%s", strconv.FormatUint(instance.Id, 10)),
|
||||
},
|
||||
Policies: role.Policies,
|
||||
Metadata: map[string]string{
|
||||
"project_id": metadata.ProjectId,
|
||||
"project_number": strconv.FormatInt(metadata.ProjectNumber, 10),
|
||||
"zone": metadata.Zone,
|
||||
"instance_id": metadata.InstanceId,
|
||||
"instance_name": metadata.InstanceName,
|
||||
"instance_creation_timestamp": strconv.FormatInt(metadata.CreatedAt, 10),
|
||||
"service_account_id": loginInfo.ServiceAccountId,
|
||||
"role": loginInfo.RoleName,
|
||||
},
|
||||
Metadata: authMetadata(loginInfo, serviceAccount),
|
||||
DisplayName: instance.Name,
|
||||
LeaseOptions: logical.LeaseOptions{
|
||||
Renewable: true,
|
||||
|
@ -428,9 +431,28 @@ func (b *GcpAuthBackend) pathGceLogin(req *logical.Request, loginInfo *gcpLoginI
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func authMetadata(loginInfo *gcpLoginInfo, serviceAccount *iam.ServiceAccount) map[string]string {
|
||||
metadata := map[string]string{
|
||||
"role": loginInfo.RoleName,
|
||||
"service_account_id": serviceAccount.UniqueId,
|
||||
"service_account_email": serviceAccount.Email,
|
||||
}
|
||||
|
||||
if loginInfo.GceMetadata != nil {
|
||||
gceMetadata := loginInfo.GceMetadata
|
||||
metadata["project_id"] = gceMetadata.ProjectId
|
||||
metadata["project_number"] = strconv.FormatInt(gceMetadata.ProjectNumber, 10)
|
||||
metadata["zone"] = gceMetadata.Zone
|
||||
metadata["instance_id"] = gceMetadata.InstanceId
|
||||
metadata["instance_name"] = gceMetadata.InstanceName
|
||||
metadata["instance_creation_timestamp"] = strconv.FormatInt(gceMetadata.CreatedAt, 10)
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
|
||||
// pathGceRenew returns an error if the instance referenced in the auth token metadata cannot renew the
|
||||
// auth token for the given role.
|
||||
func (b *GcpAuthBackend) pathGceRenew(req *logical.Request, role *gcpRole) error {
|
||||
func (b *GcpAuthBackend) pathGceRenew(req *logical.Request, roleName string, role *gcpRole) error {
|
||||
gceClient, err := b.GCE(req.Storage)
|
||||
if err != nil {
|
||||
return fmt.Errorf(clientErrorTemplate, "GCE", err)
|
||||
|
@ -451,7 +473,7 @@ func (b *GcpAuthBackend) pathGceRenew(req *logical.Request, role *gcpRole) error
|
|||
return errors.New("invalid auth metadata: service_account_id not found")
|
||||
}
|
||||
if err := b.authorizeGCEInstance(instance, req.Storage, role, meta.Zone, serviceAccountId); err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not renew token for role %s: %v", roleName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -143,7 +143,7 @@
|
|||
branch = "master"
|
||||
name = "github.com/hashicorp/vault"
|
||||
packages = ["api","helper/certutil","helper/compressutil","helper/consts","helper/errutil","helper/jsonutil","helper/logformat","helper/mlock","helper/parseutil","helper/pluginutil","helper/policyutil","helper/salt","helper/strutil","helper/wrapping","logical","logical/framework","logical/plugin"]
|
||||
revision = "87581df7dd8f9b2a7faf16dc48b692aaab329ade"
|
||||
revision = "27197f728e7fc8bffc9eaa59e8af4e0766b81320"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
|
|
@ -7,7 +7,7 @@ This plugin allows for Kubernets Service Accounts to authenticate with Vault.
|
|||
|
||||
## Quick Links
|
||||
- Vault Website: https://www.vaultproject.io
|
||||
- Kubernetes Auth Docs: https://www.vaultproject.io/docs/auth/kubernetes.html
|
||||
- Kunernetes Auth Docs: https://www.vaultproject.io/docs/auth/kubernetes.html
|
||||
- Main Project Github: https://www.github.com/hashicorp/vault
|
||||
|
||||
|
||||
|
@ -21,7 +21,13 @@ Otherwise, first read this guide on how to [get started with Vault](https://www.
|
|||
|
||||
To learn specifically about how plugins work, see documentation on [Vault plugins](https://www.vaultproject.io/docs/internals/plugins.html).
|
||||
|
||||
### Usage
|
||||
## Security Model
|
||||
|
||||
The current authentication model requires providing Vault with a Service Account token, which can be used to make authenticated calls to Kubernetes. This token should not typically be shared, but in order for Kubernetes to be treated as a trusted third party, Vault must validate something that Kubernetes has cryptographically signed and that conveys the identity of the token holder.
|
||||
|
||||
We expect Kubernetes to support less sensitive mechanisms in the future, and the Vault integration will be updated to use those mechanisms when available.
|
||||
|
||||
## Usage
|
||||
|
||||
Please see [documentation for the plugin](https://www.vaultproject.io/docs/auth/kubernetes.html)
|
||||
on the Vault website.
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICZDCCAeugAwIBAgIJALM9NbK8WRuBMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
|
||||
dXMxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdp
|
||||
dHMgUHR5IEx0ZDAeFw0xNzA5MTExNzQ2NDNaFw0yNzA5MDkxNzQ2NDNaMEUxCzAJ
|
||||
BgNVBAYTAnVzMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5l
|
||||
dCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATcqsBLxKP+
|
||||
UHk7Y6ktGGFvfrIfIXHxeZe3Xwt691CWfdmJFvrGzyzW5/AbJIuO1utdOsqUStAm
|
||||
W/Scfxop/FGadKqR4nAWLNBI4intgnf0r1rzBCSOmanolHqxQPqQ0UOjgacwgaQw
|
||||
HQYDVR0OBBYEFHxh1pTd8ApEzg0gKMwwt01aA10TMHUGA1UdIwRuMGyAFHxh1pTd
|
||||
8ApEzg0gKMwwt01aA10ToUmkRzBFMQswCQYDVQQGEwJ1czETMBEGA1UECBMKU29t
|
||||
ZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkggkAsz01
|
||||
srxZG4EwDAYDVR0TBAUwAwEB/zAJBgcqhkjOPQQBA2gAMGUCMCR+CvAoNBhqSe2M
|
||||
4qWWD/9XX/0qmf0O442Qowcg5MWH1+mwl1s7ozinvbTPDPaYDwIxAM54qKhuL6xt
|
||||
GxqJpa7Onn15Hu8zTsdzeYBqUUXA6wtn+Pa7197CgUkfty9yc2eeQw==
|
||||
-----END CERTIFICATE-----
|
|
@ -1,6 +0,0 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MIGkAgEBBDC8aqQEyHUFnPPhnwk6wzO4L2bxB+eCvgNKuvaV+A0Ut8wgWR9Et/X4
|
||||
2fNGXFvXBnOgBwYFK4EEACKhZANiAATcqsBLxKP+UHk7Y6ktGGFvfrIfIXHxeZe3
|
||||
Xwt691CWfdmJFvrGzyzW5/AbJIuO1utdOsqUStAmW/Scfxop/FGadKqR4nAWLNBI
|
||||
4intgnf0r1rzBCSOmanolHqxQPqQ0UM=
|
||||
-----END EC PRIVATE KEY-----
|
|
@ -1,5 +0,0 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHQCAQEEICRfLPO5eiMXmBDKiCcpzAJ6d8/grut5jviH/CZc2svSoAcGBSuBBAAK
|
||||
oUQDQgAEkBfDOBa/VAm0zem0wmu2QlAFprcYU3vTcQgTYIZ622sPTLvp8q4QxP7P
|
||||
AkTjKGEOg4tfap+4hKd94psmlOex0A==
|
||||
-----END EC PRIVATE KEY-----
|
|
@ -1,4 +0,0 @@
|
|||
-----BEGIN PUBLIC KEY-----
|
||||
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEkBfDOBa/VAm0zem0wmu2QlAFprcYU3vT
|
||||
cQgTYIZ622sPTLvp8q4QxP7PAkTjKGEOg4tfap+4hKd94psmlOex0A==
|
||||
-----END PUBLIC KEY-----
|
|
@ -7,6 +7,7 @@ import (
|
|||
"encoding/pem"
|
||||
"errors"
|
||||
|
||||
"github.com/SermoDigital/jose/jws"
|
||||
"github.com/hashicorp/vault/logical"
|
||||
"github.com/hashicorp/vault/logical/framework"
|
||||
)
|
||||
|
@ -19,13 +20,6 @@ func pathConfig(b *kubeAuthBackend) *framework.Path {
|
|||
return &framework.Path{
|
||||
Pattern: "config$",
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"pem_keys": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `List of PEM-formated public keys or certificates
|
||||
used to verify the signatures of kubernetes service account
|
||||
JWTs. If a certificate is given, its public key will be
|
||||
extracted.`,
|
||||
},
|
||||
"kubernetes_host": {
|
||||
Type: framework.TypeString,
|
||||
Description: "Host must be a host string, a host:port pair, or a URL to the base of the Kubernetes API server.",
|
||||
|
@ -34,6 +28,19 @@ extracted.`,
|
|||
Type: framework.TypeString,
|
||||
Description: "PEM encoded CA cert for use by the TLS client used to talk with the API.",
|
||||
},
|
||||
"token_reviewer_jwt": {
|
||||
Type: framework.TypeString,
|
||||
Description: `A service account JWT used to access the
|
||||
TokenReview API to validate other JWTs during login. If not set
|
||||
the JWT used for login will be used to access the API.`,
|
||||
},
|
||||
"pem_keys": {
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Description: `Optional list of PEM-formated public keys or certificates
|
||||
used to verify the signatures of kubernetes service account
|
||||
JWTs. If a certificate is given, its public key will be
|
||||
extracted. Not every installation of Kuberentes exposes these keys.`,
|
||||
},
|
||||
},
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: b.pathConfigWrite(),
|
||||
|
@ -57,9 +64,10 @@ func (b *kubeAuthBackend) pathConfigRead() framework.OperationFunc {
|
|||
// Create a map of data to be returned
|
||||
resp := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"pem_keys": config.PEMKeys,
|
||||
"kubernetes_host": config.Host,
|
||||
"kubernetes_ca_cert": config.CACert,
|
||||
"token_reviewer_jwt": config.TokenReviewerJWT,
|
||||
"pem_keys": config.PEMKeys,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -82,11 +90,21 @@ func (b *kubeAuthBackend) pathConfigWrite() framework.OperationFunc {
|
|||
return logical.ErrorResponse("one of pem_keys or kubernetes_ca_cert must be set"), nil
|
||||
}
|
||||
|
||||
tokenReviewer := data.Get("token_reviewer_jwt").(string)
|
||||
if len(tokenReviewer) > 0 {
|
||||
// Validate it's a JWT
|
||||
_, err := jws.ParseJWT([]byte(tokenReviewer))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
config := &kubeConfig{
|
||||
PublicKeys: make([]interface{}, len(pemList)),
|
||||
PEMKeys: pemList,
|
||||
Host: host,
|
||||
CACert: caCert,
|
||||
TokenReviewerJWT: tokenReviewer,
|
||||
}
|
||||
|
||||
var err error
|
||||
|
@ -121,6 +139,8 @@ type kubeConfig struct {
|
|||
Host string `json:"host"`
|
||||
// CACert is the CA Cert to use to call into the kubernetes API
|
||||
CACert string `json:"ca_cert"`
|
||||
// TokenReviewJWT is the bearer to use during the TokenReview API call
|
||||
TokenReviewerJWT string `json:"token_reviewer_jwt"`
|
||||
}
|
||||
|
||||
// PasrsePublicKeyPEM is used to parse RSA and ECDSA public keys from PEMs
|
||||
|
|
|
@ -45,7 +45,7 @@ func pathLogin(b *kubeAuthBackend) *framework.Path {
|
|||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: b.pathLogin(),
|
||||
logical.PersonaLookaheadOperation: b.personaLookahead(),
|
||||
logical.AliasLookaheadOperation: b.aliasLookahead(),
|
||||
},
|
||||
|
||||
HelpSynopsis: pathLoginHelpSyn,
|
||||
|
@ -100,7 +100,7 @@ func (b *kubeAuthBackend) pathLogin() framework.OperationFunc {
|
|||
Auth: &logical.Auth{
|
||||
NumUses: role.NumUses,
|
||||
Period: role.Period,
|
||||
Persona: &logical.Persona{
|
||||
Alias: &logical.Alias{
|
||||
Name: serviceAccount.UID,
|
||||
},
|
||||
InternalData: map[string]interface{}{
|
||||
|
@ -134,9 +134,9 @@ func (b *kubeAuthBackend) pathLogin() framework.OperationFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// personaLookahead returns the persona object with the SA UID from the JWT
|
||||
// aliasLookahead returns the alias object with the SA UID from the JWT
|
||||
// Claims.
|
||||
func (b *kubeAuthBackend) personaLookahead() framework.OperationFunc {
|
||||
func (b *kubeAuthBackend) aliasLookahead() framework.OperationFunc {
|
||||
return func(req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
jwtStr := data.Get("jwt").(string)
|
||||
if len(jwtStr) == 0 {
|
||||
|
@ -156,7 +156,7 @@ func (b *kubeAuthBackend) personaLookahead() framework.OperationFunc {
|
|||
|
||||
return &logical.Response{
|
||||
Auth: &logical.Auth{
|
||||
Persona: &logical.Persona{
|
||||
Alias: &logical.Alias{
|
||||
Name: saUID,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICsDCCAhmgAwIBAgIJAOfUpFI2c2Y9MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTcwOTEyMDAzODU1WhcNMTcxMDEyMDAzODU1WjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
|
||||
gQDIuRPNO+X/6BwCriiV097TuN3wngX3k37LbmPe/i5gWRRxxOKN+9NBkqPkrZFK
|
||||
aNxAFRaHazMUNxKljICYKjs9zs/H6Oe6pOpkZ3HOGuxwNPbPRPDz8/nJgLLXPQUd
|
||||
zJket+YpPXE/5yoi7S5qceb5qz/mD8jOG0YCepusj9oheQIDAQABo4GnMIGkMB0G
|
||||
A1UdDgQWBBQBlWx0kNoBmGW4T9dUqv8c0KS/WjB1BgNVHSMEbjBsgBQBlWx0kNoB
|
||||
mGW4T9dUqv8c0KS/WqFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUt
|
||||
U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAOfUpFI2
|
||||
c2Y9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAZngST25nmzvmNvWu
|
||||
zHaOL7cmYLPzuvfGiJYPj/vCzG1fc8Tf9AUznFq7ssXWunURkJ4MM9pZSAfP9nXA
|
||||
pMWSxi9QJyYPrNAI3EMPXSiuQkDYussFJBfQ20/VjJ5KhwMbb9t3EP6bopYBcxb4
|
||||
zs9O4svzeBlPT40wXAhvom3zBd0=
|
||||
-----END CERTIFICATE-----
|
|
@ -1,15 +0,0 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXgIBAAKBgQDIuRPNO+X/6BwCriiV097TuN3wngX3k37LbmPe/i5gWRRxxOKN
|
||||
+9NBkqPkrZFKaNxAFRaHazMUNxKljICYKjs9zs/H6Oe6pOpkZ3HOGuxwNPbPRPDz
|
||||
8/nJgLLXPQUdzJket+YpPXE/5yoi7S5qceb5qz/mD8jOG0YCepusj9oheQIDAQAB
|
||||
AoGBAMEXMdJcDczZN6Docwh28cOQ8ogXLDxXOkFup0qMEIcFCqLLOPpHR5mr/Ffv
|
||||
FHaVW1OWNb79w/xtYlW5TLeU4LjE0Ej2KDHKWrCM2FN8U+7B621OX3sD2/3+bDgs
|
||||
Y0amFoBpGDuxIQ+6MVTAOi1sqrsocAaJi4HvglIgj9Bgc5n1AkEA/XilqA2e8VGq
|
||||
lAfypVi16iY82/3vEpSkZo26biAHAvFBhYPDU4pf5rJ3T61Kgyl2tgUWjm2cY+Ow
|
||||
V3dgk/SA+wJBAMq5trTudcmgnbIpbS/sjYRGgb8AkVOqB4bzo9IFC7RzYP46Pmge
|
||||
RCB6FBqsI9bpfyDLicyCbPn/PWVwdioQ5RsCQQCTQ1Ebfi5mDgiI0MVNA2lNjMG3
|
||||
HqWTqgCKBLXX3Yu1Te2/YHpPQwnMwstG42tzINfzkKk2PsCp2FNPve/Chj+ZAkAe
|
||||
5uxI7EicMZWYQORZ988iqLTCbs24WSTIl38TVp2QJj5UwoAc0vBDmxhRcIgODI3K
|
||||
a/xXZlJCUXwEaH46r1SdAkEA5ntS8X4tfKB6N1b3089FcbLLvKFLNzr5MSVJqwaW
|
||||
geHK0vrK9BAQmPEfsgSperZCbNgzbNSSFHO5lcEif1whaw==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -78,8 +78,16 @@ func (t *tokenReviewAPI) Review(jwt string) (*tokenReviewResult, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If we have a configured TokenReviewer JWT use it as the bearer, otherwise
|
||||
// try to use the passed in JWT.
|
||||
bearer := fmt.Sprintf("Bearer %s", jwt)
|
||||
if len(t.config.TokenReviewerJWT) > 0 {
|
||||
bearer = fmt.Sprintf("Bearer %s", t.config.TokenReviewerJWT)
|
||||
}
|
||||
|
||||
// Set the JWT as the Bearer token
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", jwt))
|
||||
req.Header.Set("Authorization", bearer)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
|
@ -104,12 +112,17 @@ func (t *tokenReviewAPI) Review(jwt string) (*tokenReviewResult, error) {
|
|||
return nil, errors.New("lookup failed: service account jwt not valid")
|
||||
}
|
||||
|
||||
// the username is of format: system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)
|
||||
// The username is of format: system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT)
|
||||
parts := strings.Split(r.Status.User.Username, ":")
|
||||
if len(parts) != 4 {
|
||||
return nil, errors.New("lookup failed: unexpected username format")
|
||||
}
|
||||
|
||||
// Validate the user that comes back from token review is a service account
|
||||
if parts[0] != "system" || parts[1] != "serviceaccount" {
|
||||
return nil, errors.New("lookup failed: username returned is not a service account")
|
||||
}
|
||||
|
||||
return &tokenReviewResult{
|
||||
Name: parts[3],
|
||||
Namespace: parts[2],
|
||||
|
|
|
@ -1147,10 +1147,16 @@
|
|||
"revisionTime": "2017-09-02T04:25:43Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "J/+RffHqbSdOeI82+ysAJruyO9w=",
|
||||
"checksumSHA1": "/11y5HSVYFHHjBUHUIt35qi6D/g=",
|
||||
"path": "github.com/hashicorp/vault-plugin-auth-gcp",
|
||||
"revision": "440e5e20278c115840fab1f27b7a9f99d405ebbd",
|
||||
"revisionTime": "2017-10-05T00:02:52Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "a/6XqbRHzvZ1ngOoGASIIIcmjwM=",
|
||||
"path": "github.com/hashicorp/vault-plugin-auth-gcp/plugin",
|
||||
"revision": "a807a8507e636e40403455258ed25954ec254cad",
|
||||
"revisionTime": "2017-09-15T19:03:59Z"
|
||||
"revision": "440e5e20278c115840fab1f27b7a9f99d405ebbd",
|
||||
"revisionTime": "2017-10-05T00:02:52Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "nrNcGdv/8Ut8ScFy3tQoY3dpQvs=",
|
||||
|
@ -1159,10 +1165,10 @@
|
|||
"revisionTime": "2017-09-15T19:03:59Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "U8kIY2Z/WO1nU+3g7wykzo20C+o=",
|
||||
"checksumSHA1": "/xje1EITZoa0tj7KqPof+3FG+og=",
|
||||
"path": "github.com/hashicorp/vault-plugin-auth-kubernetes",
|
||||
"revision": "e6ff3b4fefe641225a7a81013337b3b62027b3a0",
|
||||
"revisionTime": "2017-09-19T14:00:28Z"
|
||||
"revision": "7b79e81da4f5d56811fb7ddda078a96f7f950814",
|
||||
"revisionTime": "2017-10-05T00:02:34Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "ZhK6IO2XN81Y+3RAjTcVm1Ic7oU=",
|
||||
|
|
Loading…
Reference in New Issue