mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-20 20:39:08 +02:00
[management] Refuse a usage limit a one-off setup key cannot honour (#7220)
refuse creating one-off keys without limits set to 1
This commit is contained in:
@@ -64,6 +64,19 @@ func (h *handler) createSetupKey(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A one-off key can be used once, and GenerateSetupKey pins its usage limit
|
||||||
|
// at 1 whatever the request says. Silently overriding a caller that asked
|
||||||
|
// for a different number leaves them holding a key that does not do what
|
||||||
|
// they configured, and no way to find out except by using it. Only values
|
||||||
|
// above 1 are refused: usage_limit is a required field with no null, so 0
|
||||||
|
// cannot be told apart from a caller that has nothing to say about it.
|
||||||
|
if types.SetupKeyType(req.Type) == types.SetupKeyOneOff && req.UsageLimit > 1 {
|
||||||
|
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument,
|
||||||
|
"usage_limit %d is not valid for a one-off setup key, which can be used once; use type reusable for a key that can be used more than once",
|
||||||
|
req.UsageLimit), w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
expiresIn := time.Duration(req.ExpiresIn) * time.Second
|
expiresIn := time.Duration(req.ExpiresIn) * time.Second
|
||||||
|
|
||||||
if expiresIn < 0 {
|
if expiresIn < 0 {
|
||||||
|
|||||||
@@ -134,6 +134,40 @@ func TestSetupKeysHandlers(t *testing.T) {
|
|||||||
expectedBody: true,
|
expectedBody: true,
|
||||||
expectedSetupKey: expectedNewKey,
|
expectedSetupKey: expectedNewKey,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// A one-off key is used once. Asking for more used to be accepted
|
||||||
|
// and then quietly reduced to 1.
|
||||||
|
name: "Create One-Off Setup Key With Conflicting Usage Limit",
|
||||||
|
requestType: http.MethodPost,
|
||||||
|
requestPath: "/api/setup-keys",
|
||||||
|
requestBody: bytes.NewBuffer(
|
||||||
|
[]byte(fmt.Sprintf("{\"name\":\"%s\",\"type\":\"one-off\",\"expires_in\":86400,\"usage_limit\":5}", newSetupKeyName))),
|
||||||
|
expectedStatus: http.StatusUnprocessableEntity,
|
||||||
|
expectedBody: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// 0 is what a caller sends when it has nothing to say about the
|
||||||
|
// usage limit, since the field is required and has no null, so it
|
||||||
|
// has to keep working.
|
||||||
|
name: "Create One-Off Setup Key Without Usage Limit",
|
||||||
|
requestType: http.MethodPost,
|
||||||
|
requestPath: "/api/setup-keys",
|
||||||
|
requestBody: bytes.NewBuffer(
|
||||||
|
[]byte(fmt.Sprintf("{\"name\":\"%s\",\"type\":\"one-off\",\"expires_in\":86400,\"usage_limit\":0}", newSetupKeyName))),
|
||||||
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedBody: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Only one-off keys are constrained; a reusable key means what it
|
||||||
|
// says.
|
||||||
|
name: "Create Reusable Setup Key With Usage Limit",
|
||||||
|
requestType: http.MethodPost,
|
||||||
|
requestPath: "/api/setup-keys",
|
||||||
|
requestBody: bytes.NewBuffer(
|
||||||
|
[]byte(fmt.Sprintf("{\"name\":\"%s\",\"type\":\"reusable\",\"expires_in\":86400,\"usage_limit\":5}", newSetupKeyName))),
|
||||||
|
expectedStatus: http.StatusOK,
|
||||||
|
expectedBody: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Update Setup Key",
|
name: "Update Setup Key",
|
||||||
requestType: http.MethodPut,
|
requestType: http.MethodPut,
|
||||||
|
|||||||
@@ -136,7 +136,10 @@ func Test_SetupKeys_Create(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Create Setup Key as on-off with more than one usage",
|
// The key used to be created anyway, with its usage limit quietly
|
||||||
|
// reduced to 1, so the caller was told a key they had not asked for
|
||||||
|
// was what they asked for.
|
||||||
|
name: "Create Setup Key as one-off with more than one usage",
|
||||||
requestType: http.MethodPost,
|
requestType: http.MethodPost,
|
||||||
requestPath: "/api/setup-keys",
|
requestPath: "/api/setup-keys",
|
||||||
requestBody: &api.CreateSetupKeyRequest{
|
requestBody: &api.CreateSetupKeyRequest{
|
||||||
@@ -146,23 +149,7 @@ func Test_SetupKeys_Create(t *testing.T) {
|
|||||||
Type: "one-off",
|
Type: "one-off",
|
||||||
UsageLimit: 3,
|
UsageLimit: 3,
|
||||||
},
|
},
|
||||||
expectedStatus: http.StatusOK,
|
expectedStatus: http.StatusUnprocessableEntity,
|
||||||
expectedResponse: &api.SetupKey{
|
|
||||||
AutoGroups: []string{},
|
|
||||||
Ephemeral: false,
|
|
||||||
Expires: time.Time{},
|
|
||||||
Id: "",
|
|
||||||
Key: "",
|
|
||||||
LastUsed: time.Time{},
|
|
||||||
Name: testing_tools.NewKeyName,
|
|
||||||
Revoked: false,
|
|
||||||
State: "valid",
|
|
||||||
Type: "one-off",
|
|
||||||
UpdatedAt: time.Now(),
|
|
||||||
UsageLimit: 1,
|
|
||||||
UsedTimes: 0,
|
|
||||||
Valid: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Create Setup Key with expiration in the past",
|
name: "Create Setup Key with expiration in the past",
|
||||||
|
|||||||
Reference in New Issue
Block a user