updating azure plugin and deps (#4191)

This commit is contained in:
Chris Hoffman 2018-03-23 16:48:05 -04:00 committed by GitHub
parent 74452d7db7
commit 84ec79a93f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 280 additions and 89 deletions

61
vendor/github.com/coreos/go-oidc/code-of-conduct.md generated vendored Normal file
View file

@ -0,0 +1,61 @@
## CoreOS Community Code of Conduct
### Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of
fostering an open and welcoming community, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating
documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing others' private information, such as physical or electronic addresses, without explicit permission
* Other unethical or unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct. By adopting this Code of Conduct,
project maintainers commit themselves to fairly and consistently applying these
principles to every aspect of managing this project. Project maintainers who do
not follow or enforce the Code of Conduct may be permanently removed from the
project team.
This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting a project maintainer, Brandon Philips
<brandon.philips@coreos.com>, and/or Rithu John <rithu.john@coreos.com>.
This Code of Conduct is adapted from the Contributor Covenant
(http://contributor-covenant.org), version 1.2.0, available at
http://contributor-covenant.org/version/1/2/0/
### CoreOS Events Code of Conduct
CoreOS events are working conferences intended for professional networking and
collaboration in the CoreOS community. Attendees are expected to behave
according to professional standards and in accordance with their employers
policies on appropriate workplace behavior.
While at CoreOS events or related social networking opportunities, attendees
should not engage in discriminatory or offensive speech or actions including
but not limited to gender, sexuality, race, age, disability, or religion.
Speakers should be especially aware of these concerns.
CoreOS does not condone any statements by speakers contrary to these standards.
CoreOS reserves the right to deny entrance and/or eject from an event (without
refund) any individual found to be engaging in discriminatory or offensive
speech or actions.
Please bring any concerns to the immediate attention of designated on-site
staff, Brandon Philips <brandon.philips@coreos.com>, and/or Rithu John <rithu.john@coreos.com>.

View file

@ -23,6 +23,20 @@ import (
// updated. // updated.
const keysExpiryDelta = 30 * time.Second const keysExpiryDelta = 30 * time.Second
// NewRemoteKeySet returns a KeySet that can validate JSON web tokens by using HTTP
// GETs to fetch JSON web token sets hosted at a remote URL. This is automatically
// used by NewProvider using the URLs returned by OpenID Connect discovery, but is
// exposed for providers that don't support discovery or to prevent round trips to the
// discovery URL.
//
// The returned KeySet is a long lived verifier that caches keys based on cache-control
// headers. Reuse a common remote key set instead of creating new ones as needed.
//
// The behavior of the returned KeySet is undefined once the context is canceled.
func NewRemoteKeySet(ctx context.Context, jwksURL string) KeySet {
return newRemoteKeySet(ctx, jwksURL, time.Now)
}
func newRemoteKeySet(ctx context.Context, jwksURL string, now func() time.Time) *remoteKeySet { func newRemoteKeySet(ctx context.Context, jwksURL string, now func() time.Time) *remoteKeySet {
if now == nil { if now == nil {
now = time.Now now = time.Now
@ -79,6 +93,14 @@ func (i *inflight) result() ([]jose.JSONWebKey, error) {
return i.keys, i.err return i.keys, i.err
} }
func (r *remoteKeySet) VerifySignature(ctx context.Context, jwt string) ([]byte, error) {
jws, err := jose.ParseSigned(jwt)
if err != nil {
return nil, fmt.Errorf("oidc: malformed jwt: %v", err)
}
return r.verify(ctx, jws)
}
func (r *remoteKeySet) verify(ctx context.Context, jws *jose.JSONWebSignature) ([]byte, error) { func (r *remoteKeySet) verify(ctx context.Context, jws *jose.JSONWebSignature) ([]byte, error) {
// We don't support JWTs signed with multiple signatures. // We don't support JWTs signed with multiple signatures.
keyID := "" keyID := ""

View file

@ -3,9 +3,13 @@ package oidc
import ( import (
"context" "context"
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"hash"
"io/ioutil" "io/ioutil"
"mime" "mime"
"net/http" "net/http"
@ -31,6 +35,11 @@ const (
ScopeOfflineAccess = "offline_access" ScopeOfflineAccess = "offline_access"
) )
var (
errNoAtHash = errors.New("id token did not have an access token hash")
errInvalidAtHash = errors.New("access token hash does not match value in ID token")
)
// ClientContext returns a new Context that carries the provided HTTP client. // ClientContext returns a new Context that carries the provided HTTP client.
// //
// This method sets the same context key used by the golang.org/x/oauth2 package, // This method sets the same context key used by the golang.org/x/oauth2 package,
@ -64,7 +73,7 @@ type Provider struct {
// Raw claims returned by the server. // Raw claims returned by the server.
rawClaims []byte rawClaims []byte
remoteKeySet *remoteKeySet remoteKeySet KeySet
} }
type cachedKeys struct { type cachedKeys struct {
@ -120,7 +129,7 @@ func NewProvider(ctx context.Context, issuer string) (*Provider, error) {
tokenURL: p.TokenURL, tokenURL: p.TokenURL,
userInfoURL: p.UserInfoURL, userInfoURL: p.UserInfoURL,
rawClaims: body, rawClaims: body,
remoteKeySet: newRemoteKeySet(ctx, p.JWKSURL, time.Now), remoteKeySet: NewRemoteKeySet(ctx, p.JWKSURL),
}, nil }, nil
} }
@ -242,6 +251,14 @@ type IDToken struct {
// and it's the user's responsibility to ensure it contains a valid value. // and it's the user's responsibility to ensure it contains a valid value.
Nonce string Nonce string
// at_hash claim, if set in the ID token. Callers can verify an access token
// that corresponds to the ID token using the VerifyAccessToken method.
AccessTokenHash string
// signature algorithm used for ID token, needed to compute a verification hash of an
// access token
sigAlgorithm string
// Raw payload of the id_token. // Raw payload of the id_token.
claims []byte claims []byte
} }
@ -267,6 +284,34 @@ func (i *IDToken) Claims(v interface{}) error {
return json.Unmarshal(i.claims, v) return json.Unmarshal(i.claims, v)
} }
// VerifyAccessToken verifies that the hash of the access token that corresponds to the iD token
// matches the hash in the id token. It returns an error if the hashes don't match.
// It is the caller's responsibility to ensure that the optional access token hash is present for the ID token
// before calling this method. See https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken
func (i *IDToken) VerifyAccessToken(accessToken string) error {
if i.AccessTokenHash == "" {
return errNoAtHash
}
var h hash.Hash
switch i.sigAlgorithm {
case RS256, ES256, PS256:
h = sha256.New()
case RS384, ES384, PS384:
h = sha512.New384()
case RS512, ES512, PS512:
h = sha512.New()
default:
return fmt.Errorf("oidc: unsupported signing algorithm %q", i.sigAlgorithm)
}
h.Write([]byte(accessToken)) // hash documents that Write will never return an error
sum := h.Sum(nil)[:h.Size()/2]
actual := base64.RawURLEncoding.EncodeToString(sum)
if actual != i.AccessTokenHash {
return errInvalidAtHash
}
return nil
}
type idToken struct { type idToken struct {
Issuer string `json:"iss"` Issuer string `json:"iss"`
Subject string `json:"sub"` Subject string `json:"sub"`
@ -274,6 +319,7 @@ type idToken struct {
Expiry jsonTime `json:"exp"` Expiry jsonTime `json:"exp"`
IssuedAt jsonTime `json:"iat"` IssuedAt jsonTime `json:"iat"`
Nonce string `json:"nonce"` Nonce string `json:"nonce"`
AtHash string `json:"at_hash"`
} }
type audience []string type audience []string

View file

@ -11,6 +11,6 @@ LINTABLE=$( go list -tags=golint -f '
go test -v -i -race github.com/coreos/go-oidc/... go test -v -i -race github.com/coreos/go-oidc/...
go test -v -race github.com/coreos/go-oidc/... go test -v -race github.com/coreos/go-oidc/...
golint $LINTABLE golint -set_exit_status $LINTABLE
go vet github.com/coreos/go-oidc/... go vet github.com/coreos/go-oidc/...
go build -v ./example/... go build -v ./example/...

View file

@ -19,19 +19,54 @@ const (
issuerGoogleAccountsNoScheme = "accounts.google.com" issuerGoogleAccountsNoScheme = "accounts.google.com"
) )
// keySet is an interface that lets us stub out verification policies for // KeySet is a set of publc JSON Web Keys that can be used to validate the signature
// testing. Outside of testing, it's always backed by a remoteKeySet. // of JSON web tokens. This is expected to be backed by a remote key set through
type keySet interface { // provider metadata discovery or an in-memory set of keys delivered out-of-band.
verify(ctx context.Context, jws *jose.JSONWebSignature) ([]byte, error) type KeySet interface {
// VerifySignature parses the JSON web token, verifies the signature, and returns
// the raw payload. Header and claim fields are validated by other parts of the
// package. For example, the KeySet does not need to check values such as signature
// algorithm, issuer, and audience since the IDTokenVerifier validates these values
// independently.
//
// If VerifySignature makes HTTP requests to verify the token, it's expected to
// use any HTTP client associated with the context through ClientContext.
VerifySignature(ctx context.Context, jwt string) (payload []byte, err error)
} }
// IDTokenVerifier provides verification for ID Tokens. // IDTokenVerifier provides verification for ID Tokens.
type IDTokenVerifier struct { type IDTokenVerifier struct {
keySet keySet keySet KeySet
config *Config config *Config
issuer string issuer string
} }
// NewVerifier returns a verifier manually constructed from a key set and issuer URL.
//
// It's easier to use provider discovery to construct an IDTokenVerifier than creating
// one directly. This method is intended to be used with provider that don't support
// metadata discovery, or avoiding round trips when the key set URL is already known.
//
// This constructor can be used to create a verifier directly using the issuer URL and
// JSON Web Key Set URL without using discovery:
//
// keySet := oidc.NewRemoteKeySet(ctx, "https://www.googleapis.com/oauth2/v3/certs")
// verifier := oidc.NewVerifier("https://accounts.google.com", keySet, config)
//
// Since KeySet is an interface, this constructor can also be used to supply custom
// public key sources. For example, if a user wanted to supply public keys out-of-band
// and hold them statically in-memory:
//
// // Custom KeySet implementation.
// keySet := newStatisKeySet(publicKeys...)
//
// // Verifier uses the custom KeySet implementation.
// verifier := oidc.NewVerifier("https://auth.example.com", keySet, config)
//
func NewVerifier(issuerURL string, keySet KeySet, config *Config) *IDTokenVerifier {
return &IDTokenVerifier{keySet: keySet, config: config, issuer: issuerURL}
}
// Config is the configuration for an IDTokenVerifier. // Config is the configuration for an IDTokenVerifier.
type Config struct { type Config struct {
// Expected audience of the token. For a majority of the cases this is expected to be // Expected audience of the token. For a majority of the cases this is expected to be
@ -59,21 +94,7 @@ type Config struct {
// The returned IDTokenVerifier is tied to the Provider's context and its behavior is // The returned IDTokenVerifier is tied to the Provider's context and its behavior is
// undefined once the Provider's context is canceled. // undefined once the Provider's context is canceled.
func (p *Provider) Verifier(config *Config) *IDTokenVerifier { func (p *Provider) Verifier(config *Config) *IDTokenVerifier {
return NewVerifier(p.issuer, p.remoteKeySet, config)
return newVerifier(p.remoteKeySet, config, p.issuer)
}
func newVerifier(keySet keySet, config *Config, issuer string) *IDTokenVerifier {
// If SupportedSigningAlgs is empty defaults to only support RS256.
if len(config.SupportedSigningAlgs) == 0 {
config.SupportedSigningAlgs = []string{RS256}
}
return &IDTokenVerifier{
keySet: keySet,
config: config,
issuer: issuer,
}
} }
func parseJWT(p string) ([]byte, error) { func parseJWT(p string) ([]byte, error) {
@ -135,13 +156,14 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
} }
t := &IDToken{ t := &IDToken{
Issuer: token.Issuer, Issuer: token.Issuer,
Subject: token.Subject, Subject: token.Subject,
Audience: []string(token.Audience), Audience: []string(token.Audience),
Expiry: time.Time(token.Expiry), Expiry: time.Time(token.Expiry),
IssuedAt: time.Time(token.IssuedAt), IssuedAt: time.Time(token.IssuedAt),
Nonce: token.Nonce, Nonce: token.Nonce,
claims: payload, AccessTokenHash: token.AtHash,
claims: payload,
} }
// Check issuer. // Check issuer.
@ -165,7 +187,7 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
return nil, fmt.Errorf("oidc: expected audience %q got %q", v.config.ClientID, t.Audience) return nil, fmt.Errorf("oidc: expected audience %q got %q", v.config.ClientID, t.Audience)
} }
} else { } else {
return nil, fmt.Errorf("oidc: Invalid configuration. ClientID must be provided or SkipClientIDCheck must be set.") return nil, fmt.Errorf("oidc: invalid configuration, clientID must be provided or SkipClientIDCheck must be set")
} }
} }
@ -190,11 +212,18 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
} }
sig := jws.Signatures[0] sig := jws.Signatures[0]
if len(v.config.SupportedSigningAlgs) != 0 && !contains(v.config.SupportedSigningAlgs, sig.Header.Algorithm) { supportedSigAlgs := v.config.SupportedSigningAlgs
return nil, fmt.Errorf("oidc: id token signed with unsupported algorithm, expected %q got %q", v.config.SupportedSigningAlgs, sig.Header.Algorithm) if len(supportedSigAlgs) == 0 {
supportedSigAlgs = []string{RS256}
} }
gotPayload, err := v.keySet.verify(ctx, jws) if !contains(supportedSigAlgs, sig.Header.Algorithm) {
return nil, fmt.Errorf("oidc: id token signed with unsupported algorithm, expected %q got %q", supportedSigAlgs, sig.Header.Algorithm)
}
t.sigAlgorithm = sig.Header.Algorithm
gotPayload, err := v.keySet.VerifySignature(ctx, rawIDToken)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to verify signature: %v", err) return nil, fmt.Errorf("failed to verify signature: %v", err)
} }

View file

@ -2,8 +2,11 @@ package plugin
import ( import (
"context" "context"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil"
"net/http"
"os" "os"
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2017-12-01/compute"
@ -11,10 +14,9 @@ import (
"github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/go-autorest/autorest/azure/auth" "github.com/Azure/go-autorest/autorest/azure/auth"
oidc "github.com/coreos/go-oidc" oidc "github.com/coreos/go-oidc"
) "github.com/hashicorp/errwrap"
cleanhttp "github.com/hashicorp/go-cleanhttp"
const ( "golang.org/x/oauth2"
issuerBaseURI = "https://sts.windows.net"
) )
type computeClient interface { type computeClient interface {
@ -30,39 +32,66 @@ type provider interface {
ComputeClient(subscriptionID string) computeClient ComputeClient(subscriptionID string) computeClient
} }
var _ provider = &azureProvider{}
type azureProvider struct { type azureProvider struct {
settings *azureSettings oidcVerifier *oidc.IDTokenVerifier
oidcProvider *oidc.Provider
authorizer autorest.Authorizer authorizer autorest.Authorizer
httpClient *http.Client
} }
func NewAzureProvider(config *azureConfig) (*azureProvider, error) { type oidcDiscoveryInfo struct {
Issuer string `json:"issuer"`
JWKSURL string `json:"jwks_uri"`
}
func newAzureProvider(config *azureConfig) (*azureProvider, error) {
httpClient := cleanhttp.DefaultClient()
settings, err := getAzureSettings(config) settings, err := getAzureSettings(config)
if err != nil { if err != nil {
return nil, err return nil, err
} }
issuer := fmt.Sprintf("%s/%s/", issuerBaseURI, settings.TenantID) // In many OIDC providers, the discovery endpoint matches the issuer. For Azure AD, the discovery
oidcProvider, err := oidc.NewProvider(context.Background(), issuer) // endpoint is the AD endpoint which does not match the issuer defined in the discovery payload. This
// makes a request to the discovery URL to determine the issuer and key set information to configure
// the OIDC verifier
discoveryURL := fmt.Sprintf("%s%s/.well-known/openid-configuration", settings.Environment.ActiveDirectoryEndpoint, settings.TenantID)
resp, err := httpClient.Get(discoveryURL)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer resp.Body.Close()
provider := &azureProvider{ body, err := ioutil.ReadAll(resp.Body)
settings: settings, if err != nil {
oidcProvider: oidcProvider, return nil, errwrap.Wrapf("unable to read response body: {{err}}", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s: %s", resp.Status, body)
}
var discoveryInfo oidcDiscoveryInfo
if err := json.Unmarshal(body, &discoveryInfo); err != nil {
return nil, errwrap.Wrapf("unable to unmarshal discovery url: {{err}}", err)
} }
// OAuth2 client for querying VM data // Create a remote key set from the discovery endpoint
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, httpClient)
remoteKeySet := oidc.NewRemoteKeySet(ctx, discoveryInfo.JWKSURL)
verifierConfig := &oidc.Config{
ClientID: settings.Resource,
SupportedSigningAlgs: []string{oidc.RS256},
}
oidcVerifier := oidc.NewVerifier(discoveryInfo.Issuer, remoteKeySet, verifierConfig)
// Create an OAuth2 client for retrieving VM data
var authorizer autorest.Authorizer
switch { switch {
// Use environment/config first // Use environment/config first
case settings.ClientSecret != "": case settings.ClientSecret != "":
config := auth.NewClientCredentialsConfig(settings.ClientID, settings.ClientSecret, settings.TenantID) config := auth.NewClientCredentialsConfig(settings.ClientID, settings.ClientSecret, settings.TenantID)
config.AADEndpoint = settings.Environment.ActiveDirectoryEndpoint config.AADEndpoint = settings.Environment.ActiveDirectoryEndpoint
config.Resource = settings.Environment.ResourceManagerEndpoint config.Resource = settings.Environment.ResourceManagerEndpoint
provider.authorizer, err = config.Authorizer() authorizer, err = config.Authorizer()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -70,25 +99,27 @@ func NewAzureProvider(config *azureConfig) (*azureProvider, error) {
default: default:
config := auth.NewMSIConfig() config := auth.NewMSIConfig()
config.Resource = settings.Environment.ResourceManagerEndpoint config.Resource = settings.Environment.ResourceManagerEndpoint
provider.authorizer, err = config.Authorizer() authorizer, err = config.Authorizer()
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
return provider, nil
return &azureProvider{
authorizer: authorizer,
oidcVerifier: oidcVerifier,
httpClient: httpClient,
}, nil
} }
func (p *azureProvider) Verifier() tokenVerifier { func (p *azureProvider) Verifier() tokenVerifier {
verifierConfig := &oidc.Config{ return p.oidcVerifier
ClientID: p.settings.Resource,
SupportedSigningAlgs: []string{oidc.RS256},
}
return p.oidcProvider.Verifier(verifierConfig)
} }
func (p *azureProvider) ComputeClient(subscriptionID string) computeClient { func (p *azureProvider) ComputeClient(subscriptionID string) computeClient {
client := compute.NewVirtualMachinesClient(subscriptionID) client := compute.NewVirtualMachinesClient(subscriptionID)
client.Authorizer = p.authorizer client.Authorizer = p.authorizer
client.Sender = p.httpClient
return client return client
} }

View file

@ -2,10 +2,8 @@ package plugin
import ( import (
"context" "context"
"net/http"
"sync" "sync"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/vault/logical" "github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework" "github.com/hashicorp/vault/logical/framework"
) )
@ -23,8 +21,7 @@ type azureAuthBackend struct {
l sync.RWMutex l sync.RWMutex
provider provider provider provider
httpClient *http.Client
} }
func Backend(c *logical.BackendConfig) *azureAuthBackend { func Backend(c *logical.BackendConfig) *azureAuthBackend {
@ -51,7 +48,6 @@ func Backend(c *logical.BackendConfig) *azureAuthBackend {
pathsRole(b), pathsRole(b),
), ),
} }
b.httpClient = cleanhttp.DefaultClient()
return b return b
} }
@ -81,7 +77,7 @@ func (b *azureAuthBackend) getProvider(config *azureConfig) (provider, error) {
return b.provider, nil return b.provider, nil
} }
provider, err := NewAzureProvider(config) provider, err := newAzureProvider(config)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -199,32 +199,32 @@ func (b *azureAuthBackend) verifyResource(ctx context.Context, subscriptionID, r
// Ensure the principal id for the VM matches the verified token OID // Ensure the principal id for the VM matches the verified token OID
if vm.Identity == nil { if vm.Identity == nil {
return fmt.Errorf("vm client did not return identity information") return errors.New("vm client did not return identity information")
} }
if vm.Identity.PrincipalID == nil { if vm.Identity.PrincipalID == nil {
return fmt.Errorf("vm principal id is empty") return errors.New("vm principal id is empty")
} }
if to.String(vm.Identity.PrincipalID) != claims.ObjectID { if to.String(vm.Identity.PrincipalID) != claims.ObjectID {
return fmt.Errorf("token object id does not match virtual machine principal id") return errors.New("token object id does not match virtual machine principal id")
} }
// Check bound subsriptions // Check bound subsriptions
if len(role.BoundSubscriptionsIDs) > 0 && !strutil.StrListContains(role.BoundSubscriptionsIDs, subscriptionID) { if len(role.BoundSubscriptionsIDs) > 0 && !strutil.StrListContains(role.BoundSubscriptionsIDs, subscriptionID) {
return fmt.Errorf("subscription not authoirzed") return errors.New("subscription not authorized")
} }
// Check bound resource groups // Check bound resource groups
if len(role.BoundResourceGroups) > 0 && !strutil.StrListContains(role.BoundResourceGroups, resourceGroupName) { if len(role.BoundResourceGroups) > 0 && !strutil.StrListContains(role.BoundResourceGroups, resourceGroupName) {
return fmt.Errorf("resource group not authoirzed") return errors.New("resource group not authorized")
} }
// Check bound locations // Check bound locations
if len(role.BoundLocations) > 0 { if len(role.BoundLocations) > 0 {
if vm.Location == nil { if vm.Location == nil {
return fmt.Errorf("vm location is empty") return errors.New("vm location is empty")
} }
if !strutil.StrListContains(role.BoundLocations, to.String(vm.Location)) { if !strutil.StrListContains(role.BoundLocations, to.String(vm.Location)) {
return fmt.Errorf("token object id does not match virtual machine principal id") return errors.New("location not authorized")
} }
} }
@ -234,13 +234,13 @@ func (b *azureAuthBackend) verifyResource(ctx context.Context, subscriptionID, r
func (b *azureAuthBackend) pathLoginRenew(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { func (b *azureAuthBackend) pathLoginRenew(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
roleName := req.Auth.InternalData["role"].(string) roleName := req.Auth.InternalData["role"].(string)
if roleName == "" { if roleName == "" {
return nil, fmt.Errorf("failed to fetch role_name during renewal") return nil, errors.New("failed to fetch role_name during renewal")
} }
// Ensure that the Role still exists. // Ensure that the Role still exists.
role, err := b.role(ctx, req.Storage, roleName) role, err := b.role(ctx, req.Storage, roleName)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to validate role %s during renewal:%s", roleName, err) return nil, errwrap.Wrapf(fmt.Sprintf("failed to validate role %s during renewal: {{err}}", roleName), err)
} }
if role == nil { if role == nil {
return nil, fmt.Errorf("role %s does not exist during renewal", roleName) return nil, fmt.Errorf("role %s does not exist during renewal", roleName)

View file

@ -3,6 +3,7 @@ package plugin
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -57,24 +58,29 @@ duration specified by this value. At each renewal, the token's
TTL will be set to the value of this parameter.`, TTL will be set to the value of this parameter.`,
}, },
"bound_subscription_ids": &framework.FieldSchema{ "bound_subscription_ids": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice, Type: framework.TypeCommaStringSlice,
Description: ``, Description: `Comma-separated list of subscription ids that login
is restricted to.`,
}, },
"bound_resource_groups": &framework.FieldSchema{ "bound_resource_groups": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice, Type: framework.TypeCommaStringSlice,
Description: ``, Description: `Comma-separated list of resource groups that login
is restricted to.`,
}, },
"bound_group_ids": &framework.FieldSchema{ "bound_group_ids": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice, Type: framework.TypeCommaStringSlice,
Description: ``, Description: `Comma-separated list of group ids that login
is restricted to.`,
}, },
"bound_service_principal_ids": &framework.FieldSchema{ "bound_service_principal_ids": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice, Type: framework.TypeCommaStringSlice,
Description: ``, Description: `Comma-separated list of service principal ids that login
is restricted to.`,
}, },
"bound_locations": &framework.FieldSchema{ "bound_locations": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice, Type: framework.TypeCommaStringSlice,
Description: ``, Description: `Comma-separated list of locations that login
is restricted to.`,
}, },
}, },
ExistenceCheck: b.pathRoleExistenceCheck, ExistenceCheck: b.pathRoleExistenceCheck,
@ -226,7 +232,7 @@ func (b *azureAuthBackend) pathRoleCreateUpdate(ctx context.Context, req *logica
// Create a new entry object if this is a CreateOperation // Create a new entry object if this is a CreateOperation
if role == nil { if role == nil {
if req.Operation == logical.UpdateOperation { if req.Operation == logical.UpdateOperation {
return nil, fmt.Errorf("role entry not found during update operation") return nil, errors.New("role entry not found during update operation")
} }
role = new(azureRole) role = new(azureRole)
} }

12
vendor/vendor.json vendored
View file

@ -643,10 +643,10 @@
"revisionTime": "2018-02-10T00:12:50Z" "revisionTime": "2018-02-10T00:12:50Z"
}, },
{ {
"checksumSHA1": "8o2JlMI+LchFOAR1uGZ3u6cROkY=", "checksumSHA1": "b6LGjzkSCWdrqH6dnS/Bf+BfdPU=",
"path": "github.com/coreos/go-oidc", "path": "github.com/coreos/go-oidc",
"revision": "a93f71fdfe73d2c0f5413c0565eea0af6523a6df", "revision": "065b426bd41667456c1a924468f507673629c46b",
"revisionTime": "2017-10-02T15:50:02Z" "revisionTime": "2018-01-17T17:01:38Z"
}, },
{ {
"checksumSHA1": "97BsbXOiZ8+Kr+LIuZkQFtSj7H4=", "checksumSHA1": "97BsbXOiZ8+Kr+LIuZkQFtSj7H4=",
@ -1279,10 +1279,10 @@
"revisionTime": "2018-02-03T00:31:27Z" "revisionTime": "2018-02-03T00:31:27Z"
}, },
{ {
"checksumSHA1": "LmozvTcHq18DkRN7aloRXug7Yqg=", "checksumSHA1": "C6sgT2K7ZAv4y/MFMWppVs7oqTM=",
"path": "github.com/hashicorp/vault-plugin-auth-azure/plugin", "path": "github.com/hashicorp/vault-plugin-auth-azure/plugin",
"revision": "ba506e5d0aae1d115c2b5ad4ea8d3f06be77b45a", "revision": "29767bb64e3fd21c7661a5008aa62a2eda1aebb8",
"revisionTime": "2018-03-21T20:06:11Z" "revisionTime": "2018-03-23T20:42:11Z"
}, },
{ {
"checksumSHA1": "xApm6AbAzE3wMLMaozaZ53pb7AU=", "checksumSHA1": "xApm6AbAzE3wMLMaozaZ53pb7AU=",