github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/iam/roles.go (about) 1 package iam 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 "net/url" 9 "strconv" 10 11 validation "github.com/go-ozzo/ozzo-validation/v4" 12 ) 13 14 type ( 15 // Roles is the IAM role API interface 16 Roles interface { 17 // CreateRole creates a custom role 18 // 19 // See: https://techdocs.akamai.com/iam-user-admin/reference/post-role 20 CreateRole(context.Context, CreateRoleRequest) (*Role, error) 21 22 // GetRole gets details for a specific role 23 // 24 // See: https://techdocs.akamai.com/iam-user-admin/reference/get-role 25 GetRole(context.Context, GetRoleRequest) (*Role, error) 26 27 // UpdateRole adds or removes permissions from a role and updates other parameters 28 // 29 // See: https://techdocs.akamai.com/iam-user-admin/reference/put-role 30 UpdateRole(context.Context, UpdateRoleRequest) (*Role, error) 31 32 // DeleteRole deletes a role. This operation is only allowed if the role isn't assigned to any users. 33 // 34 // See: https://techdocs.akamai.com/iam-user-admin/reference/delete-role 35 DeleteRole(context.Context, DeleteRoleRequest) error 36 37 // ListRoles lists roles for the current account and contract type 38 // 39 // See: https://techdocs.akamai.com/iam-user-admin/reference/get-roles 40 ListRoles(context.Context, ListRolesRequest) ([]Role, error) 41 42 // ListGrantableRoles lists which grantable roles can be included in a new custom role or added to an existing custom role 43 // 44 // See: https://techdocs.akamai.com/iam-user-admin/reference/get-grantable-roles 45 ListGrantableRoles(context.Context) ([]RoleGrantedRole, error) 46 } 47 48 // RoleRequest describes request parameters of the create and update role endpoint 49 RoleRequest struct { 50 Name string `json:"roleName,omitempty"` 51 Description string `json:"roleDescription,omitempty"` 52 GrantedRoles []GrantedRoleID `json:"grantedRoles,omitempty"` 53 } 54 55 // CreateRoleRequest describes the request parameters of the create role endpoint 56 CreateRoleRequest RoleRequest 57 58 // GrantedRoleID describes a unique identifier for a granted role 59 GrantedRoleID struct { 60 ID int64 `json:"grantedRoleId"` 61 } 62 63 // GetRoleRequest describes the request parameters of the get role endpoint 64 GetRoleRequest struct { 65 ID int64 66 Actions bool 67 GrantedRoles bool 68 Users bool 69 } 70 71 // UpdateRoleRequest describes the request parameters of the update role endpoint. 72 // It works as patch request. You need to provide only fields which you want to update. 73 UpdateRoleRequest struct { 74 ID int64 75 RoleRequest 76 } 77 78 // DeleteRoleRequest describes the request parameters of the delete role endpoint 79 DeleteRoleRequest struct { 80 ID int64 81 } 82 83 // ListRolesRequest describes the request parameters of the list roles endpoint 84 ListRolesRequest struct { 85 GroupID *int64 86 Actions bool 87 IgnoreContext bool 88 Users bool 89 } 90 91 // RoleAction encapsulates permissions available to the user for this role 92 RoleAction struct { 93 Delete bool `json:"delete"` 94 Edit bool `json:"edit"` 95 } 96 97 // RoleGrantedRole is a list of granted roles, giving the user access to objects in a group 98 RoleGrantedRole struct { 99 Description string `json:"grantedRoleDescription,omitempty"` 100 RoleID int64 `json:"grantedRoleId"` 101 RoleName string `json:"grantedRoleName"` 102 } 103 104 // RoleUser user who shares the same role 105 RoleUser struct { 106 AccountID string `json:"accountId"` 107 Email string `json:"email"` 108 FirstName string `json:"firstName"` 109 LastLoginDate string `json:"lastLoginDate"` 110 LastName string `json:"lastName"` 111 UIIdentityID string `json:"uiIdentityId"` 112 } 113 114 // Role encapsulates the response of the list roles endpoint 115 Role struct { 116 Actions *RoleAction `json:"actions,omitempty"` 117 CreatedBy string `json:"createdBy"` 118 CreatedDate string `json:"createdDate"` 119 GrantedRoles []RoleGrantedRole `json:"grantedRoles,omitempty"` 120 ModifiedBy string `json:"modifiedBy"` 121 ModifiedDate string `json:"modifiedDate"` 122 RoleDescription string `json:"roleDescription"` 123 RoleID int64 `json:"roleId"` 124 RoleName string `json:"roleName"` 125 Users []RoleUser `json:"users,omitempty"` 126 RoleType RoleType `json:"type"` 127 } 128 129 // RoleType is an enum of role types 130 RoleType string 131 ) 132 133 // Validate validates CreateRoleRequest 134 func (r CreateRoleRequest) Validate() error { 135 return validation.Errors{ 136 "Name": validation.Validate(r.Name, validation.Required), 137 "Description": validation.Validate(r.Description, validation.Required), 138 "GrantedRoles": validation.Validate(r.GrantedRoles, validation.Required), 139 }.Filter() 140 } 141 142 // Validate validates GetRoleRequest 143 func (r GetRoleRequest) Validate() error { 144 return validation.Errors{ 145 "ID": validation.Validate(r.ID, validation.Required), 146 }.Filter() 147 } 148 149 // Validate validates UpdateRoleRequest 150 func (r UpdateRoleRequest) Validate() error { 151 return validation.Errors{ 152 "ID": validation.Validate(r.ID, validation.Required), 153 }.Filter() 154 } 155 156 // Validate validates DeleteRoleRequest 157 func (r DeleteRoleRequest) Validate() error { 158 return validation.Errors{ 159 "ID": validation.Validate(r.ID, validation.Required), 160 }.Filter() 161 } 162 163 var ( 164 // RoleTypeStandard is a standard type provided by Akamai 165 RoleTypeStandard RoleType = "standard" 166 167 // RoleTypeCustom is a custom role provided by the account 168 RoleTypeCustom RoleType = "custom" 169 ) 170 171 var ( 172 // ErrCreateRole is returned when CreateRole fails 173 ErrCreateRole = errors.New("create a role") 174 // ErrGetRole is returned when GetRole fails 175 ErrGetRole = errors.New("get a role") 176 // ErrUpdateRole is returned when UpdateRole fails 177 ErrUpdateRole = errors.New("update a role") 178 // ErrDeleteRole is returned when DeleteRole fails 179 ErrDeleteRole = errors.New("delete a role") 180 // ErrListRoles is returned when ListRoles fails 181 ErrListRoles = errors.New("list roles") 182 // ErrListGrantableRoles is returned when ListGrantableRoles fails 183 ErrListGrantableRoles = errors.New("list grantable roles") 184 ) 185 186 func (i *iam) CreateRole(ctx context.Context, params CreateRoleRequest) (*Role, error) { 187 logger := i.Log(ctx) 188 logger.Debug("CreateRole") 189 190 if err := params.Validate(); err != nil { 191 return nil, fmt.Errorf("%s: %w:\n%s", ErrCreateRole, ErrStructValidation, err) 192 } 193 194 uri, err := url.Parse("/identity-management/v2/user-admin/roles") 195 if err != nil { 196 return nil, fmt.Errorf("%w: failed to parse url: %s", ErrCreateRole, err) 197 } 198 199 req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri.String(), nil) 200 if err != nil { 201 return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateRole, err) 202 } 203 204 var result Role 205 resp, err := i.Exec(req, &result, params) 206 if err != nil { 207 return nil, fmt.Errorf("%w: request failed: %s", ErrCreateRole, err) 208 } 209 210 if resp.StatusCode != http.StatusCreated { 211 return nil, fmt.Errorf("%s: %w", ErrCreateRole, i.Error(resp)) 212 } 213 214 return &result, nil 215 } 216 217 func (i *iam) GetRole(ctx context.Context, params GetRoleRequest) (*Role, error) { 218 logger := i.Log(ctx) 219 logger.Debug("GetRole") 220 221 if err := params.Validate(); err != nil { 222 return nil, fmt.Errorf("%s: %w:\n%s", ErrGetRole, ErrStructValidation, err) 223 } 224 225 uri, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/roles/%d", params.ID)) 226 if err != nil { 227 return nil, fmt.Errorf("%w: failed to parse url: %s", ErrGetRole, err) 228 } 229 230 q := uri.Query() 231 q.Add("actions", strconv.FormatBool(params.Actions)) 232 q.Add("grantedRoles", strconv.FormatBool(params.GrantedRoles)) 233 q.Add("users", strconv.FormatBool(params.Users)) 234 235 uri.RawQuery = q.Encode() 236 237 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil) 238 if err != nil { 239 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetRole, err) 240 } 241 242 var result Role 243 resp, err := i.Exec(req, &result) 244 if err != nil { 245 return nil, fmt.Errorf("%w: request failed: %s", ErrGetRole, err) 246 } 247 248 if resp.StatusCode != http.StatusOK { 249 return nil, fmt.Errorf("%s: %w", ErrGetRole, i.Error(resp)) 250 } 251 252 return &result, nil 253 } 254 255 func (i *iam) UpdateRole(ctx context.Context, params UpdateRoleRequest) (*Role, error) { 256 logger := i.Log(ctx) 257 logger.Debug("UpdateRole") 258 259 if err := params.Validate(); err != nil { 260 return nil, fmt.Errorf("%s: %w:\n%s", ErrUpdateRole, ErrStructValidation, err) 261 } 262 263 uri, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/roles/%d", params.ID)) 264 if err != nil { 265 return nil, fmt.Errorf("%w: failed to parse url: %s", ErrUpdateRole, err) 266 } 267 268 req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri.String(), nil) 269 if err != nil { 270 return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateRole, err) 271 } 272 273 var result Role 274 resp, err := i.Exec(req, &result, params.RoleRequest) 275 if err != nil { 276 return nil, fmt.Errorf("%w: request failed: %s", ErrUpdateRole, err) 277 } 278 279 if resp.StatusCode != http.StatusOK { 280 return nil, fmt.Errorf("%s: %w", ErrUpdateRole, i.Error(resp)) 281 } 282 283 return &result, nil 284 } 285 286 func (i *iam) DeleteRole(ctx context.Context, params DeleteRoleRequest) error { 287 logger := i.Log(ctx) 288 logger.Debug("DeleteRole") 289 290 if err := params.Validate(); err != nil { 291 return fmt.Errorf("%s: %w:\n%s", ErrDeleteRole, ErrStructValidation, err) 292 } 293 294 uri, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/roles/%d", params.ID)) 295 if err != nil { 296 return fmt.Errorf("%w: failed to parse url: %s", ErrDeleteRole, err) 297 } 298 299 req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri.String(), nil) 300 if err != nil { 301 return fmt.Errorf("%w: failed to create request: %s", ErrDeleteRole, err) 302 } 303 304 resp, err := i.Exec(req, nil) 305 if err != nil { 306 return fmt.Errorf("%w: request failed: %s", ErrDeleteRole, err) 307 } 308 309 if resp.StatusCode != http.StatusNoContent { 310 return fmt.Errorf("%s: %w", ErrDeleteRole, i.Error(resp)) 311 } 312 313 return nil 314 } 315 316 func (i *iam) ListRoles(ctx context.Context, params ListRolesRequest) ([]Role, error) { 317 logger := i.Log(ctx) 318 logger.Debug("ListRoles") 319 320 u, err := url.Parse("/identity-management/v2/user-admin/roles") 321 if err != nil { 322 return nil, fmt.Errorf("%w: failed to create request: %s", ErrListRoles, err) 323 } 324 q := u.Query() 325 q.Add("actions", strconv.FormatBool(params.Actions)) 326 q.Add("ignoreContext", strconv.FormatBool(params.IgnoreContext)) 327 q.Add("users", strconv.FormatBool(params.Users)) 328 329 if params.GroupID != nil { 330 q.Add("groupId", strconv.FormatInt(*params.GroupID, 10)) 331 } 332 333 u.RawQuery = q.Encode() 334 335 req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) 336 if err != nil { 337 return nil, fmt.Errorf("%w: failed to create request: %s", ErrListRoles, err) 338 } 339 340 var result []Role 341 resp, err := i.Exec(req, &result) 342 if err != nil { 343 return nil, fmt.Errorf("%w: request failed: %s", ErrListRoles, err) 344 } 345 346 if resp.StatusCode != http.StatusOK { 347 return nil, fmt.Errorf("%s: %w", ErrListRoles, i.Error(resp)) 348 } 349 350 return result, nil 351 } 352 353 func (i *iam) ListGrantableRoles(ctx context.Context) ([]RoleGrantedRole, error) { 354 logger := i.Log(ctx) 355 logger.Debug("ListGrantableRoles") 356 357 uri, err := url.Parse("/identity-management/v2/user-admin/roles/grantable-roles") 358 if err != nil { 359 return nil, fmt.Errorf("%w: failed to create request: %s", ErrListGrantableRoles, err) 360 } 361 362 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil) 363 if err != nil { 364 return nil, fmt.Errorf("%w: failed to create request: %s", ErrListGrantableRoles, err) 365 } 366 367 var result []RoleGrantedRole 368 resp, err := i.Exec(req, &result) 369 if err != nil { 370 return nil, fmt.Errorf("%w: request failed: %s", ErrListGrantableRoles, err) 371 } 372 373 if resp.StatusCode != http.StatusOK { 374 return nil, fmt.Errorf("%s: %w", ErrListGrantableRoles, i.Error(resp)) 375 } 376 377 return result, nil 378 }