func respondCommon(w http.ResponseWriter, resp *logical.Response, err error) bool { if resp == nil { return false } if resp.IsError() { var statusCode int switch err { case logical.ErrPermissionDenied: statusCode = http.StatusForbidden case logical.ErrUnsupportedOperation: statusCode = http.StatusMethodNotAllowed case logical.ErrUnsupportedPath: statusCode = http.StatusNotFound case logical.ErrInvalidRequest: statusCode = http.StatusBadRequest default: statusCode = http.StatusBadRequest } err := fmt.Errorf("%s", resp.Data["error"].(string)) respondError(w, statusCode, err) return true } return false }
func TestAppRole_RoleList(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) createRole(t, b, storage, "role1", "a,b") createRole(t, b, storage, "role2", "c,d") createRole(t, b, storage, "role3", "e,f") createRole(t, b, storage, "role4", "g,h") createRole(t, b, storage, "role5", "i,j") listReq := &logical.Request{ Operation: logical.ListOperation, Path: "role", Storage: storage, } resp, err = b.HandleRequest(listReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } actual := resp.Data["keys"].([]string) expected := []string{"role1", "role2", "role3", "role4", "role5"} if !policyutil.EquivalentPolicies(actual, expected) { t.Fatalf("bad: listed roles: expected:%s\nactual:%s", expected, actual) } }
func (b *PassthroughBackend) handleRead( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { // Read the path out, err := req.Storage.Get(req.Path) if err != nil { return nil, fmt.Errorf("read failed: %v", err) } // Fast-path the no data case if out == nil { return nil, nil } // Decode the data var rawData map[string]interface{} if err := json.Unmarshal(out.Value, &rawData); err != nil { return nil, fmt.Errorf("json decoding failed: %v", err) } var resp *logical.Response if b.generateLeases { // Generate the response resp = b.Secret("generic").Response(rawData, nil) resp.Secret.Renewable = false } else { resp = &logical.Response{ Secret: &logical.Secret{}, Data: rawData, } } // Check if there is a ttl key var ttl string ttl, _ = rawData["ttl"].(string) if len(ttl) == 0 { ttl, _ = rawData["lease"].(string) } ttlDuration := b.System().DefaultLeaseTTL() if len(ttl) != 0 { parsedDuration, err := time.ParseDuration(ttl) if err != nil { resp.AddWarning(fmt.Sprintf("failed to parse stored ttl '%s' for entry; using default", ttl)) } else { ttlDuration = parsedDuration } if b.generateLeases { resp.Secret.Renewable = true } } resp.Secret.TTL = ttlDuration return resp, nil }
func TestAppRole_RoleSecretIDReadDelete(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) createRole(t, b, storage, "role1", "a,b") secretIDCreateReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: storage, Path: "role/role1/secret-id", } resp, err = b.HandleRequest(secretIDCreateReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secretID := resp.Data["secret_id"].(string) if secretID == "" { t.Fatal("expected non empty secret ID") } secretIDReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: storage, Path: "role/role1/secret-id/lookup", Data: map[string]interface{}{ "secret_id": secretID, }, } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data == nil { t.Fatal(err) } deleteSecretIDReq := &logical.Request{ Operation: logical.DeleteOperation, Storage: storage, Path: "role/role1/secret-id/destroy", Data: map[string]interface{}{ "secret_id": secretID, }, } resp, err = b.HandleRequest(deleteSecretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } resp, err = b.HandleRequest(secretIDReq) if resp != nil && resp.IsError() { t.Fatalf("error response:%#v", err, resp) } if err != nil { t.Fatal(err) } }
func respondCommon(w http.ResponseWriter, resp *logical.Response) bool { if resp == nil { return false } if resp.IsError() { err := fmt.Errorf("%s", resp.Data["error"].(string)) respondError(w, http.StatusBadRequest, err) return true } return false }
func TestAppRole_CIDRSubset(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) roleData := map[string]interface{}{ "role_id": "role-id-123", "policies": "a,b", "bound_cidr_list": "127.0.0.1/24", } roleReq := &logical.Request{ Operation: logical.CreateOperation, Path: "role/testrole1", Storage: storage, Data: roleData, } resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err: %v resp: %#v", err, resp) } secretIDData := map[string]interface{}{ "cidr_list": "127.0.0.1/16", } secretIDReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: storage, Path: "role/testrole1/secret-id", Data: secretIDData, } resp, err = b.HandleRequest(secretIDReq) if resp != nil || resp.IsError() { t.Fatalf("resp:%#v", resp) } if err == nil { t.Fatal("expected an error") } roleData["bound_cidr_list"] = "192.168.27.29/16,172.245.30.40/24,10.20.30.40/30" roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err: %v resp: %#v", err, resp) } secretIDData["cidr_list"] = "192.168.27.29/20,172.245.30.40/25,10.20.30.40/32" resp, err = b.HandleRequest(secretIDReq) if resp != nil && resp.IsError() { t.Fatalf("resp: %#v", resp) } }
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) }
func TestBackend_config_lease_RU(t *testing.T) { var resp *logical.Response var err error config := logical.TestBackendConfig() config.StorageView = &logical.InmemStorage{} b := Backend() if _, err = b.Setup(config); err != nil { t.Fatal(err) } configData := map[string]interface{}{ "ttl": "10h", "max_ttl": "20h", } configReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "config/lease", Storage: config.StorageView, Data: configData, } resp, err = b.HandleRequest(configReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: resp: %#v\nerr:%s", resp, err) } if resp != nil { t.Fatal("expected a nil response") } configReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(configReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: resp: %#v\nerr:%s", resp, err) } if resp == nil { t.Fatal("expected a response") } if resp.Data["ttl"].(time.Duration) != 36000 { t.Fatalf("bad: ttl: expected:36000 actual:%d", resp.Data["ttl"].(time.Duration)) } if resp.Data["max_ttl"].(time.Duration) != 72000 { t.Fatalf("bad: ttl: expected:72000 actual:%d", resp.Data["ttl"].(time.Duration)) } }
func TestAppRole_RoleSecretIDReadDelete(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) createRole(t, b, storage, "role1", "a,b") secretIDCreateReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: storage, Path: "role/role1/secret-id", } resp, err = b.HandleRequest(secretIDCreateReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secretID := resp.Data["secret_id"].(string) secretIDReq := &logical.Request{ Operation: logical.ReadOperation, Storage: storage, Path: "role/role1/secret-id/" + secretID, } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data == nil { t.Fatal(err) } secretIDReq.Operation = logical.DeleteOperation resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secretIDReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(secretIDReq) if resp != nil && resp.IsError() { t.Fatalf("error response:%#v", err, resp) } if err != nil { t.Fatal(err) } }
func TestBackend_config_connection(t *testing.T) { var resp *logical.Response var err error config := logical.TestBackendConfig() config.StorageView = &logical.InmemStorage{} b, err := Factory(config) if err != nil { t.Fatal(err) } configData := map[string]interface{}{ "value": "", "connection_url": "sample_connection_url", "max_open_connections": 9, "max_idle_connections": 7, "verify_connection": false, } configReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "config/connection", Storage: config.StorageView, Data: configData, } resp, err = b.HandleRequest(configReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%s resp:%#v\n", err, resp) } configReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(configReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%s resp:%#v\n", err, resp) } delete(configData, "verify_connection") if !reflect.DeepEqual(configData, resp.Data) { t.Fatalf("bad: expected:%#v\nactual:%#v\n", configData, resp.Data) } }
func TestBackend_PathListRoles(t *testing.T) { var resp *logical.Response var err error config := logical.TestBackendConfig() config.StorageView = &logical.InmemStorage{} b := Backend() if _, err := b.Setup(config); err != nil { t.Fatal(err) } roleData := map[string]interface{}{ "arn": "testarn", } roleReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: config.StorageView, Data: roleData, } for i := 1; i <= 10; i++ { roleReq.Path = "roles/testrole" + strconv.Itoa(i) resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: role creation failed. resp:%#v\n err:%v", resp, err) } } resp, err = b.HandleRequest(&logical.Request{ Operation: logical.ListOperation, Path: "roles", Storage: config.StorageView, }) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: listing roles failed. resp:%#v\n err:%v", resp, err) } if len(resp.Data["keys"].([]string)) != 10 { t.Fatalf("failed to list all 10 roles") } resp, err = b.HandleRequest(&logical.Request{ Operation: logical.ListOperation, Path: "roles/", Storage: config.StorageView, }) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("bad: listing roles failed. resp:%#v\n err:%v", resp, err) } if len(resp.Data["keys"].([]string)) != 10 { t.Fatalf("failed to list all 10 roles") } }
func TestAppRole_RoleSecretID(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) roleData := map[string]interface{}{ "policies": "p,q,r,s", "secret_id_num_uses": 10, "secret_id_ttl": 300, "token_ttl": 400, "token_max_ttl": 500, } roleReq := &logical.Request{ Operation: logical.CreateOperation, Path: "role/role1", Storage: storage, Data: roleData, } resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleSecretIDReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "role/role1/secret-id", Storage: storage, } resp, err = b.HandleRequest(roleSecretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["secret_id"].(string) == "" { t.Fatalf("failed to generate secret_id") } roleSecretIDReq.Path = "role/role1/custom-secret-id" roleCustomSecretIDData := map[string]interface{}{ "secret_id": "abcd123", } roleSecretIDReq.Data = roleCustomSecretIDData roleSecretIDReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleSecretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["secret_id"] != "abcd123" { t.Fatalf("failed to set specific secret_id to role") } }
func respondErrorCommon(w http.ResponseWriter, resp *logical.Response, err error) bool { // If there are no errors return if err == nil && (resp == nil || !resp.IsError()) { return false } // Start out with internal server error since in most of these cases there // won't be a response so this won't be overridden statusCode := http.StatusInternalServerError // If we actually have a response, start out with bad request if resp != nil { statusCode = http.StatusBadRequest } // Now, check the error itself; if it has a specific logical error, set the // appropriate code if err != nil { switch { case errwrap.ContainsType(err, new(vault.StatusBadRequest)): statusCode = http.StatusBadRequest case errwrap.Contains(err, logical.ErrPermissionDenied.Error()): statusCode = http.StatusForbidden case errwrap.Contains(err, logical.ErrUnsupportedOperation.Error()): statusCode = http.StatusMethodNotAllowed case errwrap.Contains(err, logical.ErrUnsupportedPath.Error()): statusCode = http.StatusNotFound case errwrap.Contains(err, logical.ErrInvalidRequest.Error()): statusCode = http.StatusBadRequest } } if resp != nil && resp.IsError() { err = fmt.Errorf("%s", resp.Data["error"].(string)) } respondError(w, statusCode, err) return true }
func TestBackend_config_connection(t *testing.T) { var resp *logical.Response var err error config := logical.TestBackendConfig() config.StorageView = &logical.InmemStorage{} b, err := Factory(config) if err != nil { t.Fatal(err) } configData := map[string]interface{}{ "uri": "sample_connection_uri", "verify_connection": false, } configReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "config/connection", Storage: config.StorageView, Data: configData, } resp, err = b.HandleRequest(configReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%s resp:%#v\n", err, resp) } configReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(configReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%s resp:%#v\n", err, resp) } if resp.Data["uri"] != configData["uri"] { t.Fatalf("bad: %#v", resp) } }
func TestAppRole_SecretIDNumUsesUpgrade(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) roleData := map[string]interface{}{ "secret_id_num_uses": 10, } roleReq := &logical.Request{ Operation: logical.CreateOperation, Path: "role/role1", Storage: storage, Data: roleData, } resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secretIDReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "role/role1/secret-id", Storage: storage, } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secretIDReq.Operation = logical.UpdateOperation secretIDReq.Path = "role/role1/secret-id/lookup" secretIDReq.Data = map[string]interface{}{ "secret_id": resp.Data["secret_id"].(string), } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } // Check if the response contains the value set for secret_id_num_uses // and not SecretIDNumUses if resp.Data["secret_id_num_uses"] != 10 || resp.Data["SecretIDNumUses"] != 0 { t.Fatal("invalid secret_id_num_uses") } }
func TestAppRole_RoleLogin(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) createRole(t, b, storage, "role1", "a,b,c") roleRoleIDReq := &logical.Request{ Operation: logical.ReadOperation, Path: "role/role1/role-id", Storage: storage, } resp, err = b.HandleRequest(roleRoleIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleID := resp.Data["role_id"] roleSecretIDReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "role/role1/secret-id", Storage: storage, } resp, err = b.HandleRequest(roleSecretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secretID := resp.Data["secret_id"] loginData := map[string]interface{}{ "role_id": roleID, "secret_id": secretID, } loginReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "login", Storage: storage, Data: loginData, Connection: &logical.Connection{ RemoteAddr: "127.0.0.1", }, } resp, err = b.HandleRequest(loginReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Auth == nil { t.Fatalf("expected a non-nil auth object in the response") } }
func TestAppRole_RoleConstraints(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) roleData := map[string]interface{}{ "role_id": "role-id-123", "policies": "a,b", } roleReq := &logical.Request{ Operation: logical.CreateOperation, Path: "role/testrole1", Storage: storage, Data: roleData, } // Set bind_secret_id, which is enabled by default resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } // Set bound_cidr_list alone by explicitly disabling bind_secret_id roleReq.Operation = logical.UpdateOperation roleData["bind_secret_id"] = false roleData["bound_cidr_list"] = "0.0.0.0/0" resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } // Remove both constraints roleReq.Operation = logical.UpdateOperation roleData["bound_cidr_list"] = "" roleData["bind_secret_id"] = false resp, err = b.HandleRequest(roleReq) if resp != nil && resp.IsError() { t.Fatalf("resp:%#v", err, resp) } if err == nil { t.Fatalf("expected an error") } }
// 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 }
func (b *backend) secretCredsRevoke( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { // Get the username from the internal data usernameRaw, ok := req.Secret.InternalData["username"] if !ok { return nil, fmt.Errorf("secret is missing username internal data") } username, ok := usernameRaw.(string) var revocationSQL string var resp *logical.Response roleNameRaw, ok := req.Secret.InternalData["role"] if ok { role, err := b.Role(req.Storage, roleNameRaw.(string)) if err != nil { return nil, err } if role == nil { if resp == nil { resp = &logical.Response{} } resp.AddWarning(fmt.Sprintf("Role %q cannot be found. Using default revocation SQL.", roleNameRaw.(string))) } else { revocationSQL = role.RevocationSQL } } // Get our connection db, err := b.DB(req.Storage) if err != nil { return nil, err } switch revocationSQL { // This is the default revocation logic. If revocation SQL is provided it // is simply executed as-is. case "": // Check if the role exists var exists bool err = db.QueryRow("SELECT exists (SELECT rolname FROM pg_roles WHERE rolname=$1);", username).Scan(&exists) if err != nil && err != sql.ErrNoRows { return nil, err } if exists == false { return resp, nil } // Query for permissions; we need to revoke permissions before we can drop // the role // This isn't done in a transaction because even if we fail along the way, // we want to remove as much access as possible stmt, err := db.Prepare("SELECT DISTINCT table_schema FROM information_schema.role_column_grants WHERE grantee=$1;") if err != nil { return nil, err } defer stmt.Close() rows, err := stmt.Query(username) if err != nil { return nil, err } defer rows.Close() const initialNumRevocations = 16 revocationStmts := make([]string, 0, initialNumRevocations) for rows.Next() { var schema string err = rows.Scan(&schema) if err != nil { // keep going; remove as many permissions as possible right now continue } revocationStmts = append(revocationStmts, fmt.Sprintf( `REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA %s FROM %s;`, pq.QuoteIdentifier(schema), pq.QuoteIdentifier(username))) revocationStmts = append(revocationStmts, fmt.Sprintf( `REVOKE USAGE ON SCHEMA %s FROM %s;`, pq.QuoteIdentifier(schema), pq.QuoteIdentifier(username))) } // for good measure, revoke all privileges and usage on schema public revocationStmts = append(revocationStmts, fmt.Sprintf( `REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM %s;`, pq.QuoteIdentifier(username))) revocationStmts = append(revocationStmts, fmt.Sprintf( "REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM %s;", pq.QuoteIdentifier(username))) revocationStmts = append(revocationStmts, fmt.Sprintf( "REVOKE USAGE ON SCHEMA public FROM %s;", pq.QuoteIdentifier(username))) // get the current database name so we can issue a REVOKE CONNECT for // this username var dbname sql.NullString if err := db.QueryRow("SELECT current_database();").Scan(&dbname); err != nil { return nil, err } if dbname.Valid { revocationStmts = append(revocationStmts, fmt.Sprintf( `REVOKE CONNECT ON DATABASE %s FROM %s;`, pq.QuoteIdentifier(dbname.String), pq.QuoteIdentifier(username))) } // again, here, we do not stop on error, as we want to remove as // many permissions as possible right now var lastStmtError error for _, query := range revocationStmts { stmt, err := db.Prepare(query) if err != nil { lastStmtError = err continue } defer stmt.Close() _, err = stmt.Exec() if err != nil { lastStmtError = err } } // can't drop if not all privileges are revoked if rows.Err() != nil { return nil, fmt.Errorf("could not generate revocation statements for all rows: %s", rows.Err()) } if lastStmtError != nil { return nil, fmt.Errorf("could not perform all revocation statements: %s", lastStmtError) } // Drop this user stmt, err = db.Prepare(fmt.Sprintf( `DROP ROLE IF EXISTS %s;`, pq.QuoteIdentifier(username))) if err != nil { return nil, err } defer stmt.Close() if _, err := stmt.Exec(); err != nil { return nil, err } // We have revocation SQL, execute directly, within a transaction default: tx, err := db.Begin() if err != nil { return nil, err } defer func() { tx.Rollback() }() for _, query := range strutil.ParseArbitraryStringSlice(revocationSQL, ";") { query = strings.TrimSpace(query) if len(query) == 0 { continue } stmt, err := tx.Prepare(Query(query, map[string]string{ "name": username, })) if err != nil { return nil, err } defer stmt.Close() if _, err := stmt.Exec(); err != nil { return nil, err } } if err := tx.Commit(); err != nil { return nil, err } } return resp, nil }
func TestAppRole_RoleIDUniqueness(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) roleData := map[string]interface{}{ "role_id": "role-id-123", "policies": "a,b", "secret_id_num_uses": 10, "secret_id_ttl": 300, "token_ttl": 400, "token_max_ttl": 500, } roleReq := &logical.Request{ Operation: logical.CreateOperation, Path: "role/testrole1", Storage: storage, Data: roleData, } resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Path = "role/testrole2" resp, err = b.HandleRequest(roleReq) if err == nil && !(resp != nil && resp.IsError()) { t.Fatalf("expected an error: got resp:%#v", resp) } roleData["role_id"] = "role-id-456" resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.UpdateOperation roleData["role_id"] = "role-id-123" resp, err = b.HandleRequest(roleReq) if err == nil && !(resp != nil && resp.IsError()) { t.Fatalf("expected an error: got resp:%#v", resp) } roleReq.Path = "role/testrole1" roleData["role_id"] = "role-id-456" resp, err = b.HandleRequest(roleReq) if err == nil && !(resp != nil && resp.IsError()) { t.Fatalf("expected an error: got resp:%#v", resp) } roleIDData := map[string]interface{}{ "role_id": "role-id-456", } roleIDReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "role/testrole1/role-id", Storage: storage, Data: roleIDData, } resp, err = b.HandleRequest(roleIDReq) if err == nil && !(resp != nil && resp.IsError()) { t.Fatalf("expected an error: got resp:%#v", resp) } roleIDData["role_id"] = "role-id-123" roleIDReq.Path = "role/testrole2/role-id" resp, err = b.HandleRequest(roleIDReq) if err == nil && !(resp != nil && resp.IsError()) { t.Fatalf("expected an error: got resp:%#v", resp) } roleIDData["role_id"] = "role-id-2000" resp, err = b.HandleRequest(roleIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleIDData["role_id"] = "role-id-1000" roleIDReq.Path = "role/testrole1/role-id" resp, err = b.HandleRequest(roleIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } }
func TestAppRole_RoleIDUpdate(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) roleData := map[string]interface{}{ "role_id": "role-id-123", "policies": "a,b", "secret_id_num_uses": 10, "secret_id_ttl": 300, "token_ttl": 400, "token_max_ttl": 500, } roleReq := &logical.Request{ Operation: logical.CreateOperation, Path: "role/testrole1", Storage: storage, Data: roleData, } resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleIDUpdateReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "role/testrole1/role-id", Storage: storage, Data: map[string]interface{}{ "role_id": "customroleid", }, } resp, err = b.HandleRequest(roleIDUpdateReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secretIDReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: storage, Path: "role/testrole1/secret-id", } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secretID := resp.Data["secret_id"].(string) loginData := map[string]interface{}{ "role_id": "customroleid", "secret_id": secretID, } loginReq := &logical.Request{ Operation: logical.UpdateOperation, Path: "login", Storage: storage, Data: loginData, Connection: &logical.Connection{ RemoteAddr: "127.0.0.1", }, } resp, err = b.HandleRequest(loginReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Auth == nil { t.Fatalf("expected a non-nil auth object in the response") } }
func TestAppRole_RoleCRUD(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) roleData := map[string]interface{}{ "policies": "p,q,r,s", "secret_id_num_uses": 10, "secret_id_ttl": 300, "token_ttl": 400, "token_max_ttl": 500, "bound_cidr_list": "127.0.0.1/32,127.0.0.1/16", } roleReq := &logical.Request{ Operation: logical.CreateOperation, Path: "role/role1", Storage: storage, Data: roleData, } resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } expected := map[string]interface{}{ "bind_secret_id": true, "policies": []string{"default", "p", "q", "r", "s"}, "secret_id_num_uses": 10, "secret_id_ttl": 300, "token_ttl": 400, "token_max_ttl": 500, "bound_cidr_list": "127.0.0.1/32,127.0.0.1/16", } var expectedStruct roleStorageEntry err = mapstructure.Decode(expected, &expectedStruct) if err != nil { t.Fatal(err) } var actualStruct roleStorageEntry err = mapstructure.Decode(resp.Data, &actualStruct) if err != nil { t.Fatal(err) } expectedStruct.RoleID = actualStruct.RoleID if !reflect.DeepEqual(expectedStruct, actualStruct) { t.Fatalf("bad:\nexpected:%#v\nactual:%#v\n", expectedStruct, actualStruct) } roleData = map[string]interface{}{ "role_id": "test_role_id", "policies": "a,b,c,d", "secret_id_num_uses": 100, "secret_id_ttl": 3000, "token_ttl": 4000, "token_max_ttl": 5000, } roleReq.Data = roleData roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } expected = map[string]interface{}{ "policies": []string{"a", "b", "c", "d", "default"}, "secret_id_num_uses": 100, "secret_id_ttl": 3000, "token_ttl": 4000, "token_max_ttl": 5000, } err = mapstructure.Decode(expected, &expectedStruct) if err != nil { t.Fatal(err) } err = mapstructure.Decode(resp.Data, &actualStruct) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(expectedStruct, actualStruct) { t.Fatalf("bad:\nexpected:%#v\nactual:%#v\n", expectedStruct, actualStruct) } // RU for role_id field roleReq.Path = "role/role1/role-id" roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["role_id"].(string) != "test_role_id" { t.Fatalf("bad: role_id: expected:test_role_id actual:%s\n", resp.Data["role_id"].(string)) } roleReq.Data = map[string]interface{}{"role_id": "custom_role_id"} roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["role_id"].(string) != "custom_role_id" { t.Fatalf("bad: role_id: expected:custom_role_id actual:%s\n", resp.Data["role_id"].(string)) } // RUD for bind_secret_id field roleReq.Path = "role/role1/bind-secret-id" roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Data = map[string]interface{}{"bind_secret_id": false} roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["bind_secret_id"].(bool) { t.Fatalf("bad: bind_secret_id: expected:false actual:%t\n", resp.Data["bind_secret_id"].(bool)) } roleReq.Operation = logical.DeleteOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if !resp.Data["bind_secret_id"].(bool) { t.Fatalf("expected the default value of 'true' to be set") } // RUD for policiess field roleReq.Path = "role/role1/policies" roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Data = map[string]interface{}{"policies": "a1,b1,c1,d1"} roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if !reflect.DeepEqual(resp.Data["policies"].([]string), []string{"a1", "b1", "c1", "d1", "default"}) { t.Fatalf("bad: policies: actual:%s\n", resp.Data["policies"].([]string)) } roleReq.Operation = logical.DeleteOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } expectedPolicies := []string{"default"} actualPolicies := resp.Data["policies"].([]string) if !policyutil.EquivalentPolicies(expectedPolicies, actualPolicies) { t.Fatalf("bad: policies: expected:%s actual:%s", expectedPolicies, actualPolicies) } // RUD for secret-id-num-uses field roleReq.Path = "role/role1/secret-id-num-uses" roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Data = map[string]interface{}{"secret_id_num_uses": 200} roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["secret_id_num_uses"].(int) != 200 { t.Fatalf("bad: secret_id_num_uses: expected:200 actual:%d\n", resp.Data["secret_id_num_uses"].(int)) } roleReq.Operation = logical.DeleteOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["secret_id_num_uses"].(int) != 0 { t.Fatalf("expected value to be reset") } // RUD for secret_id_ttl field roleReq.Path = "role/role1/secret-id-ttl" roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Data = map[string]interface{}{"secret_id_ttl": 3001} roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["secret_id_ttl"].(time.Duration) != 3001 { t.Fatalf("bad: secret_id_ttl: expected:3001 actual:%d\n", resp.Data["secret_id_ttl"].(time.Duration)) } roleReq.Operation = logical.DeleteOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["secret_id_ttl"].(time.Duration) != 0 { t.Fatalf("expected value to be reset") } // RUD for 'period' field roleReq.Path = "role/role1/period" roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Data = map[string]interface{}{"period": 9001} roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["period"].(time.Duration) != 9001 { t.Fatalf("bad: period: expected:9001 actual:%d\n", resp.Data["9001"].(time.Duration)) } roleReq.Operation = logical.DeleteOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["period"].(time.Duration) != 0 { t.Fatalf("expected value to be reset") } // RUD for token_ttl field roleReq.Path = "role/role1/token-ttl" roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Data = map[string]interface{}{"token_ttl": 4001} roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["token_ttl"].(time.Duration) != 4001 { t.Fatalf("bad: token_ttl: expected:4001 actual:%d\n", resp.Data["token_ttl"].(time.Duration)) } roleReq.Operation = logical.DeleteOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["token_ttl"].(time.Duration) != 0 { t.Fatalf("expected value to be reset") } // RUD for token_max_ttl field roleReq.Path = "role/role1/token-max-ttl" roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Data = map[string]interface{}{"token_max_ttl": 5001} roleReq.Operation = logical.UpdateOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["token_max_ttl"].(time.Duration) != 5001 { t.Fatalf("bad: token_max_ttl: expected:5001 actual:%d\n", resp.Data["token_max_ttl"].(time.Duration)) } roleReq.Operation = logical.DeleteOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data["token_max_ttl"].(time.Duration) != 0 { t.Fatalf("expected value to be reset") } // Delete test for role roleReq.Path = "role/role1" roleReq.Operation = logical.DeleteOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } roleReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp != nil { t.Fatalf("expected a nil response") } }
func (b *backend) secretCredsRevoke( req *logical.Request, d *framework.FieldData) (*logical.Response, error) { var resp *logical.Response // Get the username from the internal data usernameRaw, ok := req.Secret.InternalData["username"] if !ok { return nil, fmt.Errorf("secret is missing username internal data") } username, ok := usernameRaw.(string) // Get our connection db, err := b.DB(req.Storage) if err != nil { return nil, err } roleName := "" roleNameRaw, ok := req.Secret.InternalData["role"] if ok { roleName = roleNameRaw.(string) } var role *roleEntry if roleName != "" { role, err = b.Role(req.Storage, roleName) if err != nil { return nil, err } } // Use a default SQL statement for revocation if one cannot be fetched from the role revocationSQL := defaultRevocationSQL if role != nil && role.RevocationSQL != "" { revocationSQL = role.RevocationSQL } else { if resp == nil { resp = &logical.Response{} } resp.AddWarning(fmt.Sprintf("Role %q cannot be found. Using default SQL for revoking user.", roleName)) } // Start a transaction tx, err := db.Begin() if err != nil { return nil, err } defer tx.Rollback() for _, query := range strutil.ParseArbitraryStringSlice(revocationSQL, ";") { query = strings.TrimSpace(query) if len(query) == 0 { continue } // This is not a prepared statement because not all commands are supported // 1295: This command is not supported in the prepared statement protocol yet // Reference https://mariadb.com/kb/en/mariadb/prepare-statement/ query = strings.Replace(query, "{{name}}", username, -1) _, err = tx.Exec(query) if err != nil { return nil, err } } // Commit the transaction if err := tx.Commit(); err != nil { return nil, err } return resp, nil }
func TestAppRoleRoleListSecretID(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) createRole(t, b, storage, "role1", "a,b") secretIDReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: storage, Path: "role/role1/secret-id", } // Create 5 'secret_id's resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } listReq := &logical.Request{ Operation: logical.ListOperation, Storage: storage, Path: "role/role1/secret-id/", } resp, err = b.HandleRequest(listReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secrets := resp.Data["keys"].([]string) if len(secrets) != 5 { t.Fatalf("bad: len of secrets: expected:5 actual:%d", len(secrets)) } }
func TestAppRole_RoleSecretIDAccessorReadDelete(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) createRole(t, b, storage, "role1", "a,b") secretIDReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: storage, Path: "role/role1/secret-id", } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } listReq := &logical.Request{ Operation: logical.ListOperation, Storage: storage, Path: "role/role1/secret-id", } resp, err = b.HandleRequest(listReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } hmacSecretID := resp.Data["keys"].([]string)[0] hmacReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: storage, Path: "role/role1/secret-id-accessor/lookup", Data: map[string]interface{}{ "secret_id_accessor": hmacSecretID, }, } resp, err = b.HandleRequest(hmacReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } if resp.Data == nil { t.Fatal(err) } hmacReq.Path = "role/role1/secret-id-accessor/destroy" resp, err = b.HandleRequest(hmacReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } hmacReq.Operation = logical.ReadOperation resp, err = b.HandleRequest(hmacReq) if resp != nil && resp.IsError() { t.Fatalf("error response:%#v", err, resp) } if err == nil { t.Fatalf("expected an error") } }
func (ts *TokenStore) tokenStoreRoleCreateUpdate( req *logical.Request, data *framework.FieldData) (*logical.Response, error) { name := data.Get("role_name").(string) if name == "" { return logical.ErrorResponse("role name cannot be empty"), nil } entry, err := ts.tokenStoreRole(name) if err != nil { return nil, err } // Due to the existence check, entry will only be nil if it's a create // operation, so just create a new one if entry == nil { entry = &tsRoleEntry{ Name: name, } } // 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)) } 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)) } if entry.ExplicitMaxTTL != 0 { sysView := ts.System() if sysView.MaxLeaseTTL() != time.Duration(0) && entry.ExplicitMaxTTL > 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", entry.ExplicitMaxTTL.Seconds(), sysView.MaxLeaseTTL().Seconds())) } } pathSuffixInt, ok := data.GetOk("path_suffix") if ok { pathSuffix := pathSuffixInt.(string) if 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) } allowedPoliciesInt, ok := data.GetOk("allowed_policies") if ok { allowedPolicies := allowedPoliciesInt.(string) if allowedPolicies != "" { entry.AllowedPolicies = strings.Split(allowedPolicies, ",") } } else if req.Operation == logical.CreateOperation { entry.AllowedPolicies = strings.Split(data.Get("allowed_policies").(string), ",") } // Explicit max TTLs and periods cannot be used at the same time since the // purpose of a periodic token is to escape max TTL semantics if entry.Period > 0 && entry.ExplicitMaxTTL > 0 { return logical.ErrorResponse("a role cannot be used to issue both periodic tokens and tokens with explicit max TTLs"), logical.ErrInvalidRequest } // Store it jsonEntry, err := logical.StorageEntryJSON(fmt.Sprintf("%s%s", rolesPrefix, name), entry) if err != nil { return nil, err } if err := ts.view.Put(jsonEntry); err != nil { return nil, err } return resp, nil }
func TestAppRole_RoleDeleteSecretID(t *testing.T) { var resp *logical.Response var err error b, storage := createBackendWithStorage(t) createRole(t, b, storage, "role1", "a,b") secretIDReq := &logical.Request{ Operation: logical.UpdateOperation, Storage: storage, Path: "role/role1/secret-id", } // Create 3 secrets on the role resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } resp, err = b.HandleRequest(secretIDReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } listReq := &logical.Request{ Operation: logical.ListOperation, Storage: storage, Path: "role/role1/secret-id", } resp, err = b.HandleRequest(listReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } secretIDAccessors := resp.Data["keys"].([]string) if len(secretIDAccessors) != 3 { t.Fatalf("bad: len of secretIDAccessors: expected:3 actual:%d", len(secretIDAccessors)) } roleReq := &logical.Request{ Operation: logical.DeleteOperation, Storage: storage, Path: "role/role1", } resp, err = b.HandleRequest(roleReq) if err != nil || (resp != nil && resp.IsError()) { t.Fatalf("err:%v resp:%#v", err, resp) } resp, err = b.HandleRequest(listReq) if err != nil || resp == nil || (resp != nil && !resp.IsError()) { t.Fatalf("expected an error. err:%v resp:%#v", err, resp) } }