func respondLogical(w http.ResponseWriter, r *http.Request, path string, dataOnly bool, resp *logical.Response) { var httpResp interface{} if resp != nil { if resp.Redirect != "" { // If we have a redirect, redirect! We use a 307 code // because we don't actually know if its permanent. http.Redirect(w, r, resp.Redirect, 307) return } if dataOnly { respondOk(w, resp.Data) return } // Check if this is a raw response if _, ok := resp.Data[logical.HTTPContentType]; ok { respondRaw(w, r, path, resp) return } logicalResp := &LogicalResponse{ Data: resp.Data, Warnings: resp.Warnings(), } if resp.Secret != nil { logicalResp.LeaseID = resp.Secret.LeaseID logicalResp.Renewable = resp.Secret.Renewable logicalResp.LeaseDuration = int(resp.Secret.TTL.Seconds()) } // If we have authentication information, then // set up the result structure. if resp.Auth != nil { logicalResp.Auth = &Auth{ ClientToken: resp.Auth.ClientToken, Accessor: resp.Auth.Accessor, Policies: resp.Auth.Policies, Metadata: resp.Auth.Metadata, LeaseDuration: int(resp.Auth.TTL.Seconds()), Renewable: resp.Auth.Renewable, } } httpResp = logicalResp } // Respond respondOk(w, httpResp) }
// pathRoleCreateUpdate is used to associate Vault policies to a given AMI ID. func (b *backend) pathRoleCreateUpdate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { roleName := strings.ToLower(data.Get("role").(string)) if roleName == "" { return logical.ErrorResponse("missing role"), nil } b.roleMutex.Lock() defer b.roleMutex.Unlock() roleEntry, err := b.nonLockedAWSRole(req.Storage, roleName) if err != nil { return nil, err } if roleEntry == nil { roleEntry = &awsRoleEntry{} } // Fetch and set the bound parameters. There can't be default values // for these. if boundAmiIDRaw, ok := data.GetOk("bound_ami_id"); ok { roleEntry.BoundAmiID = boundAmiIDRaw.(string) } if boundAccountIDRaw, ok := data.GetOk("bound_account_id"); ok { roleEntry.BoundAccountID = boundAccountIDRaw.(string) } if boundIamRoleARNRaw, ok := data.GetOk("bound_iam_role_arn"); ok { roleEntry.BoundIamRoleARN = boundIamRoleARNRaw.(string) } if boundIamInstanceProfileARNRaw, ok := data.GetOk("bound_iam_instance_profile_arn"); ok { roleEntry.BoundIamInstanceProfileARN = boundIamInstanceProfileARNRaw.(string) } // Ensure that at least one bound is set on the role switch { case roleEntry.BoundAccountID != "": case roleEntry.BoundAmiID != "": case roleEntry.BoundIamInstanceProfileARN != "": case roleEntry.BoundIamRoleARN != "": default: return logical.ErrorResponse("at least be one bound parameter should be specified on the role"), nil } policiesStr, ok := data.GetOk("policies") if ok { roleEntry.Policies = policyutil.ParsePolicies(policiesStr.(string)) } else if req.Operation == logical.CreateOperation { roleEntry.Policies = []string{"default"} } disallowReauthenticationBool, ok := data.GetOk("disallow_reauthentication") if ok { roleEntry.DisallowReauthentication = disallowReauthenticationBool.(bool) } else if req.Operation == logical.CreateOperation { roleEntry.DisallowReauthentication = data.Get("disallow_reauthentication").(bool) } allowInstanceMigrationBool, ok := data.GetOk("allow_instance_migration") if ok { roleEntry.AllowInstanceMigration = allowInstanceMigrationBool.(bool) } else if req.Operation == logical.CreateOperation { roleEntry.AllowInstanceMigration = data.Get("allow_instance_migration").(bool) } var resp logical.Response ttlRaw, ok := data.GetOk("ttl") if ok { ttl := time.Duration(ttlRaw.(int)) * time.Second defaultLeaseTTL := b.System().DefaultLeaseTTL() if ttl > defaultLeaseTTL { resp.AddWarning(fmt.Sprintf("Given ttl of %d seconds greater than current mount/system default of %d seconds; ttl will be capped at login time", ttl/time.Second, defaultLeaseTTL/time.Second)) } roleEntry.TTL = ttl } else if req.Operation == logical.CreateOperation { roleEntry.TTL = time.Duration(data.Get("ttl").(int)) * time.Second } maxTTLInt, ok := data.GetOk("max_ttl") if ok { maxTTL := time.Duration(maxTTLInt.(int)) * time.Second systemMaxTTL := b.System().MaxLeaseTTL() if maxTTL > systemMaxTTL { resp.AddWarning(fmt.Sprintf("Given max_ttl of %d seconds greater than current mount/system default of %d seconds; max_ttl will be capped at login time", maxTTL/time.Second, systemMaxTTL/time.Second)) } if maxTTL < time.Duration(0) { return logical.ErrorResponse("max_ttl cannot be negative"), nil } roleEntry.MaxTTL = maxTTL } else if req.Operation == logical.CreateOperation { roleEntry.MaxTTL = time.Duration(data.Get("max_ttl").(int)) * time.Second } if roleEntry.MaxTTL != 0 && roleEntry.MaxTTL < roleEntry.TTL { return logical.ErrorResponse("ttl should be shorter than max_ttl"), nil } roleTagStr, ok := data.GetOk("role_tag") if ok { roleEntry.RoleTag = roleTagStr.(string) // There is a limit of 127 characters on the tag key for AWS EC2 instances. // Complying to that requirement, do not allow the value of 'key' to be more than that. if len(roleEntry.RoleTag) > 127 { return logical.ErrorResponse("length of role tag exceeds the EC2 key limit of 127 characters"), nil } } else if req.Operation == logical.CreateOperation { roleEntry.RoleTag = data.Get("role_tag").(string) } if roleEntry.HMACKey == "" { roleEntry.HMACKey, err = uuid.GenerateUUID() if err != nil { return nil, fmt.Errorf("failed to generate role HMAC key: %v", err) } } if err := b.nonLockedSetAWSRole(req.Storage, roleName, roleEntry); err != nil { return nil, err } if len(resp.Warnings()) == 0 { return nil, nil } return &resp, nil }
// pathRoleCreateUpdate is used to associate Vault policies to a given AMI ID. func (b *backend) pathRoleCreateUpdate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { roleName := strings.ToLower(data.Get("role").(string)) if roleName == "" { return logical.ErrorResponse("missing role"), nil } b.roleMutex.Lock() defer b.roleMutex.Unlock() roleEntry, err := b.nonLockedAWSRole(req.Storage, roleName) if err != nil { return nil, err } if roleEntry == nil { roleEntry = &awsRoleEntry{} } // Set the bound parameters only if they are supplied. // There are no default values for bound parameters. boundAmiIDStr, ok := data.GetOk("bound_ami_id") if ok { roleEntry.BoundAmiID = boundAmiIDStr.(string) } boundIamARNStr, ok := data.GetOk("bound_iam_role_arn") if ok { roleEntry.BoundIamARN = boundIamARNStr.(string) } // At least one bound parameter should be set. Currently, only // 'bound_ami_id' and 'bound_iam_role_arn' are supported. Check if one of them is set. if roleEntry.BoundAmiID == "" { // check if an IAM Role ARN was provided instead of an AMI ID if roleEntry.BoundIamARN == "" { return logical.ErrorResponse("role is not bounded to any resource; set bound_ami_id or bount_iam_role_arn"), nil } } policiesStr, ok := data.GetOk("policies") if ok { roleEntry.Policies = policyutil.ParsePolicies(policiesStr.(string)) } else if req.Operation == logical.CreateOperation { roleEntry.Policies = []string{"default"} } disallowReauthenticationBool, ok := data.GetOk("disallow_reauthentication") if ok { roleEntry.DisallowReauthentication = disallowReauthenticationBool.(bool) } else if req.Operation == logical.CreateOperation { roleEntry.DisallowReauthentication = data.Get("disallow_reauthentication").(bool) } allowInstanceMigrationBool, ok := data.GetOk("allow_instance_migration") if ok { roleEntry.AllowInstanceMigration = allowInstanceMigrationBool.(bool) } else if req.Operation == logical.CreateOperation { roleEntry.AllowInstanceMigration = data.Get("allow_instance_migration").(bool) } var resp logical.Response maxTTLInt, ok := data.GetOk("max_ttl") if ok { maxTTL := time.Duration(maxTTLInt.(int)) * time.Second systemMaxTTL := b.System().MaxLeaseTTL() if maxTTL > systemMaxTTL { resp.AddWarning(fmt.Sprintf("Given TTL of %d seconds greater than current mount/system default of %d seconds; TTL will be capped at login time", maxTTL/time.Second, systemMaxTTL/time.Second)) } if maxTTL < time.Duration(0) { return logical.ErrorResponse("max_ttl cannot be negative"), nil } roleEntry.MaxTTL = maxTTL } else if req.Operation == logical.CreateOperation { roleEntry.MaxTTL = time.Duration(data.Get("max_ttl").(int)) * time.Second } roleTagStr, ok := data.GetOk("role_tag") if ok { roleEntry.RoleTag = roleTagStr.(string) // There is a limit of 127 characters on the tag key for AWS EC2 instances. // Complying to that requirement, do not allow the value of 'key' to be more than that. if len(roleEntry.RoleTag) > 127 { return logical.ErrorResponse("length of role tag exceeds the EC2 key limit of 127 characters"), nil } } else if req.Operation == logical.CreateOperation { roleEntry.RoleTag = data.Get("role_tag").(string) } if roleEntry.HMACKey == "" { roleEntry.HMACKey, err = uuid.GenerateUUID() if err != nil { return nil, fmt.Errorf("failed to generate role HMAC key: %v", err) } } entry, err := logical.StorageEntryJSON("role/"+roleName, roleEntry) if err != nil { return nil, err } if err := req.Storage.Put(entry); err != nil { return nil, err } if len(resp.Warnings()) == 0 { return nil, nil } return &resp, nil }