fix: template: enforce bounds of template max_ttl (#3662)

This PR makes the following changes:

- enforces lower and upper limits on template `max_ttl_ms`
- adds a migration to enforce 7-day cap on `max_ttl`
- allows setting template `max_ttl` to 0
- updates template edit CLI help to be clearer
This commit is contained in:
Cian Johnston
2022-08-24 15:45:14 +01:00
committed by GitHub
parent 343d1184b2
commit eba753ba87
9 changed files with 207 additions and 25 deletions

View File

@ -108,6 +108,64 @@ func TestPostTemplateByOrganization(t *testing.T) {
require.Equal(t, http.StatusConflict, apiErr.StatusCode())
})
t.Run("MaxTTLTooLow", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
_, err := client.CreateTemplate(ctx, user.OrganizationID, codersdk.CreateTemplateRequest{
Name: "testing",
VersionID: version.ID,
MaxTTLMillis: ptr.Ref(int64(-1)),
})
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
require.Contains(t, err.Error(), "max_ttl_ms: Must be a positive integer")
})
t.Run("MaxTTLTooHigh", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
_, err := client.CreateTemplate(ctx, user.OrganizationID, codersdk.CreateTemplateRequest{
Name: "testing",
VersionID: version.ID,
MaxTTLMillis: ptr.Ref(365 * 24 * time.Hour.Milliseconds()),
})
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusBadRequest, apiErr.StatusCode())
require.Contains(t, err.Error(), "max_ttl_ms: Cannot be greater than")
})
t.Run("NoMaxTTL", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
got, err := client.CreateTemplate(ctx, user.OrganizationID, codersdk.CreateTemplateRequest{
Name: "testing",
VersionID: version.ID,
MaxTTLMillis: ptr.Ref(int64(0)),
})
require.NoError(t, err)
require.Zero(t, got.MaxTTLMillis)
})
t.Run("Unauthorized", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
@ -271,6 +329,87 @@ func TestPatchTemplateMeta(t *testing.T) {
assert.Equal(t, req.MinAutostartIntervalMillis, updated.MinAutostartIntervalMillis)
})
t.Run("NoMaxTTL", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) {
ctr.MaxTTLMillis = ptr.Ref(24 * time.Hour.Milliseconds())
})
req := codersdk.UpdateTemplateMeta{
MaxTTLMillis: 0,
}
// We're too fast! Sleep so we can be sure that updatedAt is greater
time.Sleep(time.Millisecond * 5)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
_, err := client.UpdateTemplateMeta(ctx, template.ID, req)
require.NoError(t, err)
// Extra paranoid: did it _really_ happen?
updated, err := client.Template(ctx, template.ID)
require.NoError(t, err)
assert.Greater(t, updated.UpdatedAt, template.UpdatedAt)
assert.Equal(t, req.MaxTTLMillis, updated.MaxTTLMillis)
})
t.Run("MaxTTLTooLow", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) {
ctr.MaxTTLMillis = ptr.Ref(24 * time.Hour.Milliseconds())
})
req := codersdk.UpdateTemplateMeta{
MaxTTLMillis: -1,
}
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
_, err := client.UpdateTemplateMeta(ctx, template.ID, req)
require.ErrorContains(t, err, "max_ttl_ms: Must be a positive integer")
// Ensure no update occurred
updated, err := client.Template(ctx, template.ID)
require.NoError(t, err)
assert.Equal(t, updated.UpdatedAt, template.UpdatedAt)
assert.Equal(t, updated.MaxTTLMillis, template.MaxTTLMillis)
})
t.Run("MaxTTLTooHigh", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) {
ctr.MaxTTLMillis = ptr.Ref(24 * time.Hour.Milliseconds())
})
req := codersdk.UpdateTemplateMeta{
MaxTTLMillis: 365 * 24 * time.Hour.Milliseconds(),
}
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
_, err := client.UpdateTemplateMeta(ctx, template.ID, req)
require.ErrorContains(t, err, "max_ttl_ms: Cannot be greater than")
// Ensure no update occurred
updated, err := client.Template(ctx, template.ID)
require.NoError(t, err)
assert.Equal(t, updated.UpdatedAt, template.UpdatedAt)
assert.Equal(t, updated.MaxTTLMillis, template.MaxTTLMillis)
})
t.Run("NotModified", func(t *testing.T) {
t.Parallel()