mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
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:
@ -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()
|
||||
|
||||
|
Reference in New Issue
Block a user