diff --git a/charts/region/Chart.yaml b/charts/region/Chart.yaml index 9bc86e2..ce03c7b 100644 --- a/charts/region/Chart.yaml +++ b/charts/region/Chart.yaml @@ -4,8 +4,8 @@ description: A Helm chart for deploying Unikorn's Region Controller type: application -version: v0.1.22 -appVersion: v0.1.22 +version: v0.1.23 +appVersion: v0.1.23 icon: https://raw.githubusercontent.com/unikorn-cloud/assets/main/images/logos/dark-on-light/icon.png diff --git a/pkg/handler/handler.go b/pkg/handler/handler.go index cea6bb8..eeaa36f 100644 --- a/pkg/handler/handler.go +++ b/pkg/handler/handler.go @@ -42,6 +42,7 @@ import ( "github.com/unikorn-cloud/region/pkg/server/util" kerrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" @@ -63,9 +64,10 @@ type Handler struct { func New(client client.Client, namespace string, options *Options, identity *identityclient.Client) (*Handler, error) { h := &Handler{ - client: client, - options: options, - identity: identity, + client: client, + namespace: namespace, + options: options, + identity: identity, } return h, nil @@ -343,6 +345,30 @@ func (h *Handler) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitie util.WriteJSONResponse(w, r, http.StatusCreated, convertIdentity(identity, cloudconfig)) } +func (h *Handler) DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, projectID openapi.ProjectIDParameter, identityID openapi.IdentityIDParameter) { + if err := rbac.AllowProjectScope(r.Context(), "identities", identityapi.Delete, organizationID, projectID); err != nil { + errors.HandleError(w, r, err) + return + } + + resource := &unikornv1.Identity{ + ObjectMeta: metav1.ObjectMeta{ + Name: identityID, + Namespace: h.namespace, + }, + } + + if err := h.client.Delete(r.Context(), resource); err != nil { + if kerrors.IsNotFound(err) { + errors.HandleError(w, r, errors.HTTPNotFound().WithError(err)) + return + } + + errors.HandleError(w, r, errors.OAuth2ServerError("failed to delete identity").WithError(err)) + return + } +} + func convertPhysicalNetwork(in *unikornv1.PhysicalNetwork) *openapi.PhysicalNetworkRead { out := &openapi.PhysicalNetworkRead{ Metadata: conversion.ProjectScopedResourceReadMetadata(in, coreapi.ResourceProvisioningStatusProvisioned), diff --git a/pkg/openapi/client.go b/pkg/openapi/client.go index 93d8164..3fb0817 100644 --- a/pkg/openapi/client.go +++ b/pkg/openapi/client.go @@ -98,6 +98,9 @@ type ClientInterface interface { PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentities(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, body PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID request + DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter, reqEditors ...RequestEditorFn) (*http.Response, error) + // PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksWithBody request with any body PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksWithBody(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -152,6 +155,18 @@ func (c *Client) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentities return c.Client.Do(req) } +func (c *Client) DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDRequest(c.Server, organizationID, projectID, identityID) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksWithBody(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewPostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksRequestWithBody(c.Server, organizationID, projectID, identityID, contentType, body) if err != nil { @@ -312,6 +327,54 @@ func NewPostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesRequestWi return req, nil } +// NewDeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDRequest generates requests for DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID +func NewDeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDRequest(server string, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "organizationID", runtime.ParamLocationPath, organizationID) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "projectID", runtime.ParamLocationPath, projectID) + if err != nil { + return nil, err + } + + var pathParam2 string + + pathParam2, err = runtime.StyleParamWithLocation("simple", false, "identityID", runtime.ParamLocationPath, identityID) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/v1/organizations/%s/projects/%s/identities/%s", pathParam0, pathParam1, pathParam2) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewPostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksRequest calls the generic PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworks builder with application/json body func NewPostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksRequest(server string, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter, body PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -581,6 +644,9 @@ type ClientWithResponsesInterface interface { PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesWithResponse(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, body PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesResponse, error) + // DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDWithResponse request + DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDWithResponse(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter, reqEditors ...RequestEditorFn) (*DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse, error) + // PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksWithBodyWithResponse request with any body PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksWithBodyWithResponse(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksResponse, error) @@ -651,6 +717,32 @@ func (r PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesResponse) return 0 } +type DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse struct { + Body []byte + HTTPResponse *http.Response + JSON400 *externalRef0.BadRequestResponse + JSON401 *externalRef0.UnauthorizedResponse + JSON403 *externalRef0.ForbiddenResponse + JSON404 *externalRef0.NotFoundResponse + JSON500 *externalRef0.InternalServerErrorResponse +} + +// Status returns HTTPResponse.Status +func (r DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksResponse struct { Body []byte HTTPResponse *http.Response @@ -803,6 +895,15 @@ func (c *ClientWithResponses) PostApiV1OrganizationsOrganizationIDProjectsProjec return ParsePostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesResponse(rsp) } +// DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDWithResponse request returning *DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse +func (c *ClientWithResponses) DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDWithResponse(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter, reqEditors ...RequestEditorFn) (*DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse, error) { + rsp, err := c.DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID(ctx, organizationID, projectID, identityID, reqEditors...) + if err != nil { + return nil, err + } + return ParseDeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse(rsp) +} + // PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksWithBodyWithResponse request with arbitrary body returning *PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksResponse func (c *ClientWithResponses) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksWithBodyWithResponse(ctx context.Context, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksResponse, error) { rsp, err := c.PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksWithBody(ctx, organizationID, projectID, identityID, contentType, body, reqEditors...) @@ -964,6 +1065,60 @@ func ParsePostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesRespons return response, nil } +// ParseDeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse parses an HTTP response from a DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDWithResponse call +func ParseDeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse(rsp *http.Response) (*DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest externalRef0.BadRequestResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest externalRef0.UnauthorizedResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest externalRef0.ForbiddenResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest externalRef0.NotFoundResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest externalRef0.InternalServerErrorResponse + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + // ParsePostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksResponse parses an HTTP response from a PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksWithResponse call func ParsePostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksResponse(rsp *http.Response) (*PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworksResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/pkg/openapi/router.go b/pkg/openapi/router.go index 248cf9f..dd68832 100644 --- a/pkg/openapi/router.go +++ b/pkg/openapi/router.go @@ -21,6 +21,9 @@ type ServerInterface interface { // (POST /api/v1/organizations/{organizationID}/projects/{projectID}/identities) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentities(w http.ResponseWriter, r *http.Request, organizationID OrganizationIDParameter, projectID ProjectIDParameter) + // (DELETE /api/v1/organizations/{organizationID}/projects/{projectID}/identities/{identityID}) + DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID(w http.ResponseWriter, r *http.Request, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter) + // (POST /api/v1/organizations/{organizationID}/projects/{projectID}/identities/{identityID}/physicalNetworks) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworks(w http.ResponseWriter, r *http.Request, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter) @@ -51,6 +54,11 @@ func (_ Unimplemented) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIden w.WriteHeader(http.StatusNotImplemented) } +// (DELETE /api/v1/organizations/{organizationID}/projects/{projectID}/identities/{identityID}) +func (_ Unimplemented) DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID(w http.ResponseWriter, r *http.Request, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter) { + w.WriteHeader(http.StatusNotImplemented) +} + // (POST /api/v1/organizations/{organizationID}/projects/{projectID}/identities/{identityID}/physicalNetworks) func (_ Unimplemented) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworks(w http.ResponseWriter, r *http.Request, organizationID OrganizationIDParameter, projectID ProjectIDParameter, identityID IdentityIDParameter) { w.WriteHeader(http.StatusNotImplemented) @@ -150,6 +158,52 @@ func (siw *ServerInterfaceWrapper) PostApiV1OrganizationsOrganizationIDProjectsP handler.ServeHTTP(w, r.WithContext(ctx)) } +// DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID operation middleware +func (siw *ServerInterfaceWrapper) DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + var err error + + // ------------- Path parameter "organizationID" ------------- + var organizationID OrganizationIDParameter + + err = runtime.BindStyledParameterWithLocation("simple", false, "organizationID", runtime.ParamLocationPath, chi.URLParam(r, "organizationID"), &organizationID) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "organizationID", Err: err}) + return + } + + // ------------- Path parameter "projectID" ------------- + var projectID ProjectIDParameter + + err = runtime.BindStyledParameterWithLocation("simple", false, "projectID", runtime.ParamLocationPath, chi.URLParam(r, "projectID"), &projectID) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectID", Err: err}) + return + } + + // ------------- Path parameter "identityID" ------------- + var identityID IdentityIDParameter + + err = runtime.BindStyledParameterWithLocation("simple", false, "identityID", runtime.ParamLocationPath, chi.URLParam(r, "identityID"), &identityID) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "identityID", Err: err}) + return + } + + ctx = context.WithValue(ctx, Oauth2AuthenticationScopes, []string{}) + + handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + siw.Handler.DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID(w, r, organizationID, projectID, identityID) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r.WithContext(ctx)) +} + // PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworks operation middleware func (siw *ServerInterfaceWrapper) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworks(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -454,6 +508,9 @@ func HandlerWithOptions(si ServerInterface, options ChiServerOptions) http.Handl r.Group(func(r chi.Router) { r.Post(options.BaseURL+"/api/v1/organizations/{organizationID}/projects/{projectID}/identities", wrapper.PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentities) }) + r.Group(func(r chi.Router) { + r.Delete(options.BaseURL+"/api/v1/organizations/{organizationID}/projects/{projectID}/identities/{identityID}", wrapper.DeleteApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityID) + }) r.Group(func(r chi.Router) { r.Post(options.BaseURL+"/api/v1/organizations/{organizationID}/projects/{projectID}/identities/{identityID}/physicalNetworks", wrapper.PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworks) }) diff --git a/pkg/openapi/schema.go b/pkg/openapi/schema.go index 8a9cb42..b1ccd3a 100644 --- a/pkg/openapi/schema.go +++ b/pkg/openapi/schema.go @@ -19,88 +19,91 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "+ifRvrHu78O6Dw//GwAA//9RsMhvMGAAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/pkg/openapi/server.spec.yaml b/pkg/openapi/server.spec.yaml index 1d27d83..a21dd6d 100644 --- a/pkg/openapi/server.spec.yaml +++ b/pkg/openapi/server.spec.yaml @@ -136,6 +136,32 @@ paths: $ref: 'https://raw.githubusercontent.com/unikorn-cloud/core/main/pkg/openapi/common.spec.yaml#/components/responses/forbiddenResponse' '500': $ref: 'https://raw.githubusercontent.com/unikorn-cloud/core/main/pkg/openapi/common.spec.yaml#/components/responses/internalServerErrorResponse' + /api/v1/organizations/{organizationID}/projects/{projectID}/identities/{identityID}: + description: |- + Managed identity services. Identities should be single use e.g. a single cluster instance. + This limits blast radius in the event of a credential leak, or in some cases avoids bugs in + provisioning software. + parameters: + - $ref: '#/components/parameters/organizationIDParameter' + - $ref: '#/components/parameters/projectIDParameter' + - $ref: '#/components/parameters/identityIDParameter' + delete: + description: Delete an identity and any resources associated with it. + security: + - oauth2Authentication: [] + responses: + '202': + $ref: 'https://raw.githubusercontent.com/unikorn-cloud/core/main/pkg/openapi/common.spec.yaml#/components/responses/acceptedResponse' + '400': + $ref: 'https://raw.githubusercontent.com/unikorn-cloud/core/main/pkg/openapi/common.spec.yaml#/components/responses/badRequestResponse' + '401': + $ref: 'https://raw.githubusercontent.com/unikorn-cloud/core/main/pkg/openapi/common.spec.yaml#/components/responses/unauthorizedResponse' + '403': + $ref: 'https://raw.githubusercontent.com/unikorn-cloud/core/main/pkg/openapi/common.spec.yaml#/components/responses/forbiddenResponse' + '404': + $ref: 'https://raw.githubusercontent.com/unikorn-cloud/core/main/pkg/openapi/common.spec.yaml#/components/responses/notFoundResponse' + '500': + $ref: 'https://raw.githubusercontent.com/unikorn-cloud/core/main/pkg/openapi/common.spec.yaml#/components/responses/internalServerErrorResponse' /api/v1/organizations/{organizationID}/projects/{projectID}/identities/{identityID}/physicalNetworks: description: |- Manages physical networks. Physical networks are networks that may be required for