Skip to content

Commit

Permalink
Remove decrypted instance endpoint (#1003)
Browse files Browse the repository at this point in the history
* chore: remove endpoint which returns a decrypted instance

* chore: strip sensitive parameter values

* chore: imports

* chore: fix test

* chore: remove test

* chore: use "***" to hide sensitive value
  • Loading branch information
tonsV2 authored Feb 13, 2025
1 parent 2d439e7 commit 9e56815
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 94 deletions.
6 changes: 3 additions & 3 deletions cmd/serve/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func run() (err error) {

stackHandler := stack.NewHandler(stackService)

instanceHandler, err := newInstanceHandler(groupService, instanceService)
instanceHandler, err := newInstanceHandler(stackService, groupService, instanceService)
if err != nil {
return err
}
Expand Down Expand Up @@ -478,13 +478,13 @@ func newRabbitMQ() (rabbitMQConfig, error) {
}, nil
}

func newInstanceHandler(groupService *group.Service, instanceService *instance.Service) (instance.Handler, error) {
func newInstanceHandler(stackService stack.Service, groupService *group.Service, instanceService *instance.Service) (instance.Handler, error) {
defaultTTL, err := requireEnvAsUint("DEFAULT_TTL")
if err != nil {
return instance.Handler{}, err
}

return instance.NewHandler(groupService, instanceService, defaultTTL), nil
return instance.NewHandler(stackService, groupService, instanceService, defaultTTL), nil
}

func newDatabaseHandler(ctx context.Context, logger *slog.Logger, db *gorm.DB, groupService *group.Service, instanceService *instance.Service, stackService stack.Service) (database.Handler, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/instance/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type _ struct {
Selector string `json:"selector"`
}

// swagger:parameters deleteInstance findById findByIdDecrypted saveInstance pauseInstance resumeInstance resetInstance findDeploymentById deployDeployment deleteDeployment status instanceWithDetails instanceWithDecryptedDetails filestoreBackup
// swagger:parameters deleteInstance findById findByIdDecrypted saveInstance pauseInstance resumeInstance resetInstance findDeploymentById deployDeployment deleteDeployment status instanceWithDetails filestoreBackup
type _ struct {
// in: path
// required: true
Expand Down
112 changes: 66 additions & 46 deletions pkg/instance/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,26 @@ import (
"io"
"net/http"

"github.com/dhis2-sre/im-manager/pkg/stack"

"github.com/dhis2-sre/im-manager/internal/errdef"

"github.com/dhis2-sre/im-manager/internal/handler"
"github.com/dhis2-sre/im-manager/pkg/model"
"github.com/gin-gonic/gin"
)

func NewHandler(groupService groupServiceHandler, instanceService *Service, defaultTTL uint) Handler {
func NewHandler(stackService stack.Service, groupService groupServiceHandler, instanceService *Service, defaultTTL uint) Handler {
return Handler{
stackService: stackService,
groupService: groupService,
instanceService: instanceService,
defaultTTL: defaultTTL,
}
}

type Handler struct {
stackService stack.Service
groupService groupServiceHandler
instanceService *Service
defaultTTL uint
Expand Down Expand Up @@ -91,9 +95,40 @@ func (h Handler) DeployDeployment(c *gin.Context) {
return
}

err = h.stripDeploymentSensitiveParameterValues(deployment)
if err != nil {
_ = c.Error(err)
return
}

c.JSON(http.StatusOK, deployment)
}

func (h Handler) stripDeploymentSensitiveParameterValues(deployment *model.Deployment) error {
for _, instance := range deployment.Instances {
err := h.stripInstanceSensitiveParameterValues(instance)
if err != nil {
return err
}
}
return nil
}

func (h Handler) stripInstanceSensitiveParameterValues(instance *model.DeploymentInstance) error {
stack, err := h.stackService.Find(instance.StackName)
if err != nil {
return err
}

for index, parameter := range instance.Parameters {
if stack.Parameters[parameter.ParameterName].Sensitive {
parameter.Value = "***"
instance.Parameters[index] = parameter
}
}
return nil
}

type SaveDeploymentRequest struct {
Name string `json:"name" binding:"required,dns_rfc1035_label"`
Description string `json:"description"`
Expand Down Expand Up @@ -167,6 +202,12 @@ func (h Handler) SaveDeployment(c *gin.Context) {
return
}

err = h.stripDeploymentSensitiveParameterValues(deployment)
if err != nil {
_ = c.Error(err)
return
}

c.JSON(http.StatusCreated, deployment)
}

Expand Down Expand Up @@ -212,6 +253,12 @@ func (h Handler) FindDeploymentById(c *gin.Context) {
return
}

err = h.stripDeploymentSensitiveParameterValues(deployment)
if err != nil {
_ = c.Error(err)
return
}

c.JSON(http.StatusOK, deployment)
}

Expand Down Expand Up @@ -285,6 +332,12 @@ func (h Handler) SaveInstance(c *gin.Context) {
return
}

err = h.stripInstanceSensitiveParameterValues(instance)
if err != nil {
_ = c.Error(err)
return
}

c.JSON(http.StatusCreated, instance)
}

Expand Down Expand Up @@ -375,56 +428,12 @@ func (h Handler) InstanceWithDetails(c *gin.Context) {
return
}

c.JSON(http.StatusOK, instance)
}

// InstanceWithDecryptedDetails instance
func (h Handler) InstanceWithDecryptedDetails(c *gin.Context) {
// swagger:route PUT /instances/{id}/decrypted-details instanceWithDecryptedDetails
//
// Instance with decrypted details
//
// Returns the details of an instance including decrypted parameters
//
// Security:
// oauth2:
//
// responses:
// 202:
// 401: Error
// 403: Error
// 404: Error
// 415: Error
id, ok := handler.GetPathParameter(c, "id")
if !ok {
return
}

ctx := c.Request.Context()
user, err := handler.GetUserFromContext(ctx)
if err != nil {
_ = c.Error(err)
return
}

instance, err := h.instanceService.FindDecryptedDeploymentInstanceById(ctx, id)
if err != nil {
_ = c.Error(err)
return
}

deployment, err := h.instanceService.FindDeploymentById(ctx, instance.DeploymentID)
err = h.stripInstanceSensitiveParameterValues(instance)
if err != nil {
_ = c.Error(err)
return
}

canWrite := handler.CanWriteDeployment(user, deployment)
if !canWrite {
_ = c.AbortWithError(http.StatusUnauthorized, fmt.Errorf("write access denied"))
return
}

c.JSON(http.StatusOK, instance)
}

Expand Down Expand Up @@ -772,6 +781,17 @@ func (h Handler) FindDeployments(c *gin.Context) {
return
}

for i, group := range groupsWithDeployments {
for j, deployment := range group.Deployments {
err := h.stripDeploymentSensitiveParameterValues(deployment)
if err != nil {
_ = c.Error(err)
return
}
groupsWithDeployments[i].Deployments[j] = deployment
}
}

c.JSON(http.StatusOK, groupsWithDeployments)
}

Expand Down
19 changes: 1 addition & 18 deletions pkg/instance/instance_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func TestInstanceHandler(t *testing.T) {
}
client := inttest.SetupHTTPServer(t, func(engine *gin.Engine) {
var twoDayTTL uint = 172800
instanceHandler := instance.NewHandler(groupService, instanceService, twoDayTTL)
instanceHandler := instance.NewHandler(stackService, groupService, instanceService, twoDayTTL)
instance.Routes(engine, authenticator, instanceHandler)

databaseHandler := database.NewHandler(logger, databaseService, groupService, instanceService, stackService)
Expand Down Expand Up @@ -217,23 +217,6 @@ func TestInstanceHandler(t *testing.T) {
assert.NotEqual(t, parameters["REPLICA_COUNT"], "1")
}

t.Log("Get deployment instance with decrypted details")
path = fmt.Sprintf("/instances/%d/decrypted-details", deploymentInstance.ID)
var decryptedInstance model.DeploymentInstance
client.GetJSON(t, path, &decryptedInstance, inttest.WithAuthToken("sometoken"))
assert.Equal(t, deploymentInstance.ID, decryptedInstance.ID)
assert.Equal(t, "group-name", decryptedInstance.GroupName)
assert.Equal(t, "whoami-go", decryptedInstance.StackName)
assert.Len(t, decryptedInstance.Parameters, 5)
expectedParameters := model.DeploymentInstanceParameters{
"CHART_VERSION": {0, "", "", "0.9.0"},
"IMAGE_PULL_POLICY": {0, "", "", "IfNotPresent"},
"IMAGE_REPOSITORY": {0, "", "", "whoami-go"},
"IMAGE_TAG": {0, "", "", "0.6.0"},
"REPLICA_COUNT": {0, "", "", "1"},
}
assert.EqualExportedValues(t, expectedParameters, decryptedInstance.Parameters)

t.Log("Deploy deployment")
path = fmt.Sprintf("/deployments/%d/deploy", deployment.ID)
client.Do(t, http.MethodPost, path, nil, http.StatusOK, inttest.WithAuthToken("sometoken"))
Expand Down
1 change: 0 additions & 1 deletion pkg/instance/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ func Routes(r *gin.Engine, authenticator gin.HandlerFunc, handler Handler) {
tokenAuthenticationRouter.GET("/instances/:id/logs", handler.Logs)
tokenAuthenticationRouter.GET("/instances/:id/status", handler.Status)
tokenAuthenticationRouter.GET("/instances/:id/details", handler.InstanceWithDetails)
tokenAuthenticationRouter.GET("/instances/:id/decrypted-details", handler.InstanceWithDecryptedDetails)

tokenAuthenticationRouter.POST("/deployments", handler.SaveDeployment)
tokenAuthenticationRouter.GET("/deployments", handler.FindDeployments)
Expand Down
25 changes: 0 additions & 25 deletions swagger/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1368,31 +1368,6 @@ paths:
"200":
$ref: '#/responses/Response'
summary: Health status
/instances/{id}/decrypted-details:
put:
description: Returns the details of an instance including decrypted parameters
operationId: instanceWithDecryptedDetails
parameters:
- format: uint64
in: path
name: id
required: true
type: integer
x-go-name: ID
responses:
"202":
description: ""
"401":
$ref: '#/responses/Error'
"403":
$ref: '#/responses/Error'
"404":
$ref: '#/responses/Error'
"415":
$ref: '#/responses/Error'
security:
- oauth2: []
summary: Instance with decrypted details
/instances/{id}/details:
put:
description: Returns the details of an instance including parameters
Expand Down

0 comments on commit 9e56815

Please sign in to comment.