mirror of
https://github.com/grafana/grafana.git
synced 2024-11-25 10:20:29 -06:00
API Keys: Removal & Redirect of Create endpoint (#92144)
* API keys: redirecting of create endpont * update naming and using admonition * fmt * Apply suggestions from code review Co-authored-by: Ieva <ieva.vasiljeva@grafana.com> --------- Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
This commit is contained in:
parent
909d0fac35
commit
6a19278f23
@ -29,6 +29,11 @@ If you use Grafana v9.1 or newer, use service accounts instead of API keys. For
|
||||
|
||||
## List API keys
|
||||
|
||||
{{% admonition type="warning" %}}
|
||||
This endpoint is deprecated.
|
||||
|
||||
{{% /admonition %}}
|
||||
|
||||
`GET /api/auth/keys`
|
||||
|
||||
**Required permissions**
|
||||
@ -75,6 +80,13 @@ Content-Type: application/json
|
||||
|
||||
## Create API Key
|
||||
|
||||
{{% admonition type="warning" %}}
|
||||
This endpoint has been made obsolete in Grafana 11.3.0.
|
||||
|
||||
{{% /admonition %}}
|
||||
|
||||
Endpoint is obsolete and has been moved to [Grafana service account API]({{< relref "./serviceaccount/" >}}). For more information, refer to [Migrate to Grafana service account API]({{< relref "../../administration/api-keys/#migrate-api-keys-to-grafana-service-accounts-using-the-api" >}}).
|
||||
|
||||
`POST /api/auth/keys`
|
||||
|
||||
**Required permissions**
|
||||
@ -114,14 +126,20 @@ Error statuses:
|
||||
**Example Response**:
|
||||
|
||||
```http
|
||||
HTTP/1.1 200
|
||||
HTTP/1.1 301
|
||||
Content-Type: application/json
|
||||
|
||||
{"name":"mykey","key":"eyJrIjoiWHZiSWd3NzdCYUZnNUtibE9obUpESmE3bzJYNDRIc0UiLCJuIjoibXlrZXkiLCJpZCI6MX1=","id":1}
|
||||
""
|
||||
```
|
||||
|
||||
## Delete API Key
|
||||
|
||||
{{% admonition type="warning" %}}
|
||||
|
||||
### DEPRECATED
|
||||
|
||||
{{% /admonition %}}
|
||||
|
||||
`DELETE /api/auth/keys/:id`
|
||||
|
||||
**Required permissions**
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/components/apikeygen"
|
||||
"github.com/grafana/grafana/pkg/services/apikey"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
@ -114,59 +113,15 @@ func (hs *HTTPServer) DeleteAPIKey(c *contextmodel.ReqContext) response.Response
|
||||
// see: https://grafana.com/docs/grafana/next/administration/api-keys/#migrate-api-keys-to-grafana-service-accounts-using-the-api.
|
||||
//
|
||||
// Responses:
|
||||
// 200: postAPIkeyResponse
|
||||
// 400: badRequestError
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 409: conflictError
|
||||
// 500: internalServerError
|
||||
// 301: statusMovedPermanently
|
||||
func (hs *HTTPServer) AddAPIKey(c *contextmodel.ReqContext) response.Response {
|
||||
cmd := apikey.AddCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if !cmd.Role.IsValid() {
|
||||
return response.Error(http.StatusBadRequest, "Invalid role specified", nil)
|
||||
}
|
||||
if !c.SignedInUser.GetOrgRole().Includes(cmd.Role) {
|
||||
return response.Error(http.StatusForbidden, "Cannot assign a role higher than user's role", nil)
|
||||
}
|
||||
// Set the Location header to the new URL
|
||||
hs.log.Warn("Obsolete and Permanently moved API endpoint called", "path", c.Req.URL.Path)
|
||||
c.Context.Resp.Header().Set("Location", "/api/serviceaccounts/tokens")
|
||||
|
||||
if hs.Cfg.ApiKeyMaxSecondsToLive != -1 {
|
||||
if cmd.SecondsToLive == 0 {
|
||||
return response.Error(http.StatusBadRequest, "Number of seconds before expiration should be set", nil)
|
||||
}
|
||||
if cmd.SecondsToLive > hs.Cfg.ApiKeyMaxSecondsToLive {
|
||||
return response.Error(http.StatusBadRequest, "Number of seconds before expiration is greater than the global limit", nil)
|
||||
}
|
||||
}
|
||||
|
||||
cmd.OrgID = c.SignedInUser.GetOrgID()
|
||||
|
||||
newKeyInfo, err := apikeygen.New(cmd.OrgID, cmd.Name)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "Generating API key failed", err)
|
||||
}
|
||||
|
||||
cmd.Key = newKeyInfo.HashedKey
|
||||
key, err := hs.apiKeyService.AddAPIKey(c.Req.Context(), &cmd)
|
||||
if err != nil {
|
||||
if errors.Is(err, apikey.ErrInvalidExpiration) {
|
||||
return response.Error(http.StatusBadRequest, err.Error(), nil)
|
||||
}
|
||||
if errors.Is(err, apikey.ErrDuplicate) {
|
||||
return response.Error(http.StatusConflict, err.Error(), nil)
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "Failed to add API Key", err)
|
||||
}
|
||||
|
||||
result := &dtos.NewApiKeyResult{
|
||||
ID: key.ID,
|
||||
Name: key.Name,
|
||||
Key: newKeyInfo.ClientSecret,
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, result)
|
||||
// Respond with a 301 Moved Permanently status code
|
||||
// the Location header is enough for clients to know where to go next.
|
||||
return response.JSON(http.StatusMovedPermanently, nil)
|
||||
}
|
||||
|
||||
// swagger:parameters getAPIkeys
|
||||
@ -178,13 +133,6 @@ type GetAPIkeysParams struct {
|
||||
IncludeExpired bool `json:"includeExpired"`
|
||||
}
|
||||
|
||||
// swagger:parameters addAPIkey
|
||||
type AddAPIkeyParams struct {
|
||||
// in:body
|
||||
// required:true
|
||||
Body apikey.AddCommand
|
||||
}
|
||||
|
||||
// swagger:parameters deleteAPIkey
|
||||
type DeleteAPIkeyParams struct {
|
||||
// in:path
|
||||
|
@ -82,6 +82,11 @@ type UnauthorizedError GenericError
|
||||
// swagger:response acceptedResponse
|
||||
type AcceptedResponse GenericError
|
||||
|
||||
// StatusMovedPermanently
|
||||
//
|
||||
// swagger:response statusMovedPermanently
|
||||
type StatusMovedPermanentlyRedirect GenericError
|
||||
|
||||
// documentation for PublicError defined in errutil.Error
|
||||
|
||||
// swagger:response publicErrorResponse
|
||||
|
@ -2225,34 +2225,9 @@
|
||||
"summary": "Creates an API key.",
|
||||
"operationId": "addAPIkey",
|
||||
"deprecated": true,
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AddAPIKeyCommand"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/postAPIkeyResponse"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/responses/badRequestError"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/responses/unauthorisedError"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/responses/forbiddenError"
|
||||
},
|
||||
"409": {
|
||||
"$ref": "#/responses/conflictError"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/responses/internalServerError"
|
||||
"301": {
|
||||
"$ref": "#/responses/statusMovedPermanently"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24190,6 +24165,12 @@
|
||||
"$ref": "#/definitions/SnapshotListResponseDTO"
|
||||
}
|
||||
},
|
||||
"statusMovedPermanently": {
|
||||
"description": "StatusMovedPermanently",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ErrorResponseBody"
|
||||
}
|
||||
},
|
||||
"unauthorisedError": {
|
||||
"description": "UnauthorizedError is returned when the request is not authenticated.",
|
||||
"schema": {
|
||||
|
@ -1942,6 +1942,16 @@
|
||||
},
|
||||
"description": "(empty)"
|
||||
},
|
||||
"statusMovedPermanently": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ErrorResponseBody"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "StatusMovedPermanently"
|
||||
},
|
||||
"unauthorisedError": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
@ -15304,35 +15314,9 @@
|
||||
"deprecated": true,
|
||||
"description": "Will return details of the created API key.",
|
||||
"operationId": "addAPIkey",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AddAPIKeyCommand"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"x-originalParamName": "Body"
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/postAPIkeyResponse"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/components/responses/badRequestError"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/unauthorisedError"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/forbiddenError"
|
||||
},
|
||||
"409": {
|
||||
"$ref": "#/components/responses/conflictError"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/internalServerError"
|
||||
"301": {
|
||||
"$ref": "#/components/responses/statusMovedPermanently"
|
||||
}
|
||||
},
|
||||
"summary": "Creates an API key.",
|
||||
|
Loading…
Reference in New Issue
Block a user