mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +00:00 
			
		
		
		
	github auth: use org id to verify creds (#13332)
* github auth: use org id to verify creds * add check for required org param; add test case * update UTs * add nil check for org * add changelog * fix typo in ut * set org ID if it is unset; add more ut coverage * add optional organization_id * move client instantiation * refactor parse URL; add UT for setting org ID * fix comment in UT * add nil check * don't update org name on change; return warning * refactor verifyCredentials * error when unable to fetch org ID on config write; add warnings * fix bug in log message * update UT and small refactor * update comments and log msg * use getter for org ID
This commit is contained in:
		 John-Michael Faircloth
					John-Michael Faircloth
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							9b86b8cf90
						
					
				
				
					commit
					524ded982b
				
			| @@ -7,6 +7,7 @@ import ( | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/google/go-github/github" | ||||
| 	"github.com/hashicorp/vault/sdk/framework" | ||||
| 	"github.com/hashicorp/vault/sdk/helper/tokenutil" | ||||
| 	"github.com/hashicorp/vault/sdk/logical" | ||||
| @@ -19,8 +20,12 @@ func pathConfig(b *backend) *framework.Path { | ||||
| 			"organization": { | ||||
| 				Type:        framework.TypeString, | ||||
| 				Description: "The organization users must be part of", | ||||
| 				Required:    true, | ||||
| 			}, | ||||
| 			"organization_id": { | ||||
| 				Type:        framework.TypeInt64, | ||||
| 				Description: "The ID of the organization users must be part of", | ||||
| 			}, | ||||
|  | ||||
| 			"base_url": { | ||||
| 				Type: framework.TypeString, | ||||
| 				Description: `The API endpoint to use. Useful if you | ||||
| @@ -55,6 +60,7 @@ API-compatible authentication server.`, | ||||
| } | ||||
|  | ||||
| func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||||
| 	var resp logical.Response | ||||
| 	c, err := b.Config(ctx, req.Storage) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -66,19 +72,47 @@ func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, dat | ||||
| 	if organizationRaw, ok := data.GetOk("organization"); ok { | ||||
| 		c.Organization = organizationRaw.(string) | ||||
| 	} | ||||
| 	if c.Organization == "" { | ||||
| 		return logical.ErrorResponse("organization is a required parameter"), nil | ||||
| 	} | ||||
|  | ||||
| 	if organizationRaw, ok := data.GetOk("organization_id"); ok { | ||||
| 		c.OrganizationID = organizationRaw.(int64) | ||||
| 	} | ||||
|  | ||||
| 	var parsedURL *url.URL | ||||
| 	if baseURLRaw, ok := data.GetOk("base_url"); ok { | ||||
| 		baseURL := baseURLRaw.(string) | ||||
| 		_, err := url.Parse(baseURL) | ||||
| 		if err != nil { | ||||
| 			return logical.ErrorResponse(fmt.Sprintf("Error parsing given base_url: %s", err)), nil | ||||
| 		} | ||||
| 		if !strings.HasSuffix(baseURL, "/") { | ||||
| 			baseURL += "/" | ||||
| 		} | ||||
| 		parsedURL, err = url.Parse(baseURL) | ||||
| 		if err != nil { | ||||
| 			return logical.ErrorResponse(fmt.Sprintf("error parsing given base_url: %s", err)), nil | ||||
| 		} | ||||
| 		c.BaseURL = baseURL | ||||
| 	} | ||||
|  | ||||
| 	if c.OrganizationID == 0 { | ||||
| 		client, err := b.Client("") | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		// ensure our client has the BaseURL if it was provided | ||||
| 		if parsedURL != nil { | ||||
| 			client.BaseURL = parsedURL | ||||
| 		} | ||||
|  | ||||
| 		// we want to set the Org ID in the config so we can use that to verify | ||||
| 		// the credentials on login | ||||
| 		err = c.setOrganizationID(ctx, client) | ||||
| 		if err != nil { | ||||
| 			errorMsg := fmt.Errorf("unable to fetch the organization_id, you must manually set it in the config: %s", err) | ||||
| 			b.Logger().Error(errorMsg.Error()) | ||||
| 			return nil, errorMsg | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := c.ParseTokenFields(req, data); err != nil { | ||||
| 		return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest | ||||
| 	} | ||||
| @@ -103,7 +137,11 @@ func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, dat | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return nil, nil | ||||
| 	if len(resp.Warnings) == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	return &resp, nil | ||||
| } | ||||
|  | ||||
| func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { | ||||
| @@ -116,8 +154,9 @@ func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, data | ||||
| 	} | ||||
|  | ||||
| 	d := map[string]interface{}{ | ||||
| 		"organization": config.Organization, | ||||
| 		"base_url":     config.BaseURL, | ||||
| 		"organization_id": config.OrganizationID, | ||||
| 		"organization":    config.Organization, | ||||
| 		"base_url":        config.BaseURL, | ||||
| 	} | ||||
| 	config.PopulateTokenData(d) | ||||
|  | ||||
| @@ -163,8 +202,25 @@ func (b *backend) Config(ctx context.Context, s logical.Storage) (*config, error | ||||
| type config struct { | ||||
| 	tokenutil.TokenParams | ||||
|  | ||||
| 	Organization string        `json:"organization" structs:"organization" mapstructure:"organization"` | ||||
| 	BaseURL      string        `json:"base_url" structs:"base_url" mapstructure:"base_url"` | ||||
| 	TTL          time.Duration `json:"ttl" structs:"ttl" mapstructure:"ttl"` | ||||
| 	MaxTTL       time.Duration `json:"max_ttl" structs:"max_ttl" mapstructure:"max_ttl"` | ||||
| 	OrganizationID int64         `json:"organization_id" structs:"organization_id" mapstructure:"organization_id"` | ||||
| 	Organization   string        `json:"organization" structs:"organization" mapstructure:"organization"` | ||||
| 	BaseURL        string        `json:"base_url" structs:"base_url" mapstructure:"base_url"` | ||||
| 	TTL            time.Duration `json:"ttl" structs:"ttl" mapstructure:"ttl"` | ||||
| 	MaxTTL         time.Duration `json:"max_ttl" structs:"max_ttl" mapstructure:"max_ttl"` | ||||
| } | ||||
|  | ||||
| func (c *config) setOrganizationID(ctx context.Context, client *github.Client) error { | ||||
| 	org, _, err := client.Organizations.Get(ctx, c.Organization) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	orgID := org.GetID() | ||||
| 	if orgID == 0 { | ||||
| 		return fmt.Errorf("organization_id not found for %s", c.Organization) | ||||
| 	} | ||||
|  | ||||
| 	c.OrganizationID = orgID | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user