github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/auth/setup/setup.go (about) 1 package setup 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/treeverse/lakefs/pkg/auth" 9 "github.com/treeverse/lakefs/pkg/auth/acl" 10 "github.com/treeverse/lakefs/pkg/auth/model" 11 "github.com/treeverse/lakefs/pkg/config" 12 "github.com/treeverse/lakefs/pkg/logging" 13 "github.com/treeverse/lakefs/pkg/permissions" 14 ) 15 16 const ( 17 AdminsGroup = "Admins" 18 SuperUsersGroup = "SuperUsers" 19 DevelopersGroup = "Developers" 20 ViewersGroup = "Viewers" 21 ) 22 23 func createGroups(ctx context.Context, authService auth.Service, groups []*model.Group) error { 24 for _, group := range groups { 25 _, err := authService.CreateGroup(ctx, group) 26 if err != nil { 27 return err 28 } 29 } 30 return nil 31 } 32 33 func createPolicies(ctx context.Context, authService auth.Service, policies []*model.Policy) error { 34 for _, policy := range policies { 35 err := authService.WritePolicy(ctx, policy, false) 36 if err != nil { 37 return err 38 } 39 } 40 return nil 41 } 42 43 func CreateRBACBasePolicies(ctx context.Context, authService auth.Service, ts time.Time) error { 44 all := []string{permissions.All} 45 46 return createPolicies(ctx, authService, []*model.Policy{ 47 { 48 CreatedAt: ts, 49 DisplayName: "FSFullAccess", 50 Statement: auth.MakeStatementForPolicyTypeOrDie("FSFullAccess", all), 51 }, 52 { 53 CreatedAt: ts, 54 DisplayName: "FSReadWriteAll", 55 Statement: auth.MakeStatementForPolicyTypeOrDie("FSReadWrite", all), 56 }, 57 { 58 CreatedAt: ts, 59 DisplayName: "FSReadAll", 60 Statement: auth.MakeStatementForPolicyTypeOrDie("FSRead", all), 61 }, 62 { 63 CreatedAt: ts, 64 DisplayName: "RepoManagementFullAccess", 65 Statement: model.Statements{ 66 { 67 Action: []string{ 68 "ci:*", 69 "retention:*", 70 "branches:*", 71 "fs:ReadConfig", 72 }, 73 Resource: permissions.All, 74 Effect: model.StatementEffectAllow, 75 }, 76 }, 77 }, 78 { 79 CreatedAt: ts, 80 DisplayName: "RepoManagementReadAll", 81 Statement: auth.MakeStatementForPolicyTypeOrDie("RepoManagementRead", all), 82 }, 83 { 84 CreatedAt: ts, 85 DisplayName: "AuthFullAccess", 86 Statement: model.Statements{ 87 { 88 Action: []string{ 89 "auth:*", 90 }, 91 Resource: permissions.All, 92 Effect: model.StatementEffectAllow, 93 }, 94 }, 95 }, 96 { 97 CreatedAt: ts, 98 DisplayName: "AuthManageOwnCredentials", 99 Statement: auth.MakeStatementForPolicyTypeOrDie( 100 "AuthManageOwnCredentials", 101 []string{permissions.UserArn("${user}")}, 102 ), 103 }, 104 }) 105 } 106 107 func attachPolicies(ctx context.Context, authService auth.Service, groupID string, policyIDs []string) error { 108 for _, policyID := range policyIDs { 109 err := authService.AttachPolicyToGroup(ctx, policyID, groupID) 110 if err != nil { 111 return err 112 } 113 } 114 return nil 115 } 116 117 func CreateRBACBaseGroups(ctx context.Context, authService auth.Service, ts time.Time) error { 118 err := createGroups(ctx, authService, []*model.Group{ 119 {CreatedAt: ts, DisplayName: AdminsGroup}, 120 {CreatedAt: ts, DisplayName: SuperUsersGroup}, 121 {CreatedAt: ts, DisplayName: DevelopersGroup}, 122 {CreatedAt: ts, DisplayName: ViewersGroup}, 123 }) 124 if err != nil { 125 return err 126 } 127 128 err = CreateRBACBasePolicies(ctx, authService, ts) 129 if err != nil { 130 return err 131 } 132 133 err = attachPolicies(ctx, authService, "Admins", []string{"FSFullAccess", "AuthFullAccess", "RepoManagementFullAccess"}) 134 if err != nil { 135 return err 136 } 137 err = attachPolicies(ctx, authService, "SuperUsers", []string{"FSFullAccess", "AuthManageOwnCredentials", "RepoManagementReadAll"}) 138 if err != nil { 139 return err 140 } 141 err = attachPolicies(ctx, authService, "Developers", []string{"FSReadWriteAll", "AuthManageOwnCredentials", "RepoManagementReadAll"}) 142 if err != nil { 143 return err 144 } 145 err = attachPolicies(ctx, authService, "Viewers", []string{"FSReadAll", "AuthManageOwnCredentials"}) 146 if err != nil { 147 return err 148 } 149 150 return nil 151 } 152 153 func CreateACLBaseGroups(ctx context.Context, authService auth.Service, ts time.Time) error { 154 if _, err := authService.CreateGroup(ctx, &model.Group{CreatedAt: ts, DisplayName: acl.AdminsGroup}); err != nil { 155 return fmt.Errorf("setup: create base ACL group %s: %w", acl.AdminsGroup, err) 156 } 157 if err := acl.WriteGroupACL(ctx, authService, acl.AdminsGroup, model.ACL{Permission: acl.AdminPermission}, ts, false); err != nil { 158 return fmt.Errorf("setup: %w", err) 159 } 160 161 if _, err := authService.CreateGroup(ctx, &model.Group{CreatedAt: ts, DisplayName: acl.SupersGroup}); err != nil { 162 return fmt.Errorf("setup: create base ACL group %s: %w", acl.SupersGroup, err) 163 } 164 if err := acl.WriteGroupACL(ctx, authService, acl.SupersGroup, model.ACL{Permission: acl.SuperPermission}, ts, false); err != nil { 165 return fmt.Errorf("setup: %w", err) 166 } 167 168 if _, err := authService.CreateGroup(ctx, &model.Group{CreatedAt: ts, DisplayName: acl.WritersGroup}); err != nil { 169 return fmt.Errorf("setup: create base ACL group %s: %w", acl.WritersGroup, err) 170 } 171 if err := acl.WriteGroupACL(ctx, authService, acl.WritersGroup, model.ACL{Permission: acl.WritePermission}, ts, false); err != nil { 172 return fmt.Errorf("setup: %w", err) 173 } 174 175 if _, err := authService.CreateGroup(ctx, &model.Group{CreatedAt: ts, DisplayName: acl.ReadersGroup}); err != nil { 176 return fmt.Errorf("create base ACL group %s: %w", acl.ReadersGroup, err) 177 } 178 if err := acl.WriteGroupACL(ctx, authService, acl.ReadersGroup, model.ACL{Permission: acl.ReadPermission}, ts, false); err != nil { 179 return fmt.Errorf("setup: %w", err) 180 } 181 182 return nil 183 } 184 185 // CreateAdminUser setup base groups, policies and create admin user 186 func CreateAdminUser(ctx context.Context, authService auth.Service, cfg *config.Config, superuser *model.SuperuserConfiguration) (*model.Credential, error) { 187 // Set up the basic groups and policies 188 now := time.Now() 189 err := CreateBaseGroups(ctx, authService, cfg, now) 190 if err != nil { 191 return nil, err 192 } 193 194 return AddAdminUser(ctx, authService, superuser) 195 } 196 197 func AddAdminUser(ctx context.Context, authService auth.Service, user *model.SuperuserConfiguration) (*model.Credential, error) { 198 // verify the admin group exists 199 _, err := authService.GetGroup(ctx, AdminsGroup) 200 if err != nil { 201 return nil, fmt.Errorf("admin group - %w", err) 202 } 203 204 // create admin user 205 user.Source = "internal" 206 _, err = authService.CreateUser(ctx, &user.User) 207 if err != nil { 208 return nil, fmt.Errorf("create user - %w", err) 209 } 210 err = authService.AddUserToGroup(ctx, user.Username, AdminsGroup) 211 if err != nil { 212 return nil, fmt.Errorf("add user to group - %w", err) 213 } 214 215 var creds *model.Credential 216 if user.AccessKeyID == "" { 217 // Generate and return a key pair 218 creds, err = authService.CreateCredentials(ctx, user.Username) 219 if err != nil { 220 return nil, fmt.Errorf("create credentials for %s: %w", user.Username, err) 221 } 222 } else { 223 creds, err = authService.AddCredentials(ctx, user.Username, user.AccessKeyID, user.SecretAccessKey) 224 if err != nil { 225 return nil, fmt.Errorf("add credentials for %s: %w", user.Username, err) 226 } 227 } 228 return creds, nil 229 } 230 231 func CreateInitialAdminUser(ctx context.Context, authService auth.Service, cfg *config.Config, metadataManger auth.MetadataManager, username string) (*model.Credential, error) { 232 return CreateInitialAdminUserWithKeys(ctx, authService, cfg, metadataManger, username, nil, nil) 233 } 234 235 func CreateInitialAdminUserWithKeys(ctx context.Context, authService auth.Service, cfg *config.Config, metadataManger auth.MetadataManager, username string, accessKeyID *string, secretAccessKey *string) (*model.Credential, error) { 236 adminUser := &model.SuperuserConfiguration{ 237 User: model.User{ 238 CreatedAt: time.Now(), 239 Username: username, 240 }, 241 } 242 if accessKeyID != nil && secretAccessKey != nil { 243 adminUser.AccessKeyID = *accessKeyID 244 adminUser.SecretAccessKey = *secretAccessKey 245 } 246 247 // create first admin user 248 cred, err := CreateAdminUser(ctx, authService, cfg, adminUser) 249 if err != nil { 250 return nil, err 251 } 252 253 // update setup timestamp 254 if err := metadataManger.UpdateSetupTimestamp(ctx, time.Now()); err != nil { 255 logging.ContextUnavailable().WithError(err).Error("Failed the update setup timestamp") 256 } 257 return cred, err 258 } 259 260 func CreateBaseGroups(ctx context.Context, authService auth.Service, cfg *config.Config, ts time.Time) error { 261 if cfg.IsAuthUISimplified() { 262 return CreateACLBaseGroups(ctx, authService, ts) 263 } 264 return CreateRBACBaseGroups(ctx, authService, ts) 265 }