API: Add service account routes to the swagger (#52398)

* API: Add service account routes to the swagger
pull/52465/head
Sofia Papagiannaki 3 years ago committed by GitHub
parent a0f96ed4e1
commit e6b9ded949
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      docs/sources/developers/http_api/serviceaccount.md
  2. 90
      pkg/api/docs/definitions/service_account_tokens.go
  3. 154
      pkg/api/docs/definitions/service_accounts.go
  4. 4
      pkg/api/docs/tags.json
  5. 8
      pkg/api/dtos/apikey.go
  6. 22
      pkg/services/serviceaccounts/api/token.go
  7. 69
      pkg/services/serviceaccounts/models.go
  8. 1038
      public/api-merged.json
  9. 1054
      public/api-spec.json

@ -115,7 +115,7 @@ Requires basic authentication and that the authenticated user is a Grafana Admin
**Example Response**:
```http
HTTP/1.1 200
HTTP/1.1 201
Content-Type: application/json
{
@ -140,9 +140,9 @@ Content-Type: application/json
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
| Action | Scope |
| -------------------- | ------------------ |
| serviceaccounts:read | serviceaccounts:\* |
| Action | Scope |
| -------------------- | -------------------- |
| serviceaccounts:read | serviceaccounts:id:1 |
**Example Request**:
@ -183,14 +183,14 @@ Content-Type: application/json
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
| Action | Scope |
| --------------------- | ------------------ |
| serviceaccounts:write | serviceaccounts:\* |
| Action | Scope |
| --------------------- | -------------------- |
| serviceaccounts:write | serviceaccounts:id:1 |
**Example Request**:
```http
PUT /api/serviceaccounts/2 HTTP/1.1
PATCH /api/serviceaccounts/2 HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Basic YWRtaW46YWRtaW4=
@ -235,9 +235,9 @@ Content-Type: application/json
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
| Action | Scope |
| -------------------- | ------------------ |
| serviceaccounts:read | serviceaccounts:\* |
| Action | Scope |
| -------------------- | -------------------- |
| serviceaccounts:read | serviceaccounts:id:1 |
**Example Request**:
@ -277,9 +277,9 @@ Content-Type: application/json
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
| Action | Scope |
| --------------------- | ------------------ |
| serviceaccounts:write | serviceaccounts:\* |
| Action | Scope |
| --------------------- | -------------------- |
| serviceaccounts:write | serviceaccounts:id:1 |
**Example Request**:
@ -318,9 +318,9 @@ Content-Type: application/json
See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
| Action | Scope |
| --------------------- | ------------------ |
| serviceaccounts:write | serviceaccounts:\* |
| Action | Scope |
| --------------------- | -------------------- |
| serviceaccounts:write | serviceaccounts:id:1 |
**Example Request**:

@ -0,0 +1,90 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/services/serviceaccounts"
"github.com/grafana/grafana/pkg/services/serviceaccounts/api"
)
// swagger:route GET /serviceaccounts/{serviceAccountId}/tokens service_accounts listTokens
//
// Get service account tokens
//
// Required permissions (See note in the [introduction](https://grafana.com/docs/grafana/latest/developers/http_api/serviceaccount/#service-account-api) for an explanation):
// action: `serviceaccounts:read` scope: `global:serviceaccounts:id:1` (single service account)
//
// Requires basic authentication and that the authenticated user is a Grafana Admin.
//
// Responses:
// 200: listTokensResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /serviceaccounts/{serviceAccountId}/tokens service_accounts createToken
//
// Create service account tokens
//
// Required permissions (See note in the [introduction](https://grafana.com/docs/grafana/latest/developers/http_api/serviceaccount/#service-account-api) for an explanation):
// action: `serviceaccounts:write` scope: `serviceaccounts:id:1` (single service account)
//
// Responses:
// 200: createTokenResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 409: conflictError
// 500: internalServerError
// swagger:route DELETE /serviceaccounts/{serviceAccountId}/tokens/{tokenId} service_accounts deleteToken
//
// Delete service account tokens
//
// Required permissions (See note in the [introduction](https://grafana.com/docs/grafana/latest/developers/http_api/serviceaccount/#service-account-api) for an explanation):
// action: `serviceaccounts:write` scope: `serviceaccounts:id:1` (single service account)
//
// Requires basic authentication and that the authenticated user is a Grafana Admin.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters listTokens
type ListTokensParams struct {
// in:path
ServiceAccountId int64 `json:"serviceAccountId"`
}
// swagger:parameters createToken
type CreateTokenParams struct {
// in:path
ServiceAccountId int64 `json:"serviceAccountId"`
// in:body
Body serviceaccounts.AddServiceAccountTokenCommand
}
// swagger:parameters deleteToken
type DeleteTokenParams struct {
// in:path
TokenId int64 `json:"tokenId"`
// in:path
ServiceAccountId int64 `json:"serviceAccountId"`
}
// swagger:response listTokensResponse
type ListTokensResponse struct {
// in:body
Body *api.TokenDTO
}
// swagger:response createTokenResponse
type CreateTokenResponse struct {
// in:body
Body *dtos.NewApiKeyResult
}

@ -0,0 +1,154 @@
package definitions
import "github.com/grafana/grafana/pkg/services/serviceaccounts"
// swagger:route GET /serviceaccounts/search service_accounts searchOrgServiceAccountsWithPaging
//
// Search service accounts with Paging
//
// Required permissions (See note in the [introduction](https://grafana.com/docs/grafana/latest/developers/http_api/serviceaccount/#service-account-api) for an explanation):
// action: `serviceaccounts:read` scope: `serviceaccounts:*`
//
// Responses:
// 200: searchOrgServiceAccountsWithPagingResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /serviceaccounts service_accounts createServiceAccount
//
// Create service account
//
// Required permissions (See note in the [introduction](https://grafana.com/docs/grafana/latest/developers/http_api/serviceaccount/#service-account-api) for an explanation):
// action: `serviceaccounts:write` scope: `serviceaccounts:*`
//
// Requires basic authentication and that the authenticated user is a Grafana Admin.
//
// Responses:
// 201: createServiceAccountResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /serviceaccounts/{serviceAccountId} service_accounts retrieveServiceAccount
//
// Get single serviceaccount by Id
//
// Required permissions (See note in the [introduction](https://grafana.com/docs/grafana/latest/developers/http_api/serviceaccount/#service-account-api) for an explanation):
// action: `serviceaccounts:read` scope: `serviceaccounts:id:1` (single service account)
//
// Responses:
// 200: retrieveServiceAccountResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PATCH /serviceaccounts/{serviceAccountId} service_accounts updateServiceAccount
//
// Update service account
//
// Required permissions (See note in the [introduction](https://grafana.com/docs/grafana/latest/developers/http_api/serviceaccount/#service-account-api) for an explanation):
// action: `serviceaccounts:write` scope: `serviceaccounts:id:1` (single service account)
//
// Responses:
// 200: updateServiceAccountResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route DELETE /serviceaccounts/{serviceAccountId} service_accounts deleteServiceAccount
//
// Delete service account
//
// Required permissions (See note in the [introduction](https://grafana.com/docs/grafana/latest/developers/http_api/serviceaccount/#service-account-api) for an explanation):
// action: `serviceaccounts:delete` scope: `serviceaccounts:id:1` (single service account)
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:parameters searchOrgServiceAccountsWithPaging
type SearchOrgServiceAccountsWithPagingParams struct {
// in:query
// required:false
Disabled bool `jsson:"disabled"`
// in:query
// required:false
ExpiredTokens bool `json:"expiredTokens"`
// It will return results where the query value is contained in one of the name.
// Query values with spaces need to be URL encoded.
// in:query
// required:false
Query string `json:"query"`
// The default value is 1000.
// in:query
// required:false
PerPage int `json:"perpage"`
// The default value is 1.
// in:query
// required:false
Page int `json:"page"`
}
// swagger:parameters createServiceAccount
type CreateServiceAccountParams struct {
//in:body
Body serviceaccounts.CreateServiceAccountForm
}
// swagger:parameters retrieveServiceAccount
type RetrieveServiceAccountParams struct {
// in:path
ServiceAccountId int64 `json:"serviceAccountId"`
}
// swagger:parameters updateServiceAccount
type UpdateServiceAccountParams struct {
// in:path
ServiceAccountId int64 `json:"serviceAccountId"`
// in:body
Body serviceaccounts.UpdateServiceAccountForm
}
// swagger:parameters deleteServiceAccount
type DeleteServiceAccountParams struct {
// in:path
ServiceAccountId int64 `json:"serviceAccountId"`
}
// swagger:response searchOrgServiceAccountsWithPagingResponse
type SearchOrgServiceAccountsWithPagingResponse struct {
// in:body
Body *serviceaccounts.SearchServiceAccountsResult
}
// swagger:response createServiceAccountResponse
type CreateServiceAccountResponse struct {
// in:body
Body *serviceaccounts.ServiceAccountDTO
}
// swagger:response retrieveServiceAccountResponse
type RetrieveServiceAccountResponse struct {
// in:body
Body *serviceaccounts.ServiceAccountDTO
}
// swagger:response updateServiceAccountResponse
type UpdateServiceAccountResponse struct {
// in:body
Body struct {
Message string `json:"message"`
ID int64 `json:"id"`
Name string `json:"name"`
ServiceAccount *serviceaccounts.ServiceAccountProfileDTO `json:"serviceaccount"`
}
}

@ -83,6 +83,10 @@
{
"name": "prometheus",
"description": "Grafana Alerting Prometheus-compatible endpoints"
},
{
"name": "service_accounts",
"description": "If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information."
}
]
}

@ -7,10 +7,14 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
)
// swagger:model
type NewApiKeyResult struct {
ID int64 `json:"id"`
// example: 1
ID int64 `json:"id"`
// example: grafana
Name string `json:"name"`
Key string `json:"key"`
// example: glsa_yscW25imSKJIuav8zF37RZmnbiDvB05G_fcaaf58a
Key string `json:"key"`
}
type ApiKeyDTO struct {

@ -20,14 +20,22 @@ const (
ServiceID = "sa"
)
// swagger:model
type TokenDTO struct {
Id int64 `json:"id"`
Name string `json:"name"`
Created *time.Time `json:"created"`
LastUsedAt *time.Time `json:"lastUsedAt"`
Expiration *time.Time `json:"expiration"`
SecondsUntilExpiration *float64 `json:"secondsUntilExpiration"`
HasExpired bool `json:"hasExpired"`
// example: 1
Id int64 `json:"id"`
// example: grafana
Name string `json:"name"`
// example: 2022-03-23T10:31:02Z
Created *time.Time `json:"created"`
// example: 2022-03-23T10:31:02Z
LastUsedAt *time.Time `json:"lastUsedAt"`
// example: 2022-03-23T10:31:02Z
Expiration *time.Time `json:"expiration"`
// example: 0
SecondsUntilExpiration *float64 `json:"secondsUntilExpiration"`
// example: false
HasExpired bool `json:"hasExpired"`
}
func hasExpired(expiration *int64) bool {

@ -25,27 +25,41 @@ type ServiceAccount struct {
Id int64
}
// swagger:model
type CreateServiceAccountForm struct {
Name string `json:"name" binding:"Required"`
Role *models.RoleType `json:"role"`
IsDisabled *bool `json:"isDisabled"`
// example: grafana
Name string `json:"name" binding:"Required"`
// example: Admin
Role *models.RoleType `json:"role"`
// example: false
IsDisabled *bool `json:"isDisabled"`
}
// swagger:model
type UpdateServiceAccountForm struct {
Name *string `json:"name"`
Role *models.RoleType `json:"role"`
IsDisabled *bool `json:"isDisabled"`
}
// swagger: model
type ServiceAccountDTO struct {
Id int64 `json:"id" xorm:"user_id"`
Name string `json:"name" xorm:"name"`
Login string `json:"login" xorm:"login"`
OrgId int64 `json:"orgId" xorm:"org_id"`
IsDisabled bool `json:"isDisabled" xorm:"is_disabled"`
Role string `json:"role" xorm:"role"`
Tokens int64 `json:"tokens"`
AvatarUrl string `json:"avatarUrl"`
Id int64 `json:"id" xorm:"user_id"`
// example: grafana
Name string `json:"name" xorm:"name"`
// example: sa-grafana
Login string `json:"login" xorm:"login"`
// example: 1
OrgId int64 `json:"orgId" xorm:"org_id"`
// example: false
IsDisabled bool `json:"isDisabled" xorm:"is_disabled"`
// example: Viewer
Role string `json:"role" xorm:"role"`
// example: 0
Tokens int64 `json:"tokens"`
// example: /avatar/85ec38023d90823d3e5b43ef35646af9
AvatarUrl string `json:"avatarUrl"`
// example: {"serviceaccounts:delete": true, "serviceaccounts:read": true, "serviceaccounts:write": true}
AccessControl map[string]bool `json:"accessControl,omitempty"`
}
@ -57,23 +71,38 @@ type AddServiceAccountTokenCommand struct {
Result *models.ApiKey `json:"-"`
}
// swagger: model
type SearchServiceAccountsResult struct {
// It can be used for pagination of the user list
// E.g. if totalCount is equal to 100 users and
// the perpage parameter is set to 10 then there are 10 pages of users.
TotalCount int64 `json:"totalCount"`
ServiceAccounts []*ServiceAccountDTO `json:"serviceAccounts"`
Page int `json:"page"`
PerPage int `json:"perPage"`
}
// swagger:model
type ServiceAccountProfileDTO struct {
Id int64 `json:"id" xorm:"user_id"`
Name string `json:"name" xorm:"name"`
Login string `json:"login" xorm:"login"`
OrgId int64 `json:"orgId" xorm:"org_id"`
IsDisabled bool `json:"isDisabled" xorm:"is_disabled"`
Created time.Time `json:"createdAt" xorm:"created"`
Updated time.Time `json:"updatedAt" xorm:"updated"`
AvatarUrl string `json:"avatarUrl" xorm:"-"`
Role string `json:"role" xorm:"role"`
// example: 2
Id int64 `json:"id" xorm:"user_id"`
// example: test
Name string `json:"name" xorm:"name"`
// example: sa-grafana
Login string `json:"login" xorm:"login"`
// example: 1
OrgId int64 `json:"orgId" xorm:"org_id"`
// example: false
IsDisabled bool `json:"isDisabled" xorm:"is_disabled"`
// example: 2022-03-21T14:35:33Z
Created time.Time `json:"createdAt" xorm:"created"`
// example: 2022-03-21T14:35:33Z
Updated time.Time `json:"updatedAt" xorm:"updated"`
// example: /avatar/8ea890a677d6a223c591a1beea6ea9d2
AvatarUrl string `json:"avatarUrl" xorm:"-"`
// example: Editor
Role string `json:"role" xorm:"role"`
// example: []
Teams []string `json:"teams" xorm:"-"`
Tokens int64 `json:"tokens,omitempty"`
AccessControl map[string]bool `json:"accessControl,omitempty" xorm:"-"`

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save